main.c
来自「这是一个非常有价值的参考代码」· C语言 代码 · 共 1,580 行 · 第 1/3 页
C
1,580 行
/* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2000-2005 Brian S. Dean <bsd@bsdhome.com> * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* $Id: main.c,v 1.110 2005/09/22 14:14:14 joerg_wunsch Exp $ *//* * Code to program an Atmel AVR device through one of the supported * programmers. * * For parallel port connected programmers, the pin definitions can be * changed via a config file. See the config file for instructions on * how to add a programmer definition. * */#include "ac_cfg.h"#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <fcntl.h>#include <limits.h>#include <string.h>#include <time.h>#include <unistd.h>#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include "avr.h"#include "config.h"#include "confwin.h"#include "fileio.h"#include "lists.h"#include "par.h"#include "pindefs.h"#include "term.h"#include "safemode.h"enum { DEVICE_READ, DEVICE_WRITE, DEVICE_VERIFY};typedef struct update_t { char * memtype; int op; char * filename; int format;} UPDATE;/* Get VERSION from ac_cfg.h */char * version = VERSION;int verbose; /* verbose output */int quell_progress; /* un-verebose output */char * progname;char progbuf[PATH_MAX]; /* temporary buffer of spaces the same length as progname; used for lining up multiline messages */PROGRAMMER * pgm = NULL;LISTID updates;/* * global options */int do_cycles; /* track erase-rewrite cycles *//* * usage message */void usage(void){ fprintf(stderr, "Usage: %s [options]\n" "Options:\n" " -p <partno> Required. Specify AVR device.\n" " -b <baudrate> Override RS-232 baud rate.\n" " -B <bitclock> Specify JTAG bit clock period (us).\n" " -C <config-file> Specify location of configuration file.\n" " -c <programmer> Specify programmer type.\n" " -D Disable auto erase for flash memory\n" " -P <port> Specify connection port.\n" " -F Override invalid signature check.\n" " -e Perform a chip erase.\n" " -U <memtype>:r|w|v:<filename>[:format]\n" " Memory operation specification.\n" " Multiple -U options are allowed, each request\n" " is performed in the order specified.\n" " -n Do not write anything to the device.\n" " -V Do not verify.\n" " -u Disable safemode, default when running from a script.\n" " -s Silent safemode operation, will not ask you if\n" " fuses should be changed back.\n" " -t Enter terminal mode.\n" " -E <exitspec>[,<exitspec>] List programmer exit specifications.\n" " -y Count # erase cycles in EEPROM.\n" " -Y <number> Initialize erase cycle # in EEPROM.\n" " -v Verbose output. -v -v for more.\n" " -q Quell progress output. -q -q for less.\n" " -? Display this usage.\n" "\navrdude project: <URL:http://savannah.nongnu.org/projects/avrdude>\n" ,progname);}/* * parse the -E string */int getexitspecs(char *s, int *set, int *clr){ char *cp; while ((cp = strtok(s, ","))) { if (strcmp(cp, "reset") == 0) { *clr |= par_getpinmask(pgm->pinno[PIN_AVR_RESET]); } else if (strcmp(cp, "noreset") == 0) { *set |= par_getpinmask(pgm->pinno[PIN_AVR_RESET]); } else if (strcmp(cp, "vcc") == 0) { if (pgm->pinno[PPI_AVR_VCC]) *set |= pgm->pinno[PPI_AVR_VCC]; } else if (strcmp(cp, "novcc") == 0) { if (pgm->pinno[PPI_AVR_VCC]) *clr |= pgm->pinno[PPI_AVR_VCC]; } else { return -1; } s = 0; /* strtok() should be called with the actual string only once */ } return 0;}int read_config(char * file){ FILE * f; f = fopen(file, "r"); if (f == NULL) { fprintf(stderr, "%s: can't open config file \"%s\": %s\n", progname, file, strerror(errno)); return -1; } lineno = 1; infile = file; yyin = f; yyparse(); fclose(f); return 0;}void programmer_display(char * p){ fprintf(stderr, "%sProgrammer Type : %s\n", p, pgm->type); fprintf(stderr, "%sDescription : %s\n", p, pgm->desc); pgm->display(pgm, p);}void verify_pin_assigned(int pin, char * desc){ if (pgm->pinno[pin] == 0) { fprintf(stderr, "%s: error: no pin has been assigned for %s\n", progname, desc); exit(1); }}PROGRAMMER * locate_programmer(LISTID programmers, char * configid){ LNODEID ln1, ln2; PROGRAMMER * p = NULL; char * id; int found; found = 0; for (ln1=lfirst(programmers); ln1 && !found; ln1=lnext(ln1)) { p = ldata(ln1); for (ln2=lfirst(p->id); ln2 && !found; ln2=lnext(ln2)) { id = ldata(ln2); if (strcasecmp(configid, id) == 0) found = 1; } } if (found) return p; return NULL;}void list_programmers(FILE * f, char * prefix, LISTID programmers){ LNODEID ln1; PROGRAMMER * p; for (ln1=lfirst(programmers); ln1; ln1=lnext(ln1)) { p = ldata(ln1); fprintf(f, "%s%-8s = %-30s [%s:%d]\n", prefix, (char *)ldata(lfirst(p->id)), p->desc, p->config_file, p->lineno); } return;}typedef void (*FP_UpdateProgress)(int percent, double etime, char *hdr);static FP_UpdateProgress update_progress;/* * Report the progress of a read or write operation from/to the * device. * * The first call of report_progress() should look like this (for a write op): * * report_progress (0, 1, "Writing"); * * Then hdr should be passed NULL on subsequent calls while the * operation is progressing. Once the operation is complete, a final * call should be made as such to ensure proper termination of the * progress report: * * report_progress (1, 1, NULL); * * It would be nice if we could reduce the usage to one and only one * call for each of start, during and end cases. As things stand now, * that is not possible and makes maintenance a bit more work. */void report_progress (int completed, int total, char *hdr){ static int last = 0; static double start_time; int percent = (completed * 100) / total; struct timeval tv; double t; if (update_progress == NULL) return; gettimeofday(&tv, NULL); t = tv.tv_sec + ((double)tv.tv_usec)/1000000; if (hdr) { last = 0; start_time = t; update_progress (percent, t - start_time, hdr); } if (percent > 100) percent = 100; if (percent > last) { last = percent; update_progress (percent, t - start_time, hdr); } if (percent == 100) last = 0; /* Get ready for next time. */}static void update_progress_tty (int percent, double etime, char *hdr){ static char hashes[51]; static char *header; static int last = 0; int i; hashes[50] = 0; memset (hashes, ' ', 50); for (i=0; i<percent; i+=2) { hashes[i/2] = '#'; } if (hdr) { fprintf (stderr, "\n"); last = 0; header = hdr; } if (last == 0) { fprintf(stderr, "\r%s | %s | %d%% %0.2fs", header, hashes, percent, etime); } if (percent == 100) { last = 1; fprintf (stderr, "\n\n"); }}static void update_progress_no_tty (int percent, double etime, char *hdr){ static int done = 0; static int last = 0; int cnt = (percent>>1)*2; if (hdr) { fprintf (stderr, "\n%s | ", hdr); last = 0; done = 0; } else { while ((cnt > last) && (done == 0)) { fprintf (stderr, "#"); cnt -= 2; } } if ((percent == 100) && (done == 0)) { fprintf (stderr, " | 100%% %0.2fs\n\n", etime); last = 0; done = 1; } else last = (percent>>1)*2; /* Make last a multiple of 2. */}UPDATE * parse_op(char * s){ char buf[1024]; char * p, * cp, c; UPDATE * upd; int i; size_t fnlen; upd = (UPDATE *)malloc(sizeof(UPDATE)); if (upd == NULL) { fprintf(stderr, "%s: out of memory\n", progname); exit(1); } i = 0; p = s; while ((i < (sizeof(buf)-1) && *p && (*p != ':'))) buf[i++] = *p++; if (*p != ':') { fprintf(stderr, "%s: invalid update specification\n", progname); free(upd); return NULL; } buf[i] = 0; upd->memtype = (char *)malloc(strlen(buf)+1); if (upd->memtype == NULL) { fprintf(stderr, "%s: out of memory\n", progname); exit(1); } strcpy(upd->memtype, buf); p++; if (*p == 'r') { upd->op = DEVICE_READ; } else if (*p == 'w') { upd->op = DEVICE_WRITE; } else if (*p == 'v') { upd->op = DEVICE_VERIFY; } else { fprintf(stderr, "%s: invalid I/O mode '%c' in update specification\n", progname, *p); fprintf(stderr, " allowed values are:\n" " r = read device\n" " w = write device\n" " v = verify device\n"); free(upd->memtype); free(upd); return NULL; } p++; if (*p != ':') { fprintf(stderr, "%s: invalid update specification\n", progname); free(upd->memtype); free(upd); return NULL; } p++; /* * Now, parse the filename component. Instead of looking for the * leftmost possible colon delimiter, we look for the rightmost one. * If we found one, we do have a trailing :format specifier, and * process it. Otherwise, the remainder of the string is our file * name component. That way, the file name itself is allowed to * contain a colon itself (e. g. C:/some/file.hex), except the * optional format specifier becomes mandatory then. */ cp = p; p = strrchr(cp, ':'); if (p == NULL) { upd->format = FMT_AUTO; fnlen = strlen(cp); upd->filename = (char *)malloc(fnlen + 1); } else { fnlen = p - cp; upd->filename = (char *)malloc(fnlen +1); c = *++p; if (c && p[1]) /* More than one char - force failure below. */ c = '?'; switch (c) { case 'a': upd->format = FMT_AUTO; break; case 's': upd->format = FMT_SREC; break; case 'i': upd->format = FMT_IHEX; break; case 'r': upd->format = FMT_RBIN; break; case 'm': upd->format = FMT_IMM; break; default: fprintf(stderr, "%s: invalid file format '%s' in update specifier\n", progname, p); free(upd->memtype); free(upd); return NULL; } } if (upd->filename == NULL) { fprintf(stderr, "%s: out of memory\n", progname); free(upd->memtype); free(upd); return NULL; } memcpy(upd->filename, cp, fnlen); upd->filename[fnlen] = 0; return upd;}UPDATE * dup_update(UPDATE * upd){ UPDATE * u; u = (UPDATE *)malloc(sizeof(UPDATE)); if (u == NULL) { fprintf(stderr, "%s: out of memory\n", progname); exit(1); } memcpy(u, upd, sizeof(UPDATE)); u->memtype = strdup(upd->memtype); u->filename = strdup(upd->filename); return u;}UPDATE * new_update(int op, char * memtype, int filefmt, char * filename){ UPDATE * u; u = (UPDATE *)malloc(sizeof(UPDATE)); if (u == NULL) { fprintf(stderr, "%s: out of memory\n", progname); exit(1); } u->memtype = strdup(memtype); u->filename = strdup(filename); u->op = op; u->format = filefmt; return u;}int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite, int verify){ struct avrpart * v; AVRMEM * mem; int size, vsize;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?