comparison fluid-mnf/serial.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 6ff231195905
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 * Serial/UART driver
8 *
9 * $Id: serial.c 1.23 Fri, 18 Oct 2002 08:53:12 +0200 mmj $
10 *
11 ******************************************************************************/
12
13 #include "fluid.h"
14 #include "serial.h"
15 #include "trace.h"
16
17 #include <assert.h>
18 #include <stdio.h>
19
20 #if defined(MSC) || defined(BCC)
21 #include <windows.h> // for Sleep()
22 #else
23 // #error Not compiling for MSC or BCC?
24 #endif
25
26
27 extern void target_recv_push(char *buf, int size);
28
29
30 /******************************************************************************
31 * OS Independent
32 ******************************************************************************/
33
34 static void serial_listener(void);
35
36 #if (OS == WIN32)
37
38 /******************************************************************************
39 * Win32 Driver
40 ******************************************************************************/
41
42 #include <windows.h>
43
44 static HANDLE hCom;
45 static HANDLE thread_handle = NULL;
46 static DWORD thread_id;
47 static OVERLAPPED read_overlapped;
48 static OVERLAPPED write_overlapped;
49 static DCB dcb;
50
51 const char PORT_NAME_PRE[] = "COM";
52 // A special syntax is required when accessing com ports greater than 9, e.g., "\\.\COM10"
53 const char PORT_NAME_PREFIX[] = "\\\\.\\COM";
54
55 int serial_init(int uart, int bps, char *flowcontrol)
56 {
57 int error;
58 COMMTIMEOUTS timeouts;
59 char pc_comport[32];
60
61 sprintf(pc_comport, "%s%d", PORT_NAME_PREFIX, uart);
62
63 hCom = CreateFile(pc_comport,
64 GENERIC_READ | GENERIC_WRITE,
65 0, // comm devices must be opened w/exclusive-access
66 NULL, // no security attributes
67 OPEN_EXISTING, // comm devices must use OPEN_EXISTING
68 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
69 NULL // hTemplate must be NULL for comm devices
70 );
71 if (hCom == INVALID_HANDLE_VALUE)
72 return E_OS + E_UART_INIT;
73
74 // We will build on the current configuration, and skip setting the size
75 // of the input and output buffers with SetupComm.
76 if (!GetCommState(hCom, &dcb))
77 return E_OS + E_UART_INIT;
78
79 dcb.fAbortOnError = FALSE; // Hmm? (Dont't remember exactly what this is)
80 dcb.ByteSize = 8; // Data size, xmit, and rcv
81 dcb.Parity = NOPARITY; // No parity bit
82 dcb.StopBits = ONESTOPBIT; // One stop bit
83 dcb.fOutxCtsFlow = 0; // Disable CTS HW handshaking!
84 dcb.fOutxDsrFlow = 0; // Disable DSR HW handshaking!
85 dcb.fDsrSensitivity = 0; // Disable DSR HW handshaking!
86
87 // Note the DTR = +12V and RTS = -12V is needed to power the serial
88 // level converter!
89
90 switch (flowcontrol[0]) {
91 case 'n': dcb.fDtrControl = DTR_CONTROL_DISABLE; break;
92 case 'h': dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; break;
93 case 'p':
94 default:
95 dcb.fDtrControl = DTR_CONTROL_ENABLE; break;
96 }
97 switch (flowcontrol[1]) {
98 case 'p': dcb.fRtsControl = RTS_CONTROL_ENABLE; break;
99 case 'h': dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; break;
100 case 'n':
101 default:
102 dcb.fRtsControl = RTS_CONTROL_DISABLE; break;
103 }
104
105 if (!SetCommState(hCom, &dcb))
106 return E_OS + E_UART_INIT;
107
108 if ((error = serial_baudrate_set(bps)) < 0)
109 return error;
110
111 timeouts.ReadIntervalTimeout = 0;
112 timeouts.ReadTotalTimeoutMultiplier = 0;
113 timeouts.ReadTotalTimeoutConstant = 0;
114 timeouts.WriteTotalTimeoutMultiplier = 0;
115 timeouts.WriteTotalTimeoutConstant = 0;
116
117 assert(SetCommTimeouts (hCom, &timeouts));
118 assert(SetCommMask (hCom, EV_RXCHAR));
119 //assert(SetupComm (hCom, INPUT_BUFFER_SIZE, OUTPUT_BUFFER_SIZE));
120
121 sprintf(pc_comport, "read%s%d", PORT_NAME_PRE, uart);
122 read_overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, pc_comport);
123
124 sprintf(pc_comport, "write%s%d", PORT_NAME_PRE, uart);
125 write_overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, pc_comport);
126
127 thread_handle =
128 CreateThread (NULL,
129 0,
130 (LPTHREAD_START_ROUTINE) serial_listener,
131 NULL,
132 0,
133 &thread_id);
134
135 if (thread_handle == NULL)
136 return E_OS + E_UART_INIT;
137
138 serial_reset();
139
140 return 0;
141 }
142
143 int serial_is_baudrate(int bps)
144 {
145 int i;
146 const struct rate_s {
147 int bps;
148 int baudrate;
149 } rates[] = {
150 { 9600, 9600 }, { 9, 9600 },
151 { 14400, 14400 }, { 14, 14400 },
152 { 19200, 19200 }, { 19, 19200 },
153 { 38400, 38400 }, { 38, 38400 },
154 { 57600, 57600 }, { 57, 57600 },
155 { 115200, 115200 }, { 115, 115200 },
156 { 203125, 203125 }, { 203, 203125 }, // 13MHz clock
157 { 230400, 230400 }, { 230, 230400 },
158 { 406250, 406250 }, { 406, 406250 }, // 13MHz clock
159 { 460800, 460800 }, { 460, 460800 },
160 { 812500, 812500 }, { 812, 812500 }, // 13MHz clock
161 { 921600, 921600 }, { 921, 921600 },
162 { 0, 0 } // terminator
163 };
164
165 for (i = 0; i < sizeof(rates) / sizeof(struct rate_s) - 1; i++)
166 if (rates[i].bps == bps)
167 break;
168
169 tr(TrTargetDrv, "serial_is_baudrate(%d) %d\n", bps, rates[i].baudrate);
170
171 return rates[i].baudrate;
172 }
173
174 int serial_baudrate_set(int bps)
175 {
176 #if 0
177 if (!GetCommState(hCom, &dcb))
178 return E_OS + E_UART_PARAM;
179 #endif
180
181 bps = serial_is_baudrate(bps);
182 if (bps == 0)
183 return E_OS + E_UART_PARAM;
184
185 /* Replace 812K with 827K. Otherwise, the chip will automatically select 800K. */
186 /* 800K is OK, but we might as well gain the extra 3% speed :-) */
187 if (bps == 812500)
188 dcb.BaudRate = 827586;
189 else
190 dcb.BaudRate = bps;
191
192 if (!SetCommState(hCom, &dcb))
193 return E_OS + E_UART_PARAM;
194
195 return bps;
196 }
197
198 int serial_baudrate_get(void)
199 {
200 return dcb.BaudRate;
201 }
202
203 void serial_exit(void)
204 {
205 DWORD exit_code;
206
207 serial_reset();
208
209 (void) GetExitCodeThread (thread_handle, &exit_code);
210 (void) TerminateThread (thread_handle, exit_code);
211
212 (void) CloseHandle (hCom);
213 (void) CloseHandle (read_overlapped.hEvent);
214 (void) CloseHandle (write_overlapped.hEvent);
215 }
216
217 // Clear buffers and transactions.
218 void serial_reset(void)
219 {
220 PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
221 }
222
223 // Return the number of milli-seconds it takes to transfer <n> bytes.
224 int serial_transfer_time(int size)
225 {
226 return 1000 * 10 * size / serial_baudrate_get();
227 }
228
229
230 /***************************************
231 * Send
232 ***************************************/
233
234 int serial_send(char *buf, int size)
235 {
236 DWORD written;
237
238 ResetEvent(write_overlapped.hEvent); // why?
239
240 if (!WriteFile(hCom, buf, size, &written, &write_overlapped)) {
241 if (GetLastError() == ERROR_IO_PENDING) {
242 if (GetOverlappedResult(hCom, &write_overlapped,
243 &written, TRUE) == FALSE)
244 written = E_OS + E_UART_DRV_SEND;
245 }
246 }
247
248 return written;
249 }
250
251
252 /***************************************
253 * Receive
254 ***************************************/
255
256 void serial_recv_reset(void)
257 {
258 PurgeComm(hCom, PURGE_RXABORT|PURGE_RXCLEAR);
259 }
260
261 static void serial_listener(void)
262 {
263 DWORD event_mask;
264 char buf[64];
265 DWORD size;
266
267 while (1)
268 {
269 // Wait the event signalling characters received.
270 if (WaitCommEvent (hCom, &event_mask, NULL) != TRUE) {
271 main_msg("WaitCommEvent(): error %d\n", GetLastError());
272 return;
273 }
274 tr(TrTargetDrv, "|");
275
276 // Read all characters received in the buffer. Mysteriously, it
277 // does NOT work with a buffer size greater than one!
278 do {
279 if (!ReadFile(hCom, buf, 1, &size, &read_overlapped))
280 {
281 if (GetLastError() == ERROR_IO_PENDING) {
282 GetOverlappedResult(hCom, &read_overlapped, &size, TRUE);
283 }
284 else {
285 main_msg("ReadFile(): error %d\n", GetLastError());
286 serial_recv_reset();
287 break;
288 }
289 }
290 // Push the data to upper layer
291 target_recv_push(buf, size);
292
293 } while (size);
294 }
295 }
296
297
298 /******************************************************************************
299 * Control of Delta cable special outputs
300 ******************************************************************************/
301
302 void serial_rts(char state)
303 {
304 if (state)
305 EscapeCommFunction(hCom, SETRTS);
306 else
307 EscapeCommFunction(hCom, CLRRTS);
308 }
309
310 void serial_dtr(char state)
311 {
312 if (state)
313 EscapeCommFunction(hCom, SETDTR);
314 else
315 EscapeCommFunction(hCom, CLRDTR);
316 }
317
318 void serial_break(char state)
319 {
320 if (state)
321 SetCommBreak(hCom);
322 else
323 ClearCommBreak(hCom);
324 }
325
326 #else // (OS == WIN32)
327
328
329 /******************************************************************************
330 * Unix driver
331 ******************************************************************************/
332
333
334 #endif // (OS == WIN32)