FreeCalypso > hg > freecalypso-reveng
view fluid-mnf/target.c @ 316:2ceb1f263e19
frbl/reconst: first attempt to compile boot.c
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 04 Mar 2020 23:41:51 +0000 |
parents | 9cecc930d78f |
children | b595ff13547b |
line wrap: on
line source
/****************************************************************************** * 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; }