nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@1: #include nuclear@0: nuclear@0: enum { nuclear@0: OP_NONE, nuclear@0: OP_WRITE, nuclear@0: OP_READ, nuclear@0: OP_RESET nuclear@0: }; nuclear@0: nuclear@0: int op_write(FILE *dev, FILE *fp); nuclear@0: int op_read(FILE *dev, FILE *fp); nuclear@0: int op_reset(FILE *dev); nuclear@0: int parse_args(int argc, char **argv); nuclear@1: void print_progress(int p); nuclear@0: nuclear@0: int op, verify = 0; nuclear@0: const char *devname = "/dev/ttyUSB0"; nuclear@0: char *fname = 0; nuclear@0: uint32_t start_addr; nuclear@0: int read_size = 128 * 1024; nuclear@1: int quiet; nuclear@0: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@0: FILE *fp, *devfp; nuclear@0: int dev; nuclear@0: struct termios term; nuclear@0: nuclear@0: if(parse_args(argc, argv) == -1) { nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: if((dev = open(devname, O_RDWR)) == -1) { nuclear@0: fprintf(stderr, "failed to open device %s: %s\n", devname, strerror(errno)); nuclear@0: return 1; nuclear@0: } nuclear@0: if(tcgetattr(dev, &term) == -1) { nuclear@0: fprintf(stderr, "failed to get terminal attributes for %s: %s\n", devname, strerror(errno)); nuclear@0: return 1; nuclear@0: } nuclear@0: term.c_cflag = CS8 | CLOCAL; nuclear@0: term.c_iflag &= ~(IXON | IXOFF); nuclear@0: term.c_lflag = 0; nuclear@0: nuclear@1: cfsetispeed(&term, B115200); nuclear@1: cfsetospeed(&term, B115200); nuclear@0: nuclear@0: if(tcsetattr(dev, TCSANOW, &term) == -1) { nuclear@0: fprintf(stderr, "failed to set terminal attributes for %s: %s\n", devname, strerror(errno)); nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: if(!(devfp = fdopen(dev, "r+"))) { nuclear@0: perror("failed to attach I/O stream to the device file\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: setvbuf(devfp, 0, _IONBF, 0); nuclear@0: nuclear@0: if(fname && !(fp = fopen(fname, op == OP_READ ? "w" : "r"))) { nuclear@0: fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: switch(op) { nuclear@0: case OP_WRITE: nuclear@0: if(op_write(devfp, fp) == -1) { nuclear@0: fprintf(stderr, "write failed\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case OP_READ: nuclear@0: if(op_read(devfp, fp) == -1) { nuclear@0: fprintf(stderr, "read failed\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case OP_RESET: nuclear@0: if(op_reset(devfp) == -1) { nuclear@0: fprintf(stderr, "reset failed\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: nuclear@0: fclose(devfp); nuclear@0: close(dev); nuclear@0: if(fp) { nuclear@0: fclose(fp); nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@1: #define RET_IF_FAIL(x) if(!fgets(buf, sizeof buf, dev) || buf[0] != 'O') return x nuclear@1: /*#define RET_IF_FAIL(x) \ nuclear@1: do { \ nuclear@1: if(!fgets(buf, sizeof buf, dev)) return x; \ nuclear@1: printf("--> %s", buf); \ nuclear@1: if(buf[0] != 'O') return x; \ nuclear@1: } while(0) nuclear@1: */ nuclear@0: nuclear@0: int op_write(FILE *dev, FILE *fp) nuclear@0: { nuclear@0: char buf[128]; nuclear@1: int c, prev_progr = -1, written = 0; nuclear@1: struct stat st; nuclear@1: nuclear@1: fstat(fileno(fp), &st); nuclear@0: nuclear@0: fprintf(dev, "p\n"); nuclear@0: RET_IF_FAIL(-1); nuclear@0: fprintf(dev, "a%d\n", start_addr); nuclear@0: RET_IF_FAIL(-1); nuclear@0: nuclear@1: if(!quiet) { nuclear@1: printf("writing %d bytes starting from %xh\n", (int)st.st_size, start_addr); nuclear@1: } nuclear@1: nuclear@0: while((c = fgetc(fp)) != -1) { nuclear@1: int p; nuclear@0: fprintf(dev, "w%d\n", c); nuclear@0: RET_IF_FAIL(-1); nuclear@1: nuclear@1: if(!quiet) { nuclear@1: p = 100 * ++written / st.st_size; nuclear@1: if(p != prev_progr) { nuclear@1: prev_progr = p; nuclear@1: print_progress(p); nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: if(!quiet) { nuclear@1: putchar('\n'); nuclear@1: } nuclear@1: nuclear@1: if(verify) { nuclear@1: int verified = 0; nuclear@1: nuclear@1: rewind(fp); nuclear@1: fprintf(dev, "a%d\n", start_addr); nuclear@1: RET_IF_FAIL(-1); nuclear@1: nuclear@1: if(!quiet) { nuclear@1: printf("verifying %d bytes starting from %xh\n", (int)st.st_size, start_addr); nuclear@1: } nuclear@1: nuclear@1: while((c = fgetc(fp)) != -1) { nuclear@1: int p, val; nuclear@1: fprintf(dev, "r\n"); nuclear@1: nuclear@1: if(!fgets(buf, sizeof buf, dev) || buf[0] != 'O') { nuclear@1: fprintf(stderr, "\rread error after %d bytes\n", verified); nuclear@1: break; nuclear@1: } nuclear@1: nuclear@1: if((val = atoi(buf + 3)) != c) { /* skip 'O', 'K', ' ' */ nuclear@1: fprintf(stderr, "\rverification error at byte %d\n", verified); nuclear@1: fprintf(stderr, "expected %d (%xh), got %d (%xh)\n", c, c, val, val); nuclear@1: break; nuclear@1: } nuclear@1: nuclear@1: if(!quiet) { nuclear@1: p = 100 * ++verified / st.st_size; nuclear@1: if(p != prev_progr) { nuclear@1: prev_progr = p; nuclear@1: print_progress(p); nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: if(!quiet) { nuclear@1: putchar('\n'); nuclear@1: } nuclear@0: } nuclear@0: nuclear@0: fprintf(dev, "b\n"); nuclear@0: RET_IF_FAIL(-1); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: int op_read(FILE *dev, FILE *fp) nuclear@0: { nuclear@0: char buf[128]; nuclear@1: int i, val, prev_progr = -1; nuclear@0: nuclear@0: fprintf(dev, "p\n"); nuclear@0: RET_IF_FAIL(-1); nuclear@0: fprintf(dev, "a%d\n", start_addr); nuclear@0: RET_IF_FAIL(-1); nuclear@0: nuclear@1: if(!quiet) { nuclear@1: printf("reading %d bytes starting from %xh\n", read_size, start_addr); nuclear@1: } nuclear@1: nuclear@0: for(i=0; i\n"); nuclear@0: printf(" -r|-read \n"); nuclear@0: printf(" -a|-addr
: start address for read/write operations\n"); nuclear@0: printf(" -R|-reset: reboot machine\n"); nuclear@0: printf(" -v|-verify: do verification after writing\n"); nuclear@0: printf(" -s|-size: read size in bytes\n"); nuclear@1: printf(" -q|-quiet: don't print anything to stdout\n"); nuclear@0: printf(" -d|-device : serial device (eg /dev/ttyUSB0)\n"); nuclear@0: printf(" -h|-help: print usage and exit\n"); nuclear@0: return 0; nuclear@0: nuclear@0: } else { nuclear@0: fprintf(stderr, "invalid argument: %s\n", argv[i]); nuclear@0: return -1; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: if(!op) { nuclear@0: fprintf(stderr, "you must specify an operation\n"); nuclear@0: return -1; nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@1: nuclear@1: void print_progress(int p) nuclear@1: { nuclear@1: int i, num = p / 2; nuclear@1: printf("\rprogress: ["); nuclear@1: for(i=0; i<50; i++) { nuclear@1: if(i == num) { nuclear@1: putchar('>'); nuclear@1: } else { nuclear@1: putchar(i < num ? '=' : ' '); nuclear@1: } nuclear@1: } nuclear@1: printf("] %3d%%", p); nuclear@1: fflush(stdout); nuclear@1: }