diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fluid-mnf/target.c	Sat Feb 29 05:36:07 2020 +0000
@@ -0,0 +1,425 @@
+/******************************************************************************
+ * FLUID (Flash Loader Utility Independent of Device)
+ *
+ * Copyright Texas Instruments, 2001.
+ * Mads Meisner-Jensen, mmj@ti.com.
+ *
+ * Target Connection and Control
+ *
+ * $Id: target.c 1.20 Mon, 21 Oct 2002 18:39:13 +0200 mmj $
+ *
+ ******************************************************************************/
+
+#include "serial.h"
+#include "fluid.h"
+#include "trace.h"
+
+#include <stdio.h>
+
+#if defined(MSC) || defined(BCC)
+  #include "windows.h"
+#endif
+
+int target_trace(unsigned char ch);
+
+
+/******************************************************************************
+ * Globals
+ ******************************************************************************/
+
+HANDLE hEvent;
+
+#define RECVBUF_SIZE  (65536)
+
+static unsigned char recvbuf[RECVBUF_SIZE];
+static int recvbuf_size_target;
+static int recvbuf_put;
+static int recvbuf_get;
+
+#define recvbuf_size() (recvbuf_put - recvbuf_get + \
+                        ((recvbuf_put - recvbuf_get) < 0 ? RECVBUF_SIZE : 0))
+
+
+/******************************************************************************
+ * Error Functions
+ ******************************************************************************/
+
+void error_proto(char ch, char chx)
+{
+    char chd, chxd;
+
+    chd  = (' ' <= ch  && ch  < 127 ? ch  : '.');
+    chxd = (' ' <= chx && chx < 127 ? chx : '.');
+
+    flowf(NORMAL, "(protocol error: got '%c' 0x%02X, expected '%c' 0x%02X)\n",
+                 chd, ch, chxd, chx);
+
+    main_fatal(E_PROTO_ERROR);
+}
+
+
+/******************************************************************************
+ * Target Dependencies
+ ******************************************************************************/
+
+// <clk> is the target's clock frequency 
+int target_uart_baudrate_divider_get(int clk, int bps)
+{
+    int divider = clk / bps / 16;
+
+    tr(TrTargetDrv, "target_uart_baudrate_divider_get(%d, %d) %d\n",
+       clk, bps, divider);
+
+    return divider;
+}
+
+
+/******************************************************************************
+ * Target Init and Send
+ ******************************************************************************/
+
+static int target_trace_timer;
+
+void target_recv_reset(void)
+{
+    tr(TrTargetDrv, "recv_reset()\n");
+
+    recvbuf_get = recvbuf_put = 0;
+
+    memset(recvbuf, 0x77, RECVBUF_SIZE);
+
+    serial_recv_reset();
+}
+
+int target_driver_init(int uart, int baudrate, char *flowcontrol)
+{
+    int error;
+
+    target_recv_reset();
+
+    hEvent = CreateEvent(NULL,  // lpEventAttributes
+                         FALSE, // bManualReset (OFF)
+                         FALSE, // bInitialstate (OFF)
+                         NULL); // lpName
+
+    if (hEvent == NULL) {
+        error = E_DRIVER_INIT + E_OS;
+    }
+    else {
+        error = serial_init(uart, baudrate, flowcontrol);
+    }
+    return error;
+}
+
+int target_driver_baudrate(int baudrate)
+{
+    return serial_baudrate_set(baudrate);
+}
+    
+int target_putchar(char ch)
+{
+    char trch;
+
+    trch = (ch < ' ' || ch == 127 ? '.' : ch);
+    tr(TrPutChar, "s '%c'/0x%02X\n", trch, ch & 0xFF);
+
+    return serial_send(&ch, 1);
+}
+
+int target_send(char *buf, int size)
+{
+    tr(TrPutChar, "s (%d bytes)\n", size);
+
+    return serial_send(buf, size);
+}
+
+
+/******************************************************************************
+ * Target Wait and Receive
+ ******************************************************************************/
+
+void target_recv_signal(void)
+{
+    // Notify waiting thread when we have received the requested number of
+    // bytes. Note that we use auto-resetting events, so you have to be VERY
+    // careful to wait for the exact number of bytes you want. Otherwise you
+    // might trigger the event twice in quick succession and this will
+    // result in the next call of target_wait()'s to return immediately
+    // without waiting!
+
+    if (recvbuf_size() >= recvbuf_size_target && recvbuf_size_target > 0) {
+        // When we have triggered the event, disable further triggering
+        // until next call of target_wait()
+        recvbuf_size_target = 0;
+        tr(TrDriverGet, "!");
+        if (SetEvent(hEvent) == 0)
+            fprintf(stderr, "FATAL: recv_push_tm(): SetEvent() failed with Win32 error %d\n", GetLastError());
+    }
+}
+
+void target_recv_push(char *buf, int size)
+{
+    if (size == 0) {
+        tr(TrDriverGet, " G?");
+        return;
+    }
+
+    while (size--) {
+        recvbuf[recvbuf_put++] = *buf++;
+        recvbuf_put &= (RECVBUF_SIZE - 1);
+    }
+    tr(TrDriverGet, " G%d", recvbuf_size());
+
+    target_recv_signal();
+}
+
+// Wait maximum <timeout> milli-seconds for <size> bytes to arrive. If
+// <size> is zero, we unconditionally wait for <time_ms> milli-seconds
+// (quite simply a delay). The transfer time is automatically added to the
+// total waiting time.
+int target_wait(int size, int timeout)
+{
+    int result = 0;
+
+    tr(TrTargetWait, "target_wait(%d, %d)\n", size, timeout);
+
+    if (size > 0)
+        timeout += serial_transfer_time(size);
+
+    recvbuf_size_target = size;
+    target_trace_timer = timeout;
+
+    if (size == 0) {
+        Sleep(timeout);
+    }
+    else {
+        target_recv_signal();
+
+        switch (WaitForSingleObject(hEvent, timeout)) {
+        case WAIT_OBJECT_0: result = recvbuf_size(); break;
+        case WAIT_TIMEOUT:  result = E_RECV_TIMEOUT; break;
+        default:            result = E_OS + E_DRIVER_WAIT; break;
+        }
+    }
+    recvbuf_size_target = 0;
+
+    return result;
+}
+
+int target_recv(void *outbuf, int size)
+{
+    int i, bufsize;
+    char *buf = (char *) outbuf;
+
+    bufsize = recvbuf_size();
+    if (bufsize < size)
+        size = bufsize;
+
+    for (i = 0; i < size; i++) {
+        *buf++ = recvbuf[recvbuf_get++];
+        recvbuf_get &= (RECVBUF_SIZE - 1);
+    }
+
+    tr(TrGetChar, "r (%d bytes)\n", size);
+    return size;
+}
+
+int target_getchar(void)
+{
+    int trace_in_progress;
+    char ch;
+    
+    do {
+        ch = recvbuf[recvbuf_get++];
+        recvbuf_get &= (RECVBUF_SIZE - 1);
+        tr(TrGetChar, "r '%c' %02X\n",
+           (ch >= ' ' && ch <= 126 ? ch : '.'), ch & 0xFF);
+
+        if ((trace_in_progress = target_trace((char) ch)) != 0) {
+            if (target_wait(1, target_trace_timer) < 1)
+                main_fatal(E_RECV_TIMEOUT);
+        }
+    } while (trace_in_progress);
+    
+    return (ch & 0xFF);
+}
+
+int target_expect_char(char ch, int timeout)
+{
+    char mych;
+
+    if (target_wait(1, timeout) < 1) {
+        flowf(NORMAL, "(Waited for '%c' 0x%02X)\n", ch, ch);
+        main_fatal(E_RECV_TIMEOUT);
+    }
+
+    if ((mych = target_getchar()) != ch)
+        error_proto(mych, ch);
+
+    return ch;
+}
+
+
+/******************************************************************************
+ * Target Buffer Put
+ ******************************************************************************/
+
+int buf_put1(char *buf, unsigned char data)
+{
+    tr(TrPutChar, "buf_put1(0x%02X) '%c'\n", data, data);
+
+    *buf   = (data      ) & 0xFF;
+    return 1;
+}
+
+int buf_put2(char *buf, unsigned short data)
+{
+    tr(TrPutChar, "buf_put2(0x%04X)\n", data);
+
+    *buf++ = (data      ) & 0xFF;
+    *buf   = (data >>  8) & 0xFF;
+    return 2;
+}
+
+int buf_put4(char *buf, unsigned int data)
+{
+    tr(TrPutChar, "buf_put4(0x%08X)\n", data);
+
+    *buf++ = (data      ) & 0xFF;
+    *buf++ = (data >>  8) & 0xFF;
+    *buf++ = (data >> 16) & 0xFF;
+    *buf   = (data >> 24) & 0xFF;
+    return 4;
+}
+
+// Put 2-byte integer in network order
+int buf_put2no(char *buf, unsigned short data)
+{
+    tr(TrPutChar, "buf_put2no(0x%04X)\n", data);
+
+    *buf++ = (data >>  8) & 0xFF;
+    *buf   = (data      ) & 0xFF;
+    return 2;
+}
+
+// Put 4-byte integer in network order
+int buf_put4no(char *buf, unsigned int data)
+{
+    tr(TrPutChar, "buf_put4no(0x%08X)\n", data);
+
+    *buf++ = (data >> 24) & 0xFF;
+    *buf++ = (data >> 16) & 0xFF;
+    *buf++ = (data >>  8) & 0xFF;
+    *buf   = (data      ) & 0xFF;
+    return 4;
+}
+
+
+/******************************************************************************
+ * Special Target Control Functions
+ ******************************************************************************/
+
+// Control target power. Works *only* with special cable! If <state> is
+// non-zero, the power is on. Otherwise, it is off.
+void target_power(char state)
+{
+    if (arg_uart_level_convert)
+        return;
+
+    if (state) {
+        serial_rts(0);
+    }
+    else {
+        serial_rts(1);
+        serial_dtr(1);
+        serial_break(1);
+        serial_break(0);
+    }
+}
+
+// Control target reset line. Works *only* with special cable!  If <state>
+// is non-zero, the reset line is asserted. Otherwise, it is negated.
+void target_reset(char state)
+{
+    if (arg_uart_level_convert)
+        return;
+
+    if (state) {
+        serial_rts(1);
+        serial_dtr(0);
+        serial_rts(0);
+        serial_break(0);
+    }
+    else {
+        serial_break(1);
+        serial_rts(1);
+        serial_dtr(1);
+        serial_rts(0);
+    }
+}
+
+
+/******************************************************************************
+ * Target Trace/Debug Functions
+ ******************************************************************************/
+
+static int target_trace_enable_flag = 0;
+
+int target_trace_enable(int flag)
+{
+    int old = target_trace_enable_flag;
+
+    target_trace_enable_flag = flag;
+
+    if (arg_target_trace_enable)
+        flowf(DEBUG, "{%s}", (flag ? "enable" : "disable"));
+
+    return old;
+}
+
+// Interpret and display target trace message. Return zero if <ch> was not
+// intercepted. Otherwise, if it was intercepted, return non-zero.
+int target_trace(unsigned char ch)
+{
+    int i;
+    unsigned int number = 0;
+    char buf[80], *p;
+
+    // If target is not supposed to transmit any tracing at this point in
+    // the state machine(s), the flag will be zero and thus we return.
+    if (target_trace_enable_flag && ch == '$') {
+        if (target_wait(1, 100) < 0)
+            main_fatal(E_RECV_TIMEOUT);
+        ch = target_getchar();
+        switch (ch) {
+        case 'S':
+            p = buf;
+            while (ch != 0) {
+                if (target_wait(1, 100) < 0)
+                    main_fatal(E_RECV_TIMEOUT);
+                ch = target_getchar();
+                *p++ = ch;
+            }
+            *p = 0;
+            if (arg_target_trace_enable)
+                printf("{'%s'} ", buf);
+            break;
+        case 'N':
+            for (i = 0; i < 4; i++) {
+                if (target_wait(1, 100) < 0)
+                    main_fatal(E_RECV_TIMEOUT);
+                ch = target_getchar();
+                number = (number >> 8) + (ch << 24);
+            }
+            if (arg_target_trace_enable)
+                printf("{0x%X/%dd} ", number, number);
+            break;
+        default:
+            fprintf(stderr, "WARNING: Bad TargetTrace char received! (0x%X)\n",
+                    ch & 0xFF);
+            break;
+        }
+        return 1;
+    }
+    return 0;
+}