/* * lpc111x-isp/lpc111x.c - LPC111x/LPC11Cxx ISP programmer * * Written 2012 by Werner Almesberger * Copyright 2012 Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include #include #include #define TGT_nRESET UBB_CMD #define TGT_nISP UBB_DAT1 #define TGT_TX UBB_DAT3 #define TGT_RX UBB_DAT2 #define HOST_RX TGT_TX #define HOST_TX TGT_RX #define AUTOBAUD_TRIES 10 #define SYNC "Synchronized" /* ----- Debugging and tracing --------------------------------------------- */ static void trace(const char *label, const uint8_t *s, int len) { const uint8_t *end = s+len; if (label) printf("%s ", label); for (end = s+len; s != end; s++) { if (*s >= ' ' && *s <= '~') printf("%c", *s); else if (*s == 10) printf(s+1 == end ? "\n" : "\\n"); else if (*s == 13) ; else printf("\\%02o", *s); } if (len && end[-1] != '\n') printf("...\n"); } static void trace_out(const void *s, int len) { trace(">>>", s, len); } static void trace_in(const uint8_t *s, int len) { trace("<<<", s, len); } /* ----- Dialog functions -------------------------------------------------- */ static int dialog(const char *cmd, void *buf, int buf_len, int idle) { int cmd_len = strlen(cmd); char *tx_buf = alloca(cmd_len+3); uint8_t *rx_buf = alloca(cmd_len+2+buf_len); int got; memcpy(tx_buf, cmd, cmd_len); memcpy(tx_buf+cmd_len, "\r\n", 2); trace_out(tx_buf, cmd_len+2); got = swuart_trx(tx_buf, cmd_len+2, rx_buf, cmd_len+2+buf_len, idle, idle); if (got < cmd_len+2) { trace_in(rx_buf, got); fprintf(stderr, "response too short for echo\n"); exit(1); } if (memcmp(rx_buf, cmd, cmd_len) || rx_buf[cmd_len] != '\r' || rx_buf[cmd_len+1] != '\n') { trace_in(rx_buf, got); fprintf(stderr, "echo mismatch\n"); exit(1); } trace_in(rx_buf, cmd_len+2); got -= cmd_len+2; memcpy(buf, rx_buf+cmd_len+2, got); return got; } static int autobaud(void) { uint8_t reply[100]; int i, got; for (i = 0; i != AUTOBAUD_TRIES; i++) { CLR(TGT_nRESET); usleep(10); /* DS Table 9 pg 29 says min 50 ns */ SET(TGT_nRESET); usleep(5*1000); /* UM 26.3.1 pg 408 says max 3 ms */ got = swuart_trx("?", 1, reply, sizeof(reply), 1000, 100); trace_in(reply, got); if (got != strlen(SYNC)+2 || memcmp(reply, SYNC "\r\n", got)) continue; got = dialog(SYNC, reply, sizeof(reply), 100); trace_in(reply, got); if (got == 4 && !memcmp(reply, "OK\r\n", 4)) return 1; } return 0; } /* ----- ISP session ------------------------------------------------------- */ static void at_exit(void) { ubb_close(0); } static void start_isp(void) { uint8_t reply[1000]; int got; if (ubb_open(0) < 0) { perror("ubb_open"); exit(1); } atexit(at_exit); ubb_power(1); usleep(100*1000); SET(TGT_nRESET); OUT(TGT_nRESET); CLR(TGT_nISP); OUT(TGT_nISP); swuart_open(HOST_TX, HOST_RX, 115200); if (!autobaud()) { fprintf(stderr, "target is not responding\n"); exit(1); } got = dialog("12000", reply, sizeof(reply), 100); trace_in(reply, got); if (got != 4 || memcmp(reply, "OK\r\n", 4)) { fprintf(stderr, "cannot set clock rate\n"); exit(1); } } /* ----- Command-line processing ------------------------------------------- */ int main(int argc, char **argv) { uint8_t reply[1000]; int got; start_isp(); got = dialog("J", reply, sizeof(reply), 100); trace_in(reply, got); return 0; }