3 (c) 2003-2004 Jelmer Vernooij <jelmer@samba.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <sys/types.h>
36 char *backendname = "serial";
39 void usage(poptContext pc)
41 poptPrintHelp(pc, stderr, 0);
42 fprintf(stderr, "\nAvailable commands: \n"
46 "\twritefile [file] ...\n"
47 "\treadfile <len> [file] ...\n"
48 "\twritebyte <address> <byte>\n"
49 "\treadbyte <address>\n"
57 fprintf(stderr, "Received signal, exiting...\n");
61 void writechar(char datamem, char do_verify, int address, int byte)
64 if(datamem)writedata(address, byte);
65 else writecode(address, byte);
68 if(datamem)d = readdata(address);
69 else d = readcode(address);
72 fprintf(stderr, "Error verifying byte at offset 0x%x\n", address);
79 int writebin(FILE *fd, char do_verify, char datamem)
84 writechar(datamem, do_verify, i, fgetc(fd));
86 if(progress)fputc('.', stderr);
88 if(progress)fputc('\n', stderr);
92 int writehex(FILE *fd, char do_verify, char datamem)
94 int length; int addr1, addr2; int type;
97 int checksum1, checksum2;
104 if(fscanf(fd, ":%2x%2x%2x%2x", &length, &addr1, &addr2, &type) < 3) {
105 fprintf(stderr, "Error reading intel hex file, line %d\n", i);
115 address = addr1 * 0x100 + addr2;
119 if(type == 2) continue;
121 for(j = 0; j < length; j++) {
122 if(fscanf(fd, "%2x", &byte) < 1) {
123 fprintf(stderr, "Error reading byte %d in intel hex file, line %d\n", j, i);
129 writechar(datamem,do_verify,address+j,byte);
132 if(fscanf(fd, "%2x", &checksum2) < 1) {
133 fprintf(stderr, "Error reading checksum in intel hex file, line %d\n", i);
139 checksum1 = (~checksum1 + 1) & 0xFF;
141 if(checksum1 != checksum2) {
142 fprintf(stderr, "Warning: checksums do NOT match in intel hex file, line %d\n"
144 "File may be corrupt\n", i, checksum1, checksum2);
150 if(byte != '\n' && byte != '\r') {
156 if(progress)fputc('.', stderr);
158 if(progress)fputc('\n', stderr);
163 int read_pin_configuration(char *name)
165 char bit[10], pin[10];
167 FILE *fd = fopen(name, "r");
170 fprintf(stderr, "Can't open %s!\n"
171 "Type 'man 5 at89prog' for information about the RC file format\n", name);
179 if(fscanf(fd, "%4s %6s\n", bit, pin) < 2) {
180 fprintf(stderr, "Invalid line %d in %s, ignoring\n", line, name);
184 switch(SetPinVariable(bit, pin)) {
186 fprintf(stderr, "Invalid configuration variable '%s' at line %d in %s, ignoring\n", bit, line, name);
189 fprintf(stderr, "Can't open %s!\n"
190 "Type 'man 5 at89prog' for information about the RC file format\n", name);
198 if(fscanf(fd, "%4s %6s\n", bit, pin) < 2) {
199 fprintf(stderr, "Invalid line %d in %s, ignoring\n", line, name);
203 switch(SetPinVariable(bit, pin)) {
205 fprintf(stderr, "Invalid configuration variable '%s' at line %d in %s, ignoring\n", bit, line, name);
209 fprintf(stderr, "Invalid value '%s' for configuration variable '%s' at line %d in %s, ignoring\n", pin, bit, line, name);
221 int main(int argc, const char **argv)
223 int datamem = 0, codemem = 0, verbose = 0, do_verify = 0, ignore_chk = 0;
225 char *format = "auto";
227 char c, print_usage = 1;
228 struct poptOption long_options[] = {
230 { "data-memory", 'd', POPT_ARG_NONE, &datamem, 0, "Write specified file to data memory" },
231 { "code-memory", 'c', POPT_ARG_NONE, &codemem, 0, "Write specified file to code memory (default)" },
232 { "format", 'f', POPT_ARG_STRING, &format, 0, "File format (auto,hex,bin)" },
233 { "ignore-chk", 'i', POPT_ARG_NONE, &ignore_chk, 0, "Don't wait for CHK to confirm RST" },
234 { "progress", 'P', POPT_ARG_NONE, &progress, 0, "Print progress dots" },
235 { "verify", 'V', POPT_ARG_NONE, &do_verify, 0, "Verify written bytes" },
236 { "type", 't', POPT_ARG_STRING, &backendname, 't', "Type of port to use (serial, parallel or serial-raw)" },
237 { "port", 'p', POPT_ARG_STRING, &location, 'p', "Address of port to use" },
238 { "rcfile", 'r', POPT_ARG_STRING, &rcfile, 0, "Use rc file from specified location" },
239 { "verbose", 'v', POPT_ARG_NONE, &verbose, 0, "Be verbose" },
245 pc = poptGetContext(NULL, argc, argv, long_options, 0);
246 poptSetOtherOptionHelp(pc, "command [file-to-write]");
248 while ((c = poptGetNextOpt(pc)) != -1) { }
257 rcfile = malloc(strlen(getenv("HOME")) + 20);
258 snprintf(rcfile, strlen(getenv("HOME")) + 20, "%s/.at89progrc", getenv("HOME"));
262 if(read_pin_configuration(rcfile) != 0) return 1;
265 if(LoadPinBackend(backendname) != 0) return 1;
266 if(port)SetPinVariable(NULL, port);
267 if(BackendInit() != 0) return 1;
269 signal(SIGINT, quit);
270 signal(SIGSEGV, quit);
272 if(!activate() && !ignore_chk)
274 fprintf(stderr, "RST set, but CHK is low\n");
278 if(!strcmp(poptPeekArg(pc), "reset"))
282 if(verbose) fprintf(stderr, "Microcontroller has been reset.\n");
283 } else if(!strcmp(poptPeekArg(pc), "erase"))
288 if(verbose) fprintf(stderr, "Microcontroller memory has been erased.\n");
289 } else if(!strcmp(poptPeekArg(pc), "lock"))
293 lock_level = atoi(poptGetArg(pc));
298 if(verbose) fprintf(stderr, "Locked at level %d\n", lock_level);
299 } else if(!strcmp(poptPeekArg(pc), "writefile"))
304 while(poptPeekArg(pc)) {
306 const char *filename = poptGetArg(pc);
308 if(!strcmp(filename, "-")) fd = stdin;
310 fd = fopen(filename, "r");
312 fprintf(stderr, "Unable to open file %s, ignoring.\n", filename);
317 firstchar = getc(fd);
318 ungetc(firstchar, fd);
320 if(!strcmp(format, "hex") || (!strcmp(format, "auto") && firstchar == ':'))errors = writehex(fd, do_verify, datamem);
321 else if(!strcmp(format, "auto") || !strcmp(format, "bin"))errors = writebin(fd, do_verify, datamem);
323 fprintf(stderr, "Unknown format %s, ignoring file\n", format);
328 if(!errors && verbose)fprintf(stderr, "File %s programmed correctly\n", filename);
329 else if(verbose)fprintf(stderr, "File %s programmed with %d errors\n", filename, errors);
332 } else if(!strcmp(poptPeekArg(pc), "readfile")) {
337 if(!poptPeekArg(pc)) {
338 fprintf(stderr, "readfile needs at least one argument (number of bytes to read\n");
343 len = atol(poptGetArg(pc));
345 if(!poptPeekArg(pc)) fd = stdout;
347 fd = fopen(poptGetArg(pc), "w+");
355 if(!strcmp(format, "bin"))fprintf(stderr, "Warning: writing in binary mode\n");
357 for(i = 0; i < len; i++) {
358 if(datamem)fputc(readdata(i), fd);
359 else fputc(readcode(i), fd);
360 if(progress)fputc('.', stderr);
363 if(progress)fputc('\n', stderr);
365 if(verbose)fprintf(stderr, "%d bytes read\n", len);
367 } else if(!strcmp(poptPeekArg(pc), "writebyte")) {
371 if(!poptPeekArg(pc)) {
372 fprintf(stderr, "writebyte requires 2 arguments\n");
376 address = strtol(poptGetArg(pc), NULL, 16);
378 if(!poptPeekArg(pc)) {
379 fprintf(stderr, "writebyte requires 2 arguments\n");
383 byte = strtol(poptGetArg(pc), NULL, 16);
385 writechar(datamem, do_verify, address, byte);
386 if(verbose)fprintf(stderr, "%x written to %x\n", byte, address);
387 } else if(!strcmp(poptPeekArg(pc), "readbyte")) {
391 if(!poptPeekArg(pc)) {
392 fprintf(stderr, "readbyte requires an argument\n");
396 address = strtol(poptGetArg(pc), NULL, 16);