diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fluid-mnf/serial.c	Sat Feb 29 05:36:07 2020 +0000
@@ -0,0 +1,334 @@
+/******************************************************************************
+ * FLUID (Flash Loader Utility Independent of Device)
+ *
+ * Copyright Texas Instruments, 2001.
+ * Mads Meisner-Jensen, mmj@ti.com.
+ *
+ * Serial/UART driver
+ *
+ * $Id: serial.c 1.23 Fri, 18 Oct 2002 08:53:12 +0200 mmj $
+ *
+ ******************************************************************************/
+
+#include "fluid.h"
+#include "serial.h"
+#include "trace.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#if defined(MSC) || defined(BCC)
+  #include <windows.h> // for Sleep()
+#else
+//  #error Not compiling for MSC or BCC?
+#endif
+
+
+extern void target_recv_push(char *buf, int size);
+
+
+/******************************************************************************
+ * OS Independent
+ ******************************************************************************/
+
+static void serial_listener(void);
+
+#if (OS == WIN32)
+
+/******************************************************************************
+ * Win32 Driver
+ ******************************************************************************/
+
+#include <windows.h>
+
+static HANDLE     hCom;
+static HANDLE     thread_handle = NULL;
+static DWORD      thread_id;
+static OVERLAPPED read_overlapped;
+static OVERLAPPED write_overlapped;
+static DCB        dcb;
+
+const char PORT_NAME_PRE[] = "COM";
+// A special syntax is required when accessing com ports greater than 9, e.g., "\\.\COM10"
+const char PORT_NAME_PREFIX[] = "\\\\.\\COM";
+
+int serial_init(int uart, int bps, char *flowcontrol)
+{
+    int error;
+    COMMTIMEOUTS timeouts;
+    char pc_comport[32];
+
+    sprintf(pc_comport, "%s%d", PORT_NAME_PREFIX, uart);
+
+    hCom = CreateFile(pc_comport,
+                      GENERIC_READ | GENERIC_WRITE,
+                      0,    // comm devices must be opened w/exclusive-access
+                      NULL, // no security attributes
+                      OPEN_EXISTING, // comm devices must use OPEN_EXISTING
+                      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+                      NULL  // hTemplate must be NULL for comm devices
+        );
+    if (hCom == INVALID_HANDLE_VALUE)
+        return E_OS + E_UART_INIT;
+
+    // We will build on the current configuration, and skip setting the size
+    // of the input and output buffers with SetupComm.
+    if (!GetCommState(hCom, &dcb))
+        return E_OS + E_UART_INIT;
+
+    dcb.fAbortOnError = FALSE; // Hmm? (Dont't remember exactly what this is)
+    dcb.ByteSize = 8;          // Data size, xmit, and rcv
+    dcb.Parity = NOPARITY;     // No parity bit
+    dcb.StopBits = ONESTOPBIT; // One stop bit
+    dcb.fOutxCtsFlow = 0;      // Disable CTS HW handshaking!
+    dcb.fOutxDsrFlow = 0;      // Disable DSR HW handshaking!
+    dcb.fDsrSensitivity = 0;   // Disable DSR HW handshaking!
+
+    // Note the DTR = +12V and RTS = -12V is needed to power the serial
+    // level converter!
+
+    switch (flowcontrol[0]) {
+    case 'n': dcb.fDtrControl = DTR_CONTROL_DISABLE; break;
+    case 'h': dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; break;
+    case 'p':
+    default:
+        dcb.fDtrControl = DTR_CONTROL_ENABLE; break;
+    }
+    switch (flowcontrol[1]) {
+    case 'p': dcb.fRtsControl = RTS_CONTROL_ENABLE; break;
+    case 'h': dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; break;
+    case 'n':
+    default:
+        dcb.fRtsControl = RTS_CONTROL_DISABLE; break;
+    }
+
+    if (!SetCommState(hCom, &dcb))
+        return E_OS + E_UART_INIT;
+
+    if ((error = serial_baudrate_set(bps)) < 0)
+        return error;
+
+    timeouts.ReadIntervalTimeout = 0;
+    timeouts.ReadTotalTimeoutMultiplier = 0;
+    timeouts.ReadTotalTimeoutConstant = 0;
+    timeouts.WriteTotalTimeoutMultiplier = 0;
+    timeouts.WriteTotalTimeoutConstant = 0;
+
+    assert(SetCommTimeouts (hCom, &timeouts));
+    assert(SetCommMask (hCom, EV_RXCHAR));
+    //assert(SetupComm (hCom, INPUT_BUFFER_SIZE, OUTPUT_BUFFER_SIZE));
+
+    sprintf(pc_comport, "read%s%d", PORT_NAME_PRE, uart);
+    read_overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, pc_comport);
+
+    sprintf(pc_comport, "write%s%d", PORT_NAME_PRE, uart);
+    write_overlapped.hEvent = CreateEvent (NULL, TRUE, FALSE, pc_comport);
+
+    thread_handle =
+        CreateThread (NULL,
+                      0,
+                      (LPTHREAD_START_ROUTINE) serial_listener,
+                      NULL,
+                      0,
+                      &thread_id);
+
+    if (thread_handle == NULL)
+        return E_OS + E_UART_INIT;
+
+    serial_reset();
+
+    return 0;
+}
+
+int serial_is_baudrate(int bps)
+{
+    int i;
+    const struct rate_s {
+        int bps;
+        int baudrate;
+    } rates[] = {
+        {   9600,   9600 }, {   9,      9600 },
+        {  14400,  14400 }, {  14,     14400 },
+        {  19200,  19200 }, {  19,     19200 },
+        {  38400,  38400 }, {  38,     38400 },
+        {  57600,  57600 }, {  57,     57600 },
+        { 115200, 115200 }, { 115,    115200 },
+        { 203125, 203125 }, { 203,    203125 }, // 13MHz clock
+        { 230400, 230400 }, { 230,    230400 },
+        { 406250, 406250 }, { 406,    406250 }, // 13MHz clock
+        { 460800, 460800 }, { 460,    460800 },
+        { 812500, 812500 }, { 812,    812500 }, // 13MHz clock
+        { 921600, 921600 }, { 921,    921600 },
+        {      0,      0 } // terminator
+    };
+
+    for (i = 0; i < sizeof(rates) / sizeof(struct rate_s) - 1; i++)
+        if (rates[i].bps == bps)
+            break;
+
+    tr(TrTargetDrv, "serial_is_baudrate(%d) %d\n", bps, rates[i].baudrate);
+
+    return rates[i].baudrate;
+}
+
+int serial_baudrate_set(int bps)
+{
+#if 0
+    if (!GetCommState(hCom, &dcb))
+        return E_OS + E_UART_PARAM;
+#endif
+
+    bps = serial_is_baudrate(bps);
+    if (bps == 0)
+        return E_OS + E_UART_PARAM;
+
+    /* Replace 812K with 827K. Otherwise, the chip will automatically select 800K. */ 
+    /* 800K is OK, but we might as well gain the extra 3% speed :-) */
+    if (bps == 812500)
+        dcb.BaudRate = 827586;
+    else
+        dcb.BaudRate = bps;
+
+    if (!SetCommState(hCom, &dcb))
+        return E_OS + E_UART_PARAM;
+
+    return bps;
+}
+
+int serial_baudrate_get(void)
+{
+    return dcb.BaudRate;
+}
+
+void serial_exit(void)
+{
+    DWORD exit_code;
+
+    serial_reset();
+
+    (void) GetExitCodeThread (thread_handle, &exit_code);
+    (void) TerminateThread (thread_handle, exit_code);
+
+    (void) CloseHandle (hCom);
+    (void) CloseHandle (read_overlapped.hEvent);
+    (void) CloseHandle (write_overlapped.hEvent);
+}
+
+// Clear buffers and transactions.
+void serial_reset(void)
+{
+    PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
+}
+
+// Return the number of milli-seconds it takes to transfer <n> bytes.
+int serial_transfer_time(int size)
+{
+    return 1000 * 10 * size / serial_baudrate_get();
+}
+
+
+/***************************************
+ * Send
+ ***************************************/
+
+int serial_send(char *buf, int size)
+{
+    DWORD written;
+
+    ResetEvent(write_overlapped.hEvent); // why?
+
+    if (!WriteFile(hCom, buf, size, &written, &write_overlapped)) {
+        if (GetLastError() == ERROR_IO_PENDING) {
+            if (GetOverlappedResult(hCom, &write_overlapped,
+                                    &written, TRUE) == FALSE)
+                written = E_OS + E_UART_DRV_SEND;
+        }
+    }
+
+    return written;
+}
+
+
+/***************************************
+ * Receive
+ ***************************************/
+
+void serial_recv_reset(void)
+{
+    PurgeComm(hCom, PURGE_RXABORT|PURGE_RXCLEAR);
+}
+
+static void serial_listener(void)
+{
+    DWORD event_mask;
+    char buf[64];
+    DWORD size;
+
+    while (1)
+    {
+        // Wait the event signalling characters received.
+        if (WaitCommEvent (hCom, &event_mask, NULL) != TRUE) {
+            main_msg("WaitCommEvent(): error %d\n", GetLastError());
+            return;
+        }
+        tr(TrTargetDrv, "|");
+
+        // Read all characters received in the buffer.  Mysteriously, it
+        // does NOT work with a buffer size greater than one!
+        do {
+            if (!ReadFile(hCom, buf, 1, &size, &read_overlapped))
+            {
+                if (GetLastError() == ERROR_IO_PENDING) {
+                    GetOverlappedResult(hCom, &read_overlapped, &size, TRUE);
+                }
+                else {
+                    main_msg("ReadFile(): error %d\n", GetLastError());
+                    serial_recv_reset();
+                    break;
+                }
+            }
+            // Push the data to upper layer
+            target_recv_push(buf, size);
+
+        } while (size);
+    }
+}
+
+
+/******************************************************************************
+ * Control of Delta cable special outputs
+ ******************************************************************************/
+
+void serial_rts(char state)
+{
+    if (state)
+        EscapeCommFunction(hCom, SETRTS);
+    else
+        EscapeCommFunction(hCom, CLRRTS);
+}
+
+void serial_dtr(char state)
+{
+    if (state)
+        EscapeCommFunction(hCom, SETDTR);
+    else
+        EscapeCommFunction(hCom, CLRDTR);
+}
+
+void serial_break(char state)
+{
+    if (state)
+        SetCommBreak(hCom);
+    else
+        ClearCommBreak(hCom);
+}
+
+#else // (OS == WIN32)
+
+
+/******************************************************************************
+ * Unix driver
+ ******************************************************************************/
+
+
+#endif // (OS == WIN32)