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 }