FreeCalypso > hg > freecalypso-reveng
view fluid-mnf/target.c @ 366:c6a79ac125ac
fluid-mnf: rm Performance, incorporated into README
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 15 Mar 2020 09:00:05 +0000 |
parents | 37b5f94de802 |
children |
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 $ * * This serial interface handling architecture has been majorly redesigned * by Mychaela N. Falconia for the present fluid-mnf Linux port. * ******************************************************************************/ #include "serial.h" #include "fluid.h" #include "trace.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int target_trace(unsigned char ch); /****************************************************************************** * Globals ******************************************************************************/ #define RECVBUF_SIZE (65536) static unsigned char recvbuf[RECVBUF_SIZE]; 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(char *ttyport, int baudrate) { int rc; rc = serial_init(ttyport, baudrate); if (rc < 0) return rc; target_recv_reset(); return 0; } 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_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()); } // 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) { char rxbuf[512]; int cc; tr(TrTargetWait, "target_wait(%d, %d)\n", size, timeout); if (size > 0) timeout += serial_transfer_time(size); target_trace_timer = timeout; if (size == 0) { usleep(timeout * 1000); return 0; } while (recvbuf_size() < size) { cc = serial_recv(rxbuf, sizeof rxbuf, timeout); if (cc < 0) return cc; if (cc == 0) return E_RECV_TIMEOUT; target_recv_push(rxbuf, cc); } return recvbuf_size(); } 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; }