FreeCalypso > hg > freecalypso-reveng
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) |