From d1a0ab09739c9d3ac047c824c3db8b16dce281b6 Mon Sep 17 00:00:00 2001 From: Mariano Alvira Date: Thu, 11 Oct 2012 23:14:14 -0400 Subject: [PATCH] Add C version of mc1322x-load courtesy of Maxim Osipov --- tools/mc1322x-load.c | 312 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 tools/mc1322x-load.c diff --git a/tools/mc1322x-load.c b/tools/mc1322x-load.c new file mode 100644 index 000000000..59620e7d2 --- /dev/null +++ b/tools/mc1322x-load.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2012, Maxim Osipov + * Copyright (c) 2010, Mariano Alvira and other contributors + * to the MC1322x project (http://mc1322x.devl.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +char* filename; +char* second; +char* term = "/dev/ttyUSB0"; +int baud = B115200; +int verbose = 0; +char* rts = "rts"; +char* command; +int first_delay = 50; +int second_delay = 100; +int do_exit = 0; +int zerolen = 0; + +struct stat sbuf; +struct termios options; +char buf[256]; +int pfd; +int ffd; +int sfd; + +void help(void); + +int main(int argc, char **argv) +{ + int c = 0; + int r = 0; + int i = 0; + uint32_t s = 0; + opterr = 0; + + /* Parse options */ + while ((c = getopt(argc, argv, "f:s:zt:vu:r:c:a:b:eh")) != -1) { + switch (c) + { + case 'f': + filename = optarg; + break; + case 's': + second = optarg; + break; + case 'z': + zerolen = 1; + break; + case 't': + term = optarg; + break; + case 'v': + verbose = 1; + break; + case 'u': + if (strcmp(optarg, "115200")) { + baud = B115200; + } else if (strcmp(optarg, "57600")) { + baud = B115200; + } else if (strcmp(optarg, "19200")) { + baud = B19200; + } else if (strcmp(optarg, "9600")) { + baud = B9600; + } else { + printf("Unknown baud rate %s!\n", optarg); + return -1; + } + break; + case 'r': + rts = optarg; + break; + case 'c': + command = optarg; + break; + case 'a': + first_delay = atoi(optarg); + break; + case 'b': + second_delay = atoi(optarg); + break; + case 'e': + do_exit = 1; + break; + case 'h': + case '?': + help(); + return 0; + default: + abort(); + } + } + + /* Print settings */ + if (verbose) { + printf("Primary file (RAM): %s\n", filename); + printf("Secondary file (Flash): %s\n", second); + printf("Zero secondary file: %s\n", zerolen == 1 ? "Yes" : "No"); + printf("Port: %s\n", term); + printf("Baud rate: %i\n", baud); + printf("Flow control: %s\n", rts); + printf("Reset command: %s\n", command); + printf("Exit after load: %s\n", do_exit == 1 ? "Yes" : "No"); + printf("Delay 1: %i\n", first_delay); + printf("Delay 2: %i\n", second_delay); + } + + /* Open and configure serial port */ + pfd = open(term, O_RDWR | O_NOCTTY | O_NDELAY); + if (pfd == -1) { + printf("Cannot open serial port %s!\n", term); + return -1; + } + fcntl(pfd, F_SETFL, FNDELAY); + tcgetattr(pfd, &options); + cfsetispeed(&options, baud); + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + if (strcmp(rts, "rts")) { + options.c_cflag &= ~CRTSCTS; + } else { + options.c_cflag |= CRTSCTS; + } + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_oflag &= ~OPOST; + tcsetattr(pfd, TCSANOW, &options); + + /* Reset the board if we can */ + printf("Reset the board to enter bootloader (waiting for CONNECT)...\n"); + if (command) { + printf("Performing reset: %s\n", command); + system(command); + } + + /* Primary bootloader wait loop */ + i = 0; + while (1) { + /* Wait for CONNECT */ + r = write(pfd, (const void*)"\0", 1); + sleep(1); + r = read(pfd, &buf[i], sizeof(buf)-1-i); + if (r > 0) { + buf[i+r] = '\0'; + printf("%s", &buf[i]); fflush(stdout); + if (strstr(&buf[i], "CONNECT")) { + printf("\n"); + break; + } + i += r; + if (i >= sizeof(buf)-1) { + i = 0; + } + } else { + printf("."); fflush(stdout); + } + } + + /* Send primary file */ + if (!filename) { + printf("Please specify firmware file name (-f option)!\n"); + return -1; + } + if (stat(filename, &sbuf)) { + printf("Cannot open firmware file %s!\n", filename); + return -1; + } + ffd = open(filename, O_RDONLY); + if (ffd == -1) { + printf("Cannot open firmware file %s!\n", filename); + return -1; + } + printf("Sending %s (%i bytes)...\n", filename, sbuf.st_size); + s = sbuf.st_size; + r = write(pfd, (const void*)&s, 4); + i = 0; + r = read(ffd, buf, 1); + while (r > 0) { + do { + usleep(first_delay); + c = write(pfd, (const void*)buf, r); + } while(c < r); + i += r; + printf("Written %i\r", i); fflush(stdout); + r = read(ffd, buf, 1); + } + printf("\n"); + + /* Secondary loader wait loop */ + if (second || zerolen) { + /* Wait for ready */ + printf("Sending secondary file (waiting for ready)...\n"); + i = 0; + while (1) { + sleep(1); + r = read(pfd, &buf[i], sizeof(buf)-1-i); + if (r > 0) { + buf[i+r] = '\0'; + printf("%s", &buf[i]); fflush(stdout); + if (strstr(buf, "ready")) { + printf("\n"); + break; + } + i += r; + if (i >= sizeof(buf)-1) { + i = 0; + } + } else { + printf("."); fflush(stdout); + } + } + + /* Send secondary file */ + if (second) { + if (stat(second, &sbuf)) { + printf("Cannot open secondary file %s!\n", second); + return -1; + } + sfd = open(second, O_RDONLY); + if (sfd == -1) { + printf("Cannot open secondary file %s!\n", second); + return -1; + } + } + + /* Send secondary file */ + printf("Sending %s (%i bytes)...\n", second, sbuf.st_size); + s = sbuf.st_size; + r = write(pfd, (const void*)&s, 4); + i = 0; + r = read(sfd, buf, 1); + while (r > 0) { + do { + usleep(second_delay); + c = write(pfd, (const void*)buf, r); + } while(c < r); + i += r; + printf("Written %i\r", i); fflush(stdout); + r = read(sfd, buf, 1); + } + printf("\n"); + } + + /* Drop in echo mode */ + if (!do_exit) { + while (1) { + r = read(pfd, buf, sizeof(buf)); + if (r > 0) { + buf[r] = '\0'; + printf("%s", buf); fflush(stdout); + } + } + } +} + + +void help(void) +{ + printf("Example usage: mc1322x-load -f foo.bin -t /dev/ttyS0 -b 9600\n"); + printf(" or : mc1322x-load -f flasher.bin -s flashme.bin 0x1e000,0x11223344,0x55667788\n"); + printf(" or : mc1322x-load -f flasher.bin -z 0x1e000,0x11223344,0x55667788\n"); + printf(" -f required: binary file to load\n"); + printf(" -s optional: secondary binary file to send\n"); + printf(" -z optional: send a zero length file as secondary\n"); + printf(" -t, terminal default: /dev/ttyUSB0\n"); + printf(" -u, baud rate default: 115200\n"); + printf(" -r [none|rts] flow control default: rts\n"); + printf(" -c command to run for autoreset: \n"); + printf(" e.g. -c 'bbmc -l redbee-econotag -i 0 reset'\n"); + printf(" -e exit instead of dropping to terminal display\n"); + printf(" -a first intercharacter delay, passed to usleep\n"); + printf(" -b second intercharacter delay, passed to usleep\n"); + printf("\n"); + printf("Anything on the command line is sent after all of the files.\n\n"); +}