12 #define VERSION "0.5.1"
14 void usage(poptContext pc)
16 poptPrintHelp(pc, stderr, 0);
17 fprintf(stderr, "\nAvailable commands: \n"
21 "\twritefile [file] ...\n"
22 "\treadfile <len> [file] ...\n"
23 "\twritebyte <address> <byte>\n"
24 "\treadbyte <address>\n"
31 fprintf(stderr, "Received signal, exiting...\n");
35 void writechar(char datamem, char do_verify, int address, int byte)
38 if(datamem)writedata(address, byte);
39 else writecode(address, byte);
42 if(datamem)d = readdata(address);
43 else d = readcode(address);
46 fprintf(stderr, "Error verifying byte at offset 0x%x\n", address);
53 int writebin(FILE *fd, char do_verify, char datamem)
58 writechar(datamem, do_verify, i, fgetc(fd));
66 int writehex(FILE *fd, char do_verify, char datamem)
68 int length; long address; int type;
70 int checksum1, checksum2;
77 if(fscanf(fd, ":%2x%4lx%2x", &length, &address, &type) < 3) {
78 fprintf(stderr, "Error reading intel hex file, line %d\n", i);
85 checksum1+=address & 0xFF;
86 checksum1+=address & 0xFF00;
90 if(type == 2) continue;
92 for(j = 0; j < length; j++) {
93 if(fscanf(fd, "%2x", &byte) < 1) {
94 fprintf(stderr, "Error reading byte %d in intel hex file, line %d\n", j, i);
100 writechar(datamem,do_verify,address+j,byte);
103 if(fscanf(fd, "%2x", &checksum2) < 1) {
104 fprintf(stderr, "Error reading checksum in intel hex file, line %d\n", i);
109 if((0x100 - (checksum1 & 0xFF)) != checksum2) {
110 fprintf(stderr, "Warning: checksums do NOT match in intel hex file, line %d\n"
112 "File may be corrupt\n", i, 0x100 - (checksum1 & 0xFF), checksum2);
118 if(byte != '\n' && byte != '\r') {
131 int main(int argc, const char **argv)
133 char datamem = 0, codemem = 0, verbose = 0, do_verify = 0, ignore_chk = 0;
136 char *format = "auto";
138 char c, print_usage = 1;
139 struct poptOption long_options[] = {
141 { "data-memory", 'd', POPT_ARG_VAL, &datamem, 0, "Write specified file to data memory" },
142 { "code-memory", 'c', POPT_ARG_VAL, &codemem, 0, "Write specified file to code memory (default)" },
143 { "format", 'f', POPT_ARG_STRING, &format, 0, "File format (auto,hex,bin)" },
144 { "ignore-chk", 'i', POPT_ARG_VAL, &ignore_chk, 0, "Don't wait for CHK to confirm RST" },
145 { "verify", 0, POPT_ARG_VAL, &do_verify, 0, "Verify written bytes" },
146 { "port", 'p', POPT_ARG_STRING, NULL, 'p', "Address of serial port to use [3f8]" },
147 { "rcfile", 'r', POPT_ARG_STRING, &rcfile, 0, "Use rc file from specified location" },
148 { "verbose", 'v', POPT_ARG_VAL, &verbose, 0, "Be verbose" },
154 pc = poptGetContext(NULL, argc, argv, long_options, POPT_CONTEXT_KEEP_FIRST);
155 poptSetOtherOptionHelp(pc, "command [file-to-write]");
157 while ((c = poptGetNextOpt(pc)) != -1) {
159 case 'p': newserport = strtol(poptGetOptArg(pc), NULL, 16); break;
164 rcfile = malloc(strlen(getenv("HOME")) + 20);
165 snprintf(rcfile, strlen(getenv("HOME")) + 20, "%s/.at89progrc", getenv("HOME"));
169 if(readrcfile(rcfile) != 0) return 1;
172 if(newserport != -1)serport = newserport;
174 if(ioperm(serport, 7, 1) == -1)
177 fprintf(stderr, "Run at89prog with IO port access\n");
181 if(ioperm(0x80, 1, 1) == -1)
187 signal(SIGINT, quit);
188 signal(SIGSEGV, quit);
190 poptGetArg(pc); /* drop argv[0] */
198 if(!activate() && !ignore_chk)
200 fprintf(stderr, "RST set, but CHK is low\n");
204 if(!strcmp(poptPeekArg(pc), "reset"))
208 if(verbose) fprintf(stderr, "Microcontroller has been reset.\n");
209 } else if(!strcmp(poptPeekArg(pc), "erase"))
214 if(verbose) fprintf(stderr, "Microcontroller memory has been erased.\n");
215 } else if(!strcmp(poptPeekArg(pc), "lock"))
219 lock_level = atoi(poptGetArg(pc));
224 if(verbose) fprintf(stderr, "Locked at level %d\n", lock_level);
225 } else if(!strcmp(poptPeekArg(pc), "writefile"))
230 while(poptPeekArg(pc)) {
232 const char *filename = poptGetArg(pc);
234 if(!strcmp(filename, "-")) fd = stdin;
236 fd = fopen(filename, "r");
238 fprintf(stderr, "Unable to open file %s, ignoring.\n", filename);
243 firstchar = getc(fd);
244 ungetc(firstchar, fd);
246 if(!strcmp(format, "hex") || (!strcmp(format, "auto") && firstchar == ':'))errors = writehex(fd, do_verify, datamem);
247 else if(!strcmp(format, "auto") || !strcmp(format, "bin"))errors = writebin(fd, do_verify, datamem);
249 fprintf(stderr, "Unknown format %s, ignoring file\n", format);
254 if(!errors)fprintf(stderr, "File %s programmed correctly\n", filename);
255 else fprintf(stderr, "File %s programmed with %d errors\n", filename, errors);
258 } else if(!strcmp(poptPeekArg(pc), "readfile")) {
263 if(!poptPeekArg(pc)) {
264 fprintf(stderr, "readfile needs at least one argument (number of bytes to read\n");
269 len = atol(poptGetArg(pc));
271 if(!poptPeekArg(pc)) fd = stdout;
273 fd = fopen(poptGetArg(pc), "w+");
281 if(!strcmp(format, "bin"))fprintf(stderr, "Warning: writing in binary mode\n");
283 for(i = 0; i < len; i++) {
284 if(datamem)fputc(readdata(i), fd);
285 else fputc(readcode(i), fd);
291 if(verbose)fprintf(stderr, "%d bytes read\n", len);
293 } else if(!strcmp(poptPeekArg(pc), "writebyte")) {
297 if(!poptPeekArg(pc)) {
298 fprintf(stderr, "writebyte requires 2 arguments\n");
302 address = strtol(poptGetArg(pc), NULL, 16);
304 if(!poptPeekArg(pc)) {
305 fprintf(stderr, "writebyte requires 2 arguments\n");
309 byte = strtol(poptGetArg(pc), NULL, 16);
311 writechar(datamem, do_verify, address, byte);
312 if(verbose)fprintf(stderr, "%x written to %x\n", byte, address);
313 } else if(!strcmp(poptPeekArg(pc), "readbyte")) {
317 if(!poptPeekArg(pc)) {
318 fprintf(stderr, "writebyte requires 2 arguments\n");
322 address = strtol(poptGetArg(pc), NULL, 16);
324 if(datamem) printf("%x\n", readdata(address));
325 else printf("%x\n", readcode(address));
326 } else if(!strcmp(poptPeekArg(pc), "version")) {
327 fprintf(stderr, "at89prog - a AT89S8252 programmer over the serial port\n");
328 fprintf(stderr, " Version "VERSION"\n");
329 fprintf(stderr, " (C) 2003 Jelmer Vernooij <jelmer@samba.org>\n");
330 fprintf(stderr, " Published under the GNU GPL\n");
333 fprintf(stderr, "Unknown command %s\n", poptGetArg(pc));