FreeCalypso > hg > freecalypso-reveng
comparison fluid-mnf/target.c @ 311:9cecc930d78f
fluid-mnf: original source from TI,
defenestrated line endings and rearranged directory structure,
but no *.[ch] source file content changes yet
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 29 Feb 2020 05:36:07 +0000 |
parents | |
children | b595ff13547b |
comparison
equal
deleted
inserted
replaced
310:ae39d76d5b7a | 311:9cecc930d78f |
---|---|
1 /****************************************************************************** | |
2 * FLUID (Flash Loader Utility Independent of Device) | |
3 * | |
4 * Copyright Texas Instruments, 2001. | |
5 * Mads Meisner-Jensen, mmj@ti.com. | |
6 * | |
7 * Target Connection and Control | |
8 * | |
9 * $Id: target.c 1.20 Mon, 21 Oct 2002 18:39:13 +0200 mmj $ | |
10 * | |
11 ******************************************************************************/ | |
12 | |
13 #include "serial.h" | |
14 #include "fluid.h" | |
15 #include "trace.h" | |
16 | |
17 #include <stdio.h> | |
18 | |
19 #if defined(MSC) || defined(BCC) | |
20 #include "windows.h" | |
21 #endif | |
22 | |
23 int target_trace(unsigned char ch); | |
24 | |
25 | |
26 /****************************************************************************** | |
27 * Globals | |
28 ******************************************************************************/ | |
29 | |
30 HANDLE hEvent; | |
31 | |
32 #define RECVBUF_SIZE (65536) | |
33 | |
34 static unsigned char recvbuf[RECVBUF_SIZE]; | |
35 static int recvbuf_size_target; | |
36 static int recvbuf_put; | |
37 static int recvbuf_get; | |
38 | |
39 #define recvbuf_size() (recvbuf_put - recvbuf_get + \ | |
40 ((recvbuf_put - recvbuf_get) < 0 ? RECVBUF_SIZE : 0)) | |
41 | |
42 | |
43 /****************************************************************************** | |
44 * Error Functions | |
45 ******************************************************************************/ | |
46 | |
47 void error_proto(char ch, char chx) | |
48 { | |
49 char chd, chxd; | |
50 | |
51 chd = (' ' <= ch && ch < 127 ? ch : '.'); | |
52 chxd = (' ' <= chx && chx < 127 ? chx : '.'); | |
53 | |
54 flowf(NORMAL, "(protocol error: got '%c' 0x%02X, expected '%c' 0x%02X)\n", | |
55 chd, ch, chxd, chx); | |
56 | |
57 main_fatal(E_PROTO_ERROR); | |
58 } | |
59 | |
60 | |
61 /****************************************************************************** | |
62 * Target Dependencies | |
63 ******************************************************************************/ | |
64 | |
65 // <clk> is the target's clock frequency | |
66 int target_uart_baudrate_divider_get(int clk, int bps) | |
67 { | |
68 int divider = clk / bps / 16; | |
69 | |
70 tr(TrTargetDrv, "target_uart_baudrate_divider_get(%d, %d) %d\n", | |
71 clk, bps, divider); | |
72 | |
73 return divider; | |
74 } | |
75 | |
76 | |
77 /****************************************************************************** | |
78 * Target Init and Send | |
79 ******************************************************************************/ | |
80 | |
81 static int target_trace_timer; | |
82 | |
83 void target_recv_reset(void) | |
84 { | |
85 tr(TrTargetDrv, "recv_reset()\n"); | |
86 | |
87 recvbuf_get = recvbuf_put = 0; | |
88 | |
89 memset(recvbuf, 0x77, RECVBUF_SIZE); | |
90 | |
91 serial_recv_reset(); | |
92 } | |
93 | |
94 int target_driver_init(int uart, int baudrate, char *flowcontrol) | |
95 { | |
96 int error; | |
97 | |
98 target_recv_reset(); | |
99 | |
100 hEvent = CreateEvent(NULL, // lpEventAttributes | |
101 FALSE, // bManualReset (OFF) | |
102 FALSE, // bInitialstate (OFF) | |
103 NULL); // lpName | |
104 | |
105 if (hEvent == NULL) { | |
106 error = E_DRIVER_INIT + E_OS; | |
107 } | |
108 else { | |
109 error = serial_init(uart, baudrate, flowcontrol); | |
110 } | |
111 return error; | |
112 } | |
113 | |
114 int target_driver_baudrate(int baudrate) | |
115 { | |
116 return serial_baudrate_set(baudrate); | |
117 } | |
118 | |
119 int target_putchar(char ch) | |
120 { | |
121 char trch; | |
122 | |
123 trch = (ch < ' ' || ch == 127 ? '.' : ch); | |
124 tr(TrPutChar, "s '%c'/0x%02X\n", trch, ch & 0xFF); | |
125 | |
126 return serial_send(&ch, 1); | |
127 } | |
128 | |
129 int target_send(char *buf, int size) | |
130 { | |
131 tr(TrPutChar, "s (%d bytes)\n", size); | |
132 | |
133 return serial_send(buf, size); | |
134 } | |
135 | |
136 | |
137 /****************************************************************************** | |
138 * Target Wait and Receive | |
139 ******************************************************************************/ | |
140 | |
141 void target_recv_signal(void) | |
142 { | |
143 // Notify waiting thread when we have received the requested number of | |
144 // bytes. Note that we use auto-resetting events, so you have to be VERY | |
145 // careful to wait for the exact number of bytes you want. Otherwise you | |
146 // might trigger the event twice in quick succession and this will | |
147 // result in the next call of target_wait()'s to return immediately | |
148 // without waiting! | |
149 | |
150 if (recvbuf_size() >= recvbuf_size_target && recvbuf_size_target > 0) { | |
151 // When we have triggered the event, disable further triggering | |
152 // until next call of target_wait() | |
153 recvbuf_size_target = 0; | |
154 tr(TrDriverGet, "!"); | |
155 if (SetEvent(hEvent) == 0) | |
156 fprintf(stderr, "FATAL: recv_push_tm(): SetEvent() failed with Win32 error %d\n", GetLastError()); | |
157 } | |
158 } | |
159 | |
160 void target_recv_push(char *buf, int size) | |
161 { | |
162 if (size == 0) { | |
163 tr(TrDriverGet, " G?"); | |
164 return; | |
165 } | |
166 | |
167 while (size--) { | |
168 recvbuf[recvbuf_put++] = *buf++; | |
169 recvbuf_put &= (RECVBUF_SIZE - 1); | |
170 } | |
171 tr(TrDriverGet, " G%d", recvbuf_size()); | |
172 | |
173 target_recv_signal(); | |
174 } | |
175 | |
176 // Wait maximum <timeout> milli-seconds for <size> bytes to arrive. If | |
177 // <size> is zero, we unconditionally wait for <time_ms> milli-seconds | |
178 // (quite simply a delay). The transfer time is automatically added to the | |
179 // total waiting time. | |
180 int target_wait(int size, int timeout) | |
181 { | |
182 int result = 0; | |
183 | |
184 tr(TrTargetWait, "target_wait(%d, %d)\n", size, timeout); | |
185 | |
186 if (size > 0) | |
187 timeout += serial_transfer_time(size); | |
188 | |
189 recvbuf_size_target = size; | |
190 target_trace_timer = timeout; | |
191 | |
192 if (size == 0) { | |
193 Sleep(timeout); | |
194 } | |
195 else { | |
196 target_recv_signal(); | |
197 | |
198 switch (WaitForSingleObject(hEvent, timeout)) { | |
199 case WAIT_OBJECT_0: result = recvbuf_size(); break; | |
200 case WAIT_TIMEOUT: result = E_RECV_TIMEOUT; break; | |
201 default: result = E_OS + E_DRIVER_WAIT; break; | |
202 } | |
203 } | |
204 recvbuf_size_target = 0; | |
205 | |
206 return result; | |
207 } | |
208 | |
209 int target_recv(void *outbuf, int size) | |
210 { | |
211 int i, bufsize; | |
212 char *buf = (char *) outbuf; | |
213 | |
214 bufsize = recvbuf_size(); | |
215 if (bufsize < size) | |
216 size = bufsize; | |
217 | |
218 for (i = 0; i < size; i++) { | |
219 *buf++ = recvbuf[recvbuf_get++]; | |
220 recvbuf_get &= (RECVBUF_SIZE - 1); | |
221 } | |
222 | |
223 tr(TrGetChar, "r (%d bytes)\n", size); | |
224 return size; | |
225 } | |
226 | |
227 int target_getchar(void) | |
228 { | |
229 int trace_in_progress; | |
230 char ch; | |
231 | |
232 do { | |
233 ch = recvbuf[recvbuf_get++]; | |
234 recvbuf_get &= (RECVBUF_SIZE - 1); | |
235 tr(TrGetChar, "r '%c' %02X\n", | |
236 (ch >= ' ' && ch <= 126 ? ch : '.'), ch & 0xFF); | |
237 | |
238 if ((trace_in_progress = target_trace((char) ch)) != 0) { | |
239 if (target_wait(1, target_trace_timer) < 1) | |
240 main_fatal(E_RECV_TIMEOUT); | |
241 } | |
242 } while (trace_in_progress); | |
243 | |
244 return (ch & 0xFF); | |
245 } | |
246 | |
247 int target_expect_char(char ch, int timeout) | |
248 { | |
249 char mych; | |
250 | |
251 if (target_wait(1, timeout) < 1) { | |
252 flowf(NORMAL, "(Waited for '%c' 0x%02X)\n", ch, ch); | |
253 main_fatal(E_RECV_TIMEOUT); | |
254 } | |
255 | |
256 if ((mych = target_getchar()) != ch) | |
257 error_proto(mych, ch); | |
258 | |
259 return ch; | |
260 } | |
261 | |
262 | |
263 /****************************************************************************** | |
264 * Target Buffer Put | |
265 ******************************************************************************/ | |
266 | |
267 int buf_put1(char *buf, unsigned char data) | |
268 { | |
269 tr(TrPutChar, "buf_put1(0x%02X) '%c'\n", data, data); | |
270 | |
271 *buf = (data ) & 0xFF; | |
272 return 1; | |
273 } | |
274 | |
275 int buf_put2(char *buf, unsigned short data) | |
276 { | |
277 tr(TrPutChar, "buf_put2(0x%04X)\n", data); | |
278 | |
279 *buf++ = (data ) & 0xFF; | |
280 *buf = (data >> 8) & 0xFF; | |
281 return 2; | |
282 } | |
283 | |
284 int buf_put4(char *buf, unsigned int data) | |
285 { | |
286 tr(TrPutChar, "buf_put4(0x%08X)\n", data); | |
287 | |
288 *buf++ = (data ) & 0xFF; | |
289 *buf++ = (data >> 8) & 0xFF; | |
290 *buf++ = (data >> 16) & 0xFF; | |
291 *buf = (data >> 24) & 0xFF; | |
292 return 4; | |
293 } | |
294 | |
295 // Put 2-byte integer in network order | |
296 int buf_put2no(char *buf, unsigned short data) | |
297 { | |
298 tr(TrPutChar, "buf_put2no(0x%04X)\n", data); | |
299 | |
300 *buf++ = (data >> 8) & 0xFF; | |
301 *buf = (data ) & 0xFF; | |
302 return 2; | |
303 } | |
304 | |
305 // Put 4-byte integer in network order | |
306 int buf_put4no(char *buf, unsigned int data) | |
307 { | |
308 tr(TrPutChar, "buf_put4no(0x%08X)\n", data); | |
309 | |
310 *buf++ = (data >> 24) & 0xFF; | |
311 *buf++ = (data >> 16) & 0xFF; | |
312 *buf++ = (data >> 8) & 0xFF; | |
313 *buf = (data ) & 0xFF; | |
314 return 4; | |
315 } | |
316 | |
317 | |
318 /****************************************************************************** | |
319 * Special Target Control Functions | |
320 ******************************************************************************/ | |
321 | |
322 // Control target power. Works *only* with special cable! If <state> is | |
323 // non-zero, the power is on. Otherwise, it is off. | |
324 void target_power(char state) | |
325 { | |
326 if (arg_uart_level_convert) | |
327 return; | |
328 | |
329 if (state) { | |
330 serial_rts(0); | |
331 } | |
332 else { | |
333 serial_rts(1); | |
334 serial_dtr(1); | |
335 serial_break(1); | |
336 serial_break(0); | |
337 } | |
338 } | |
339 | |
340 // Control target reset line. Works *only* with special cable! If <state> | |
341 // is non-zero, the reset line is asserted. Otherwise, it is negated. | |
342 void target_reset(char state) | |
343 { | |
344 if (arg_uart_level_convert) | |
345 return; | |
346 | |
347 if (state) { | |
348 serial_rts(1); | |
349 serial_dtr(0); | |
350 serial_rts(0); | |
351 serial_break(0); | |
352 } | |
353 else { | |
354 serial_break(1); | |
355 serial_rts(1); | |
356 serial_dtr(1); | |
357 serial_rts(0); | |
358 } | |
359 } | |
360 | |
361 | |
362 /****************************************************************************** | |
363 * Target Trace/Debug Functions | |
364 ******************************************************************************/ | |
365 | |
366 static int target_trace_enable_flag = 0; | |
367 | |
368 int target_trace_enable(int flag) | |
369 { | |
370 int old = target_trace_enable_flag; | |
371 | |
372 target_trace_enable_flag = flag; | |
373 | |
374 if (arg_target_trace_enable) | |
375 flowf(DEBUG, "{%s}", (flag ? "enable" : "disable")); | |
376 | |
377 return old; | |
378 } | |
379 | |
380 // Interpret and display target trace message. Return zero if <ch> was not | |
381 // intercepted. Otherwise, if it was intercepted, return non-zero. | |
382 int target_trace(unsigned char ch) | |
383 { | |
384 int i; | |
385 unsigned int number = 0; | |
386 char buf[80], *p; | |
387 | |
388 // If target is not supposed to transmit any tracing at this point in | |
389 // the state machine(s), the flag will be zero and thus we return. | |
390 if (target_trace_enable_flag && ch == '$') { | |
391 if (target_wait(1, 100) < 0) | |
392 main_fatal(E_RECV_TIMEOUT); | |
393 ch = target_getchar(); | |
394 switch (ch) { | |
395 case 'S': | |
396 p = buf; | |
397 while (ch != 0) { | |
398 if (target_wait(1, 100) < 0) | |
399 main_fatal(E_RECV_TIMEOUT); | |
400 ch = target_getchar(); | |
401 *p++ = ch; | |
402 } | |
403 *p = 0; | |
404 if (arg_target_trace_enable) | |
405 printf("{'%s'} ", buf); | |
406 break; | |
407 case 'N': | |
408 for (i = 0; i < 4; i++) { | |
409 if (target_wait(1, 100) < 0) | |
410 main_fatal(E_RECV_TIMEOUT); | |
411 ch = target_getchar(); | |
412 number = (number >> 8) + (ch << 24); | |
413 } | |
414 if (arg_target_trace_enable) | |
415 printf("{0x%X/%dd} ", number, number); | |
416 break; | |
417 default: | |
418 fprintf(stderr, "WARNING: Bad TargetTrace char received! (0x%X)\n", | |
419 ch & 0xFF); | |
420 break; | |
421 } | |
422 return 1; | |
423 } | |
424 return 0; | |
425 } |