FreeCalypso > hg > freecalypso-reveng
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; +}