2001-01-19 02:46:50 +00:00
|
|
|
/*
|
2001-10-01 14:04:46 +00:00
|
|
|
* Copyright 2001 Brian S. Dean <bsd@bsdhome.com>
|
2001-01-19 02:46:50 +00:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``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 BRIAN S. DEAN 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* $Id$ */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Code to program an Atmel AVR AT90S device using the parallel port.
|
|
|
|
*
|
2001-10-01 14:04:46 +00:00
|
|
|
* Pin definitions can be changed via a config file. Below is the
|
2001-10-14 23:17:26 +00:00
|
|
|
* default pin configuration in the absence of a config definition
|
|
|
|
* which lists "default" as one of its ids.
|
2001-01-19 02:46:50 +00:00
|
|
|
*
|
2001-01-24 18:45:58 +00:00
|
|
|
* Parallel Port Programmer Function
|
|
|
|
* ------------- -----------------------------
|
|
|
|
* Pins 2-5 -> Vcc (see note below)
|
|
|
|
* Pin 7 -> AVR /RESET
|
|
|
|
* Pin 8 -> AVR SCK (clock input)
|
|
|
|
* Pin 9 -> AVR MOSI (instruction in)
|
|
|
|
* Pin 10 <- AVR MISO (data out)
|
|
|
|
* Pin 18 Signal Ground
|
|
|
|
*
|
2001-10-14 23:17:26 +00:00
|
|
|
* Additionally, the following connections can be made to enable
|
|
|
|
* additional features, however, to enable these features use the
|
|
|
|
* pin configuration id "alf" ("-c alf" on the command line):
|
2001-01-24 18:45:58 +00:00
|
|
|
*
|
|
|
|
* Parallel Port Programmer Function
|
|
|
|
* ------------- -----------------------------
|
|
|
|
* Pin 1 STATUS LED, active low (program or verify error)
|
|
|
|
* Pin 6 -> /ENABLE ('367 bus driver)
|
|
|
|
* Pin 14 STATUS LED, active low (ready)
|
|
|
|
* Pin 16 STATUS LED, active low (programming)
|
|
|
|
* Pin 17 STATUS LED, active low (verifying)
|
|
|
|
*
|
|
|
|
* Pin 6 can be tied to the enable line of a 74HC367 in order to
|
|
|
|
* isolate and buffer the data to and from the PC parallel port.
|
|
|
|
* This is useful for connecting to a device in-circuit, and keeps
|
|
|
|
* the state of the parallel port pins from interfering with the
|
|
|
|
* normal operation of the target system. When programming is
|
|
|
|
* complete, this pin is driven high, causing to pins of the '367 to
|
|
|
|
* float.
|
2001-01-19 02:46:50 +00:00
|
|
|
*
|
|
|
|
* NOTE on Vcc connection: make sure your parallel port can supply an
|
2001-01-24 18:45:58 +00:00
|
|
|
* adequate amount of current to power your device. 6-10 mA per pin
|
|
|
|
* is common for parallel port signal lines, but is not guaranteed,
|
|
|
|
* especially for notebook computers. For additional power, use
|
|
|
|
* multiple pins tied together with Schottky diodes. If in doubt,
|
|
|
|
* don't risk damaging your parallel port, use an external power
|
|
|
|
* supply.
|
|
|
|
*
|
2001-01-19 02:46:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2001-09-19 17:04:25 +00:00
|
|
|
#include <stdlib.h>
|
2001-01-19 02:46:50 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
2001-01-26 20:34:08 +00:00
|
|
|
#include <time.h>
|
2001-01-19 02:46:50 +00:00
|
|
|
#include <unistd.h>
|
2001-09-19 17:04:25 +00:00
|
|
|
#include <ctype.h>
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
#include "avr.h"
|
2001-10-14 23:17:26 +00:00
|
|
|
#include "config.h"
|
2001-01-19 02:46:50 +00:00
|
|
|
#include "fileio.h"
|
2001-01-24 19:10:34 +00:00
|
|
|
#include "pindefs.h"
|
2001-01-19 02:46:50 +00:00
|
|
|
#include "ppi.h"
|
|
|
|
#include "term.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define DEFAULT_PARALLEL "/dev/ppi0"
|
|
|
|
|
2001-01-26 20:34:08 +00:00
|
|
|
extern char * avr_version;
|
2001-10-14 23:17:26 +00:00
|
|
|
extern char * config_version;
|
2001-01-26 20:34:08 +00:00
|
|
|
extern char * fileio_version;
|
2001-10-14 23:17:26 +00:00
|
|
|
extern char * lists_version;
|
2001-01-26 20:34:08 +00:00
|
|
|
extern char * main_version;
|
|
|
|
extern char * ppi_version;
|
|
|
|
extern char * term_version;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
#define N_MODULES 7
|
2001-01-26 20:34:08 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
char ** modules[N_MODULES] = {
|
|
|
|
&avr_version,
|
|
|
|
&config_version,
|
|
|
|
&fileio_version,
|
|
|
|
&lists_version,
|
2001-01-26 20:34:08 +00:00
|
|
|
&main_version,
|
|
|
|
&ppi_version,
|
|
|
|
&term_version
|
|
|
|
};
|
|
|
|
|
2001-10-31 02:18:08 +00:00
|
|
|
char * version = "1.4.4";
|
2001-01-26 20:34:08 +00:00
|
|
|
|
|
|
|
char * main_version = "$Id$";
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
char * progname;
|
|
|
|
char progbuf[PATH_MAX]; /* temporary buffer of spaces the same
|
|
|
|
length as progname; used for lining up
|
|
|
|
multiline messages */
|
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
PROGRAMMER * pgm = NULL;
|
|
|
|
|
|
|
|
PROGRAMMER compiled_in_pgm;
|
|
|
|
|
2001-09-19 17:04:25 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
/*
|
|
|
|
* usage message
|
|
|
|
*/
|
2001-10-13 03:13:13 +00:00
|
|
|
void usage(void)
|
2001-01-19 02:46:50 +00:00
|
|
|
{
|
2001-01-20 04:28:49 +00:00
|
|
|
fprintf(stderr,
|
2001-10-14 23:17:26 +00:00
|
|
|
"\nUsage: %s -p partno [-e] [-E exitspec[,exitspec]] [-f format] "
|
|
|
|
"[-F]\n"
|
2001-01-26 20:34:08 +00:00
|
|
|
" %s[-i filename] [-m memtype] [-o filename] [-P parallel] "
|
2001-10-14 23:17:26 +00:00
|
|
|
"[-t]\n"
|
|
|
|
" %s[-c programmer] [-C config-file] [-v [-v]] [-n]\n\n",
|
|
|
|
progname, progbuf, progbuf);
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* parse the -E string
|
|
|
|
*/
|
2001-10-13 03:13:13 +00:00
|
|
|
int getexitspecs(char *s, int *set, int *clr)
|
2001-01-19 02:46:50 +00:00
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
while ((cp = strtok(s, ","))) {
|
|
|
|
if (strcmp(cp, "reset") == 0) {
|
2001-10-14 23:17:26 +00:00
|
|
|
*clr |= ppi_getpinmask(pgm->pinno[PIN_AVR_RESET]);
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
else if (strcmp(cp, "noreset") == 0) {
|
2001-10-14 23:17:26 +00:00
|
|
|
*set |= ppi_getpinmask(pgm->pinno[PIN_AVR_RESET]);
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
else if (strcmp(cp, "vcc") == 0) {
|
2001-10-14 23:17:26 +00:00
|
|
|
if (pgm->pinno[PPI_AVR_VCC])
|
|
|
|
*set |= pgm->pinno[PPI_AVR_VCC];
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
else if (strcmp(cp, "novcc") == 0) {
|
2001-10-14 23:17:26 +00:00
|
|
|
if (pgm->pinno[PPI_AVR_VCC])
|
|
|
|
*clr |= pgm->pinno[PPI_AVR_VCC];
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
s = 0; /* strtok() should be called with the actual string only once */
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-10-13 03:13:13 +00:00
|
|
|
int parse_cvsid(char * cvsid, char * name, char * rev, char * datetime)
|
2001-01-26 20:34:08 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
if (strncmp(cvsid,"$Id: ",5) != 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
name[0] = 0;
|
|
|
|
rev[0] = 0;
|
|
|
|
datetime[0] = 0;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
j = 5;
|
|
|
|
while (cvsid[j] && cvsid[j] != ',')
|
|
|
|
name[i++] = cvsid[j++];
|
|
|
|
name[i] = 0;
|
|
|
|
|
|
|
|
while (cvsid[j] && cvsid[j] != ' ')
|
|
|
|
j++;
|
|
|
|
|
|
|
|
if (cvsid[j])
|
|
|
|
j++;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (cvsid[j] && cvsid[j] != ' ')
|
|
|
|
rev[i++] = cvsid[j++];
|
|
|
|
rev[i] = 0;
|
|
|
|
|
|
|
|
if (cvsid[j])
|
|
|
|
j++;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (cvsid[j] && cvsid[j] != ' ')
|
|
|
|
datetime[i++] = cvsid[j++];
|
|
|
|
if (cvsid[j] == ' ') {
|
|
|
|
datetime[i++] = cvsid[j++];
|
|
|
|
while (cvsid[j] && cvsid[j] != ' ')
|
|
|
|
datetime[i++] = cvsid[j++];
|
|
|
|
}
|
|
|
|
datetime[i] = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-10-13 03:13:13 +00:00
|
|
|
int print_module_versions(FILE * outf, char * timestamp)
|
2001-01-26 20:34:08 +00:00
|
|
|
{
|
|
|
|
char name[64], rev[16], datetime[64];
|
|
|
|
int y, m, d, h, min, s;
|
|
|
|
int i;
|
|
|
|
int rc;
|
|
|
|
int maxtime;
|
|
|
|
struct tm t;
|
|
|
|
time_t now;
|
|
|
|
|
|
|
|
maxtime = 0;
|
|
|
|
for (i=0; i<N_MODULES; i++) {
|
|
|
|
parse_cvsid(*modules[i], name, rev, datetime);
|
|
|
|
rc = sscanf(datetime, "%d/%d/%d %d:%d:%d", &y, &m, &d, &h, &min, &s);
|
|
|
|
if (rc != 6) {
|
|
|
|
fprintf(stderr, "%s: module version scan error, rc=%d\n", progname, rc);
|
|
|
|
}
|
2001-01-26 20:45:05 +00:00
|
|
|
else if (timestamp) {
|
2001-01-26 20:34:08 +00:00
|
|
|
now = time(NULL);
|
|
|
|
gmtime_r(&now, &t);
|
|
|
|
t.tm_sec = s;
|
|
|
|
t.tm_min = min;
|
|
|
|
t.tm_hour = h;
|
|
|
|
t.tm_mday = d;
|
|
|
|
t.tm_mon = m-1;
|
|
|
|
t.tm_year = y-1900;
|
|
|
|
now = timegm(&t);
|
2001-01-26 20:45:05 +00:00
|
|
|
if (now > maxtime) {
|
2001-01-26 20:34:08 +00:00
|
|
|
maxtime = now;
|
2001-01-26 20:45:05 +00:00
|
|
|
strcpy(timestamp, datetime);
|
|
|
|
strcat(timestamp, " GMT");
|
|
|
|
}
|
2001-01-26 20:34:08 +00:00
|
|
|
}
|
|
|
|
if (outf)
|
|
|
|
fprintf(outf, " %-10s %-5s %s\n", name, rev, datetime);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outf)
|
|
|
|
fprintf(outf, "\n");
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
gmtime_r(&maxtime, &t);
|
|
|
|
fprintf(stderr, "Latest revision date is %04d/%02d/%02d %02d:%02d:%02d\n",
|
|
|
|
t.tm_year+1900, t.tm_mon, t.tm_mday,
|
|
|
|
t.tm_hour, t.tm_min, t.tm_sec);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (outf)
|
|
|
|
fprintf(outf, "\n");
|
|
|
|
|
2001-01-26 20:45:05 +00:00
|
|
|
return 0;
|
2001-01-26 20:34:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-09-19 17:04:25 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
int read_config(char * file)
|
2001-09-19 17:04:25 +00:00
|
|
|
{
|
|
|
|
FILE * f;
|
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
f = fopen(file, "r");
|
2001-09-19 17:04:25 +00:00
|
|
|
if (f == NULL) {
|
|
|
|
fprintf(stderr, "%s: can't open config file \"%s\": %s\n",
|
2001-10-16 02:47:55 +00:00
|
|
|
progname, file, strerror(errno));
|
2001-09-19 17:04:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
infile = file;
|
|
|
|
yyin = f;
|
2001-09-19 17:04:25 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
yyparse();
|
2001-09-19 17:04:25 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
fclose(f);
|
2001-09-19 17:04:25 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
return 0;
|
2001-09-19 17:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-09-20 03:19:31 +00:00
|
|
|
static char vccpins_buf[64];
|
|
|
|
char * vccpins_str(unsigned int pmask)
|
|
|
|
{
|
|
|
|
unsigned int mask;
|
|
|
|
int pin;
|
|
|
|
char b2[8];
|
|
|
|
char * b;
|
|
|
|
|
|
|
|
b = vccpins_buf;
|
|
|
|
|
|
|
|
b[0] = 0;
|
|
|
|
for (pin = 2, mask = 1; mask < 0x80; mask = mask << 1, pin++) {
|
|
|
|
if (pmask & mask) {
|
|
|
|
sprintf(b2, "%d", pin);
|
|
|
|
if (b[0] != 0)
|
|
|
|
strcat(b, ",");
|
|
|
|
strcat(b, b2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
void pinconfig_display(char * p)
|
2001-09-19 17:04:25 +00:00
|
|
|
{
|
2001-09-20 03:19:31 +00:00
|
|
|
char vccpins[64];
|
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
if (pgm->pinno[PPI_AVR_VCC]) {
|
2001-09-20 03:19:31 +00:00
|
|
|
snprintf(vccpins, sizeof(vccpins), " = pins %s",
|
2001-10-14 23:17:26 +00:00
|
|
|
vccpins_str(pgm->pinno[PPI_AVR_VCC]));
|
2001-09-20 03:19:31 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
vccpins[0] = 0;
|
|
|
|
}
|
|
|
|
|
2001-09-19 17:04:25 +00:00
|
|
|
fprintf(stderr, "%sProgrammer Pin Configuration: %s (%s)\n", p,
|
2001-10-14 23:17:26 +00:00
|
|
|
(char *)ldata(lfirst(pgm->id)), pgm->desc);
|
2001-09-20 03:19:31 +00:00
|
|
|
|
2001-09-19 17:04:25 +00:00
|
|
|
fprintf(stderr,
|
2001-09-20 03:19:31 +00:00
|
|
|
"%s VCC = 0x%02x %s\n"
|
2001-09-19 17:04:25 +00:00
|
|
|
"%s BUFF = %d\n"
|
|
|
|
"%s RESET = %d\n"
|
|
|
|
"%s SCK = %d\n"
|
|
|
|
"%s MOSI = %d\n"
|
|
|
|
"%s MISO = %d\n"
|
|
|
|
"%s ERR LED = %d\n"
|
|
|
|
"%s RDY LED = %d\n"
|
|
|
|
"%s PGM LED = %d\n"
|
|
|
|
"%s VFY LED = %d\n",
|
2001-10-14 23:17:26 +00:00
|
|
|
p, pgm->pinno[PPI_AVR_VCC], vccpins,
|
|
|
|
p, pgm->pinno[PIN_AVR_BUFF],
|
|
|
|
p, pgm->pinno[PIN_AVR_RESET],
|
|
|
|
p, pgm->pinno[PIN_AVR_SCK],
|
|
|
|
p, pgm->pinno[PIN_AVR_MOSI],
|
|
|
|
p, pgm->pinno[PIN_AVR_MISO],
|
|
|
|
p, pgm->pinno[PIN_LED_ERR],
|
|
|
|
p, pgm->pinno[PIN_LED_RDY],
|
|
|
|
p, pgm->pinno[PIN_LED_PGM],
|
|
|
|
p, pgm->pinno[PIN_LED_VFY]);
|
2001-09-19 17:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void verify_pin_assigned(int pin, char * desc)
|
|
|
|
{
|
2001-10-14 23:17:26 +00:00
|
|
|
if (pgm->pinno[pin] == 0) {
|
2001-09-19 17:04:25 +00:00
|
|
|
fprintf(stderr, "%s: error: no pin has been assigned for %s\n",
|
|
|
|
progname, desc);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
|
|
|
|
PROGRAMMER * locate_pinconfig(LISTID programmers, char * configid)
|
|
|
|
{
|
|
|
|
LNODEID ln1, ln2;
|
2001-10-16 02:50:27 +00:00
|
|
|
PROGRAMMER * p = NULL;
|
2001-10-14 23:17:26 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AVRPART * locate_part(LISTID parts, char * partdesc)
|
|
|
|
{
|
|
|
|
LNODEID ln1;
|
2001-10-16 02:50:27 +00:00
|
|
|
AVRPART * p = NULL;
|
2001-10-14 23:17:26 +00:00
|
|
|
int found;
|
|
|
|
|
|
|
|
found = 0;
|
|
|
|
|
|
|
|
for (ln1=lfirst(parts); ln1 && !found; ln1=lnext(ln1)) {
|
|
|
|
p = ldata(ln1);
|
|
|
|
if ((strcasecmp(partdesc, p->id) == 0) ||
|
|
|
|
(strcasecmp(partdesc, p->desc) == 0))
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
return p;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void list_parts(FILE * f, char * prefix, LISTID parts)
|
|
|
|
{
|
|
|
|
LNODEID ln1;
|
|
|
|
AVRPART * p;
|
|
|
|
|
|
|
|
for (ln1=lfirst(parts); ln1; ln1=lnext(ln1)) {
|
|
|
|
p = ldata(ln1);
|
2001-11-11 01:58:21 +00:00
|
|
|
fprintf(f, "%s%-4s = %s\n", prefix, p->id, p->desc);
|
2001-10-14 23:17:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-09-19 17:04:25 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
/*
|
|
|
|
* main routine
|
|
|
|
*/
|
2001-10-13 03:13:13 +00:00
|
|
|
int main(int argc, char * argv [])
|
2001-01-19 02:46:50 +00:00
|
|
|
{
|
|
|
|
int fd; /* file descriptor for parallel port */
|
|
|
|
int rc; /* general return code checking */
|
|
|
|
int exitrc; /* exit code for main() */
|
|
|
|
int i; /* general loop counter */
|
|
|
|
int ch; /* options flag */
|
|
|
|
int size; /* size of memory region */
|
|
|
|
int len; /* length for various strings */
|
|
|
|
unsigned char sig[4]; /* AVR signature bytes */
|
|
|
|
unsigned char nulldev[4]; /* 0xff signature bytes for comparison */
|
2001-10-14 23:17:26 +00:00
|
|
|
struct avrpart * p; /* which avr part we are programming */
|
|
|
|
struct avrpart * v; /* used for verify */
|
2001-01-19 02:46:50 +00:00
|
|
|
int readorwrite; /* true if a chip read/write op was selected */
|
|
|
|
int ppidata; /* cached value of the ppi data register */
|
2001-01-20 16:34:28 +00:00
|
|
|
int vsize=-1; /* number of bytes to verify */
|
2001-01-26 20:45:05 +00:00
|
|
|
char timestamp[64];
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
/* options / operating mode variables */
|
|
|
|
int memtype; /* AVR_FLASH or AVR_EEPROM */
|
2001-02-08 01:08:30 +00:00
|
|
|
int doread; /* 1=reading AVR, 0=writing AVR */
|
2001-01-19 02:46:50 +00:00
|
|
|
int erase; /* 1=erase chip, 0=don't */
|
|
|
|
char * outputf; /* output file name */
|
|
|
|
char * inputf; /* input file name */
|
|
|
|
int ovsigck; /* 1=override sig check, 0=don't */
|
|
|
|
char * parallel; /* parallel port device */
|
|
|
|
int terminal; /* 1=enter terminal mode, 0=don't */
|
|
|
|
FILEFMT filefmt; /* FMT_AUTO, FMT_IHEX, FMT_SREC, FMT_RBIN */
|
|
|
|
int nowrite; /* don't actually write anything to the chip */
|
|
|
|
int verify; /* perform a verify operation */
|
|
|
|
int ppisetbits; /* bits to set in ppi data register at exit */
|
|
|
|
int ppiclrbits; /* bits to clear in ppi data register at exit */
|
2001-09-21 03:27:20 +00:00
|
|
|
char * exitspecs; /* exit specs string from command line */
|
2001-10-14 23:17:26 +00:00
|
|
|
int verbose; /* verbose output */
|
|
|
|
char * pinconfig; /* programmer id */
|
|
|
|
char * partdesc; /* part id */
|
|
|
|
char configfile[PATH_MAX]; /* pin configuration file */
|
|
|
|
|
|
|
|
progname = rindex(argv[0],'/');
|
|
|
|
if (progname)
|
|
|
|
progname++;
|
|
|
|
else
|
|
|
|
progname = argv[0];
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
init_config();
|
|
|
|
|
|
|
|
partdesc = NULL;
|
2001-09-19 17:04:25 +00:00
|
|
|
readorwrite = 0;
|
|
|
|
parallel = DEFAULT_PARALLEL;
|
|
|
|
outputf = NULL;
|
|
|
|
inputf = NULL;
|
|
|
|
doread = 1;
|
2001-10-13 03:12:52 +00:00
|
|
|
memtype = AVR_M_FLASH;
|
2001-09-19 17:04:25 +00:00
|
|
|
erase = 0;
|
|
|
|
p = NULL;
|
|
|
|
ovsigck = 0;
|
|
|
|
terminal = 0;
|
|
|
|
filefmt = FMT_AUTO;
|
|
|
|
nowrite = 0;
|
|
|
|
verify = 1; /* on by default; XXX can't turn it off */
|
2001-09-21 03:27:20 +00:00
|
|
|
ppisetbits = 0;
|
|
|
|
ppiclrbits = 0;
|
|
|
|
exitspecs = NULL;
|
2001-10-14 23:17:26 +00:00
|
|
|
pgm = NULL;
|
|
|
|
pinconfig = "avrprog"; /* compiled-in default */
|
2001-10-13 03:12:52 +00:00
|
|
|
verbose = 0;
|
2001-09-19 17:04:25 +00:00
|
|
|
|
|
|
|
strcpy(configfile, CONFIG_DIR);
|
|
|
|
i = strlen(configfile);
|
|
|
|
if (i && (configfile[i-1] != '/'))
|
|
|
|
strcat(configfile, "/");
|
|
|
|
strcat(configfile, "avrprog.conf");
|
|
|
|
|
|
|
|
/*
|
2001-10-14 23:17:26 +00:00
|
|
|
* initialize compiled-in default programmer
|
2001-09-19 17:04:25 +00:00
|
|
|
*/
|
2001-10-14 23:17:26 +00:00
|
|
|
pgm = &compiled_in_pgm;
|
|
|
|
pgm->id = lcreat(NULL, 0);
|
|
|
|
ladd(pgm->id, dup_string("avrprog"));
|
|
|
|
strcpy(pgm->desc, "avrprog compiled-in default");
|
|
|
|
for (i=0; i<N_PINS; i++)
|
|
|
|
pgm->pinno[i] = 0;
|
|
|
|
pgm->pinno[PPI_AVR_VCC] = 0x0f; /* ppi pins 2-5, data reg bits 0-3 */
|
|
|
|
pgm->pinno[PIN_AVR_BUFF] = 0;
|
|
|
|
pgm->pinno[PIN_AVR_RESET] = 7;
|
|
|
|
pgm->pinno[PIN_AVR_SCK] = 8;
|
|
|
|
pgm->pinno[PIN_AVR_MOSI] = 9;
|
|
|
|
pgm->pinno[PIN_AVR_MISO] = 10;
|
|
|
|
pgm->pinno[PIN_LED_ERR] = 0;
|
|
|
|
pgm->pinno[PIN_LED_RDY] = 0;
|
|
|
|
pgm->pinno[PIN_LED_PGM] = 0;
|
|
|
|
pgm->pinno[PIN_LED_VFY] = 0;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
len = strlen(progname) + 2;
|
|
|
|
for (i=0; i<len; i++)
|
|
|
|
progbuf[i] = ' ';
|
|
|
|
progbuf[i] = 0;
|
|
|
|
|
2001-01-26 20:45:05 +00:00
|
|
|
print_module_versions(NULL, timestamp);
|
2001-01-26 20:34:08 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
/*
|
|
|
|
* check for no arguments
|
|
|
|
*/
|
|
|
|
if (argc == 1) {
|
|
|
|
usage();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* process command line arguments
|
|
|
|
*/
|
2001-10-13 03:12:52 +00:00
|
|
|
while ((ch = getopt(argc,argv,"?c:C:eE:f:Fi:m:no:p:P:tv")) != -1) {
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
switch (ch) {
|
2001-09-19 17:04:25 +00:00
|
|
|
case 'c': /* pin configuration */
|
|
|
|
pinconfig = optarg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'C': /* pin configuration file */
|
|
|
|
strncpy(configfile, optarg, PATH_MAX);
|
|
|
|
configfile[PATH_MAX-1] = 0;
|
|
|
|
break;
|
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
case 'm': /* select memory type to operate on */
|
|
|
|
if ((strcasecmp(optarg,"e")==0)||(strcasecmp(optarg,"eeprom")==0)) {
|
2001-10-13 03:12:52 +00:00
|
|
|
memtype = AVR_M_EEPROM;
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
else if ((strcasecmp(optarg,"f")==0)||
|
|
|
|
(strcasecmp(optarg,"flash")==0)) {
|
2001-10-13 03:12:52 +00:00
|
|
|
memtype = AVR_M_FLASH;
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf(stderr, "%s: invalid memory type \"%s\"\n\n",
|
|
|
|
progname, optarg);
|
|
|
|
usage();
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
readorwrite = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'F': /* override invalid signature check */
|
|
|
|
ovsigck = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
nowrite = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'o': /* specify output file */
|
|
|
|
if (inputf || terminal) {
|
|
|
|
fprintf(stderr,"%s: -i, -o, and -t are incompatible\n\n", progname);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
doread = 1;
|
|
|
|
outputf = optarg;
|
|
|
|
if (filefmt == FMT_AUTO)
|
|
|
|
filefmt = FMT_RBIN;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'p' : /* specify AVR part */
|
2001-10-14 23:17:26 +00:00
|
|
|
partdesc = optarg;
|
2001-01-19 02:46:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'e': /* perform a chip erase */
|
|
|
|
erase = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'E':
|
2001-09-21 03:27:20 +00:00
|
|
|
exitspecs = optarg;
|
2001-01-19 02:46:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'i': /* specify input file */
|
|
|
|
if (outputf || terminal) {
|
|
|
|
fprintf(stderr,"%s: -o, -i, and -t are incompatible\n\n", progname);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
doread = 0;
|
|
|
|
inputf = optarg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'f': /* specify file format */
|
|
|
|
if (strlen(optarg) != 1) {
|
|
|
|
fprintf(stderr, "%s: invalid file format \"%s\"\n",
|
|
|
|
progname, optarg);
|
|
|
|
usage();
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
switch (optarg[0]) {
|
|
|
|
case 'a' : filefmt = FMT_AUTO; break;
|
|
|
|
case 'i' : filefmt = FMT_IHEX; break;
|
|
|
|
case 'r' : filefmt = FMT_RBIN; break;
|
|
|
|
case 's' :
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: Motorola S-Record format not yet supported\n\n",
|
|
|
|
progname);
|
|
|
|
exit(1);
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
fprintf(stderr, "%s: invalid file format \"%s\"\n\n",
|
|
|
|
progname, optarg);
|
|
|
|
usage();
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 't': /* enter terminal mode */
|
|
|
|
if (!((inputf == NULL)||(outputf == NULL))) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: terminal mode is not compatible with -i or -o\n\n",
|
|
|
|
progname);
|
|
|
|
usage();
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
terminal = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'P':
|
|
|
|
parallel = optarg;
|
|
|
|
break;
|
|
|
|
|
2001-10-13 03:12:52 +00:00
|
|
|
case 'v':
|
|
|
|
verbose++;
|
2001-01-19 02:46:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '?': /* help */
|
|
|
|
usage();
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "%s: invalid option -%c\n\n", progname, ch);
|
|
|
|
usage();
|
|
|
|
exit(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2001-10-13 03:12:52 +00:00
|
|
|
if (verbose) {
|
|
|
|
/*
|
|
|
|
* Print out an identifying string so folks can tell what version
|
|
|
|
* they are running
|
|
|
|
*/
|
|
|
|
fprintf(stderr, "\n%s: Copyright 2001 Brian Dean, bsd@bsdhome.com\n"
|
|
|
|
"%sVersion %s Revision Timestamp %s\n\n",
|
|
|
|
progname, progbuf, version, timestamp);
|
|
|
|
|
|
|
|
if (verbose > 1) {
|
|
|
|
print_module_versions(stderr, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
rc = read_config(configfile);
|
|
|
|
if (rc) {
|
|
|
|
fprintf(stderr, "%s: error reading \"%s\" configuration from \"%s\"\n",
|
|
|
|
progname, pinconfig, configfile);
|
|
|
|
exit(1);
|
|
|
|
}
|
2001-10-13 03:12:52 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
if (strcmp(pinconfig, "avrprog") == 0) {
|
|
|
|
pgm = locate_pinconfig(programmers, "default");
|
|
|
|
if (pgm == NULL) {
|
|
|
|
/* no default config listed, use the compile-in default */
|
|
|
|
pgm = &compiled_in_pgm;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pgm = locate_pinconfig(programmers, pinconfig);
|
|
|
|
if (pgm == NULL) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: Can't find pin config id \"%s\"\n",
|
|
|
|
progname, pinconfig);
|
|
|
|
fprintf(stderr,"\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (partdesc == NULL) {
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"%s: No AVR part has been specified, use \"-p Part\"\n\n"
|
|
|
|
" Valid Parts are:\n\n",
|
2001-10-13 03:13:13 +00:00
|
|
|
progname);
|
2001-10-14 23:17:26 +00:00
|
|
|
list_parts(stderr, " ", part_list);
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stderr,"\n");
|
2001-10-14 23:17:26 +00:00
|
|
|
exit(1);
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
|
|
|
|
p = locate_part(part_list, partdesc);
|
|
|
|
if (p == NULL) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: AVR Part \"%s\" not found. Valid parts are:\n\n",
|
|
|
|
progname, partdesc);
|
|
|
|
list_parts(stderr, " ", part_list);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
exit(1);
|
2001-09-19 17:04:25 +00:00
|
|
|
}
|
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
|
2001-09-21 03:27:20 +00:00
|
|
|
if (exitspecs != NULL) {
|
|
|
|
if (getexitspecs(exitspecs, &ppisetbits, &ppiclrbits) < 0) {
|
|
|
|
usage();
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-09-19 17:04:25 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
/*
|
|
|
|
* set up seperate instances of the avr part, one for use in
|
|
|
|
* programming, one for use in verifying. These are separate
|
|
|
|
* because they need separate flash and eeprom buffer space
|
|
|
|
*/
|
2001-10-14 23:17:26 +00:00
|
|
|
p = avr_dup_part(p);
|
|
|
|
v = avr_dup_part(p);
|
2001-01-19 02:46:50 +00:00
|
|
|
|
2001-10-13 03:12:52 +00:00
|
|
|
if (verbose) {
|
|
|
|
avr_display(stderr, p, progbuf);
|
|
|
|
fprintf(stderr, "\n");
|
2001-10-14 23:17:26 +00:00
|
|
|
pinconfig_display(progbuf);
|
2001-10-13 03:12:52 +00:00
|
|
|
}
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
2001-09-19 17:04:25 +00:00
|
|
|
verify_pin_assigned(PIN_AVR_RESET, "AVR RESET");
|
|
|
|
verify_pin_assigned(PIN_AVR_SCK, "AVR SCK");
|
|
|
|
verify_pin_assigned(PIN_AVR_MISO, "AVR MISO");
|
|
|
|
verify_pin_assigned(PIN_AVR_MOSI, "AVR MOSI");
|
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
/*
|
|
|
|
* open the parallel port
|
|
|
|
*/
|
2001-10-13 03:13:13 +00:00
|
|
|
fd = open(parallel, O_RDWR);
|
2001-01-19 02:46:50 +00:00
|
|
|
if (fd < 0) {
|
2001-10-13 03:13:13 +00:00
|
|
|
fprintf(stderr, "%s: can't open device \"%s\": %s\n\n",
|
|
|
|
progname, parallel, strerror(errno));
|
2001-01-19 02:46:50 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
exitrc = 0;
|
|
|
|
|
2001-01-24 18:45:58 +00:00
|
|
|
#if 0
|
|
|
|
ppi_sense(fd);
|
|
|
|
#endif
|
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
ppidata = ppi_getall(fd, PPIDATA);
|
|
|
|
if (ppidata < 0) {
|
2001-10-13 03:13:13 +00:00
|
|
|
fprintf(stderr, "%s: error reading status of ppi data port\n", progname);
|
2001-01-19 02:46:50 +00:00
|
|
|
exitrc = 1;
|
|
|
|
ppidata = 0; /* clear all bits at exit */
|
|
|
|
goto main_exit;
|
|
|
|
}
|
2001-09-21 02:57:58 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
ppidata &= ~ppiclrbits;
|
|
|
|
ppidata |= ppisetbits;
|
|
|
|
|
2001-01-24 19:10:34 +00:00
|
|
|
/*
|
|
|
|
* turn off all the status leds
|
|
|
|
*/
|
2001-10-14 23:17:26 +00:00
|
|
|
LED_OFF(fd, pgm->pinno[PIN_LED_RDY]);
|
|
|
|
LED_OFF(fd, pgm->pinno[PIN_LED_ERR]);
|
|
|
|
LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
|
|
|
|
LED_OFF(fd, pgm->pinno[PIN_LED_VFY]);
|
2001-01-24 19:10:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* enable the 74367 buffer, if connected; this signal is active low
|
|
|
|
*/
|
2001-10-14 23:17:26 +00:00
|
|
|
ppi_setpin(fd, pgm->pinno[PIN_AVR_BUFF], 0);
|
2001-01-24 19:10:34 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
/*
|
|
|
|
* initialize the chip in preperation for accepting commands
|
|
|
|
*/
|
|
|
|
rc = avr_initialize(fd,p);
|
|
|
|
if (rc < 0) {
|
2001-10-13 03:13:13 +00:00
|
|
|
fprintf(stderr, "%s: initialization failed, rc=%d\n", progname, rc);
|
2001-01-19 02:46:50 +00:00
|
|
|
exitrc = 1;
|
|
|
|
goto main_exit;
|
|
|
|
}
|
|
|
|
|
2001-01-24 19:10:34 +00:00
|
|
|
/* indicate ready */
|
2001-10-14 23:17:26 +00:00
|
|
|
LED_ON(fd, pgm->pinno[PIN_LED_RDY]);
|
2001-01-24 19:10:34 +00:00
|
|
|
|
2001-10-13 03:13:13 +00:00
|
|
|
fprintf(stderr,
|
2001-01-19 02:46:50 +00:00
|
|
|
"%s: AVR device initialized and ready to accept instructions\n",
|
2001-10-13 03:13:13 +00:00
|
|
|
progname);
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Let's read the signature bytes to make sure there is at least a
|
|
|
|
* chip on the other end that is responding correctly. A check
|
|
|
|
* against 0xffffffff should ensure that the signature bytes are
|
|
|
|
* valid.
|
|
|
|
*/
|
|
|
|
avr_signature(fd, sig);
|
|
|
|
fprintf(stderr, "%s: Device signature = 0x", progname);
|
|
|
|
for (i=0; i<4; i++)
|
|
|
|
fprintf(stderr, "%02x", sig[i]);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
|
|
memset(nulldev,0xff,4);
|
|
|
|
if (memcmp(sig,nulldev,4)==0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: Yikes! Invalid device signature.\n", progname);
|
|
|
|
if (!ovsigck) {
|
2001-01-26 17:25:45 +00:00
|
|
|
fprintf(stderr, "%sDouble check connections and try again, "
|
|
|
|
"or use -F to override\n"
|
2001-01-19 02:46:50 +00:00
|
|
|
"%sthis check.\n\n",
|
2001-10-13 03:13:13 +00:00
|
|
|
progbuf, progbuf);
|
2001-01-26 17:25:45 +00:00
|
|
|
exitrc = 1;
|
|
|
|
goto main_exit;
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
|
|
if (erase) {
|
|
|
|
/*
|
|
|
|
* erase the chip's flash and eeprom memories, this is required
|
|
|
|
* before the chip can accept new programming
|
|
|
|
*/
|
2001-10-13 03:13:13 +00:00
|
|
|
fprintf(stderr, "%s: erasing chip\n", progname);
|
2001-01-19 02:46:50 +00:00
|
|
|
avr_chip_erase(fd,p);
|
2001-10-13 03:13:13 +00:00
|
|
|
fprintf(stderr, "%s: done.\n", progname);
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!terminal && ((inputf==NULL) && (outputf==NULL))) {
|
|
|
|
/*
|
|
|
|
* Check here to see if any other operations were selected and
|
|
|
|
* generate an error message because if they were, we need either
|
2001-02-08 01:08:30 +00:00
|
|
|
* an input or an output file, but one was not selected.
|
2001-01-19 02:46:50 +00:00
|
|
|
* Otherwise, we just shut down.
|
|
|
|
*/
|
|
|
|
if (readorwrite) {
|
|
|
|
fprintf(stderr, "%s: you must specify an input or an output file\n",
|
|
|
|
progname);
|
|
|
|
exitrc = 1;
|
|
|
|
}
|
|
|
|
goto main_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (terminal) {
|
|
|
|
/*
|
|
|
|
* terminal mode
|
|
|
|
*/
|
|
|
|
exitrc = terminal_mode(fd, p);
|
|
|
|
}
|
|
|
|
else if (doread) {
|
|
|
|
/*
|
|
|
|
* read out the specified device memory and write it to a file
|
|
|
|
*/
|
|
|
|
fprintf(stderr, "%s: reading %s memory:\n",
|
|
|
|
progname, avr_memtstr(memtype));
|
2001-11-19 17:44:24 +00:00
|
|
|
rc = avr_read(fd, p, memtype, 0);
|
2001-01-20 16:34:28 +00:00
|
|
|
if (rc < 0) {
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n",
|
|
|
|
progname, avr_memtstr(memtype), rc);
|
|
|
|
exitrc = 1;
|
|
|
|
goto main_exit;
|
|
|
|
}
|
2001-01-20 16:34:28 +00:00
|
|
|
size = rc;
|
2001-01-19 02:46:50 +00:00
|
|
|
|
|
|
|
fprintf(stderr, "%s: writing output file \"%s\"\n",
|
|
|
|
progname, outputf);
|
2001-01-20 16:34:28 +00:00
|
|
|
rc = fileio(FIO_WRITE, outputf, filefmt, p, memtype, size);
|
2001-01-19 02:46:50 +00:00
|
|
|
if (rc < 0) {
|
|
|
|
fprintf(stderr, "%s: terminating\n", progname);
|
|
|
|
exitrc = 1;
|
|
|
|
goto main_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* write the selected device memory using data from a file; first
|
|
|
|
* read the data from the specified file
|
|
|
|
*/
|
|
|
|
fprintf(stderr, "%s: reading input file \"%s\"\n",
|
|
|
|
progname, inputf);
|
2001-01-20 16:34:28 +00:00
|
|
|
rc = fileio(FIO_READ, inputf, filefmt, p, memtype, -1);
|
2001-01-19 02:46:50 +00:00
|
|
|
if (rc < 0) {
|
|
|
|
fprintf(stderr, "%s: terminating\n", progname);
|
|
|
|
exitrc = 1;
|
|
|
|
goto main_exit;
|
|
|
|
}
|
|
|
|
size = rc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* write the buffer contents to the selected memory type
|
|
|
|
*/
|
|
|
|
fprintf(stderr, "%s: writing %s:\n",
|
|
|
|
progname, avr_memtstr(memtype));
|
|
|
|
|
|
|
|
if (!nowrite) {
|
2001-10-13 03:13:13 +00:00
|
|
|
rc = avr_write(fd, p, memtype, size);
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* test mode, don't actually write to the chip, output the buffer
|
|
|
|
* to stdout in intel hex instead
|
|
|
|
*/
|
2001-01-20 16:34:28 +00:00
|
|
|
rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, memtype, size);
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
2001-01-20 16:34:28 +00:00
|
|
|
if (rc < 0) {
|
2001-10-13 03:13:13 +00:00
|
|
|
fprintf(stderr, "%s: failed to write flash memory, rc=%d\n",
|
|
|
|
progname, rc);
|
2001-01-19 02:46:50 +00:00
|
|
|
exitrc = 1;
|
|
|
|
goto main_exit;
|
|
|
|
}
|
|
|
|
|
2001-01-20 16:34:28 +00:00
|
|
|
vsize = rc;
|
|
|
|
|
|
|
|
fprintf(stderr, "%s: %d bytes of %s written\n", progname,
|
|
|
|
vsize, avr_memtstr(memtype));
|
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!doread && verify) {
|
|
|
|
/*
|
2001-10-13 03:12:52 +00:00
|
|
|
* verify that the in memory file (p->mem[AVR_M_FLASH|AVR_M_EEPROM])
|
2001-02-08 01:08:30 +00:00
|
|
|
* is the same as what is on the chip
|
2001-01-19 02:46:50 +00:00
|
|
|
*/
|
2001-10-14 23:17:26 +00:00
|
|
|
LED_ON(fd, pgm->pinno[PIN_LED_VFY]);
|
2001-01-24 19:10:34 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stderr, "%s: verifying %s memory against %s:\n",
|
|
|
|
progname, avr_memtstr(memtype), inputf);
|
|
|
|
fprintf(stderr, "%s: reading on-chip %s data:\n",
|
|
|
|
progname, avr_memtstr(memtype));
|
2001-11-19 17:44:24 +00:00
|
|
|
rc = avr_read(fd, v, memtype, vsize);
|
2001-01-20 16:34:28 +00:00
|
|
|
if (rc < 0) {
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n",
|
|
|
|
progname, avr_memtstr(memtype), rc);
|
2001-10-14 23:17:26 +00:00
|
|
|
LED_ON(fd, pgm->pinno[PIN_LED_ERR]);
|
2001-01-19 02:46:50 +00:00
|
|
|
exitrc = 1;
|
|
|
|
goto main_exit;
|
|
|
|
}
|
2001-01-20 16:34:28 +00:00
|
|
|
|
|
|
|
fprintf(stderr, "%s: verifying ...\n", progname);
|
|
|
|
rc = avr_verify(p, v, memtype, vsize);
|
|
|
|
if (rc < 0) {
|
2001-01-19 02:46:50 +00:00
|
|
|
fprintf(stderr, "%s: verification error; content mismatch\n",
|
|
|
|
progname);
|
2001-10-14 23:17:26 +00:00
|
|
|
LED_ON(fd, pgm->pinno[PIN_LED_ERR]);
|
2001-01-19 02:46:50 +00:00
|
|
|
exitrc = 1;
|
|
|
|
goto main_exit;
|
|
|
|
}
|
|
|
|
|
2001-01-20 16:34:28 +00:00
|
|
|
fprintf(stderr, "%s: %d bytes of %s verified\n",
|
|
|
|
progname, rc, avr_memtstr(memtype));
|
2001-01-24 19:10:34 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
LED_OFF(fd, pgm->pinno[PIN_LED_VFY]);
|
2001-01-19 02:46:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
main_exit:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* program complete
|
|
|
|
*/
|
|
|
|
|
|
|
|
avr_powerdown(fd);
|
2001-09-21 03:27:20 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
ppi_setall(fd, PPIDATA, ppidata);
|
|
|
|
|
2001-01-24 19:10:34 +00:00
|
|
|
/*
|
|
|
|
* disable the 74367 buffer, if connected; this signal is active low
|
|
|
|
*/
|
2001-10-14 23:17:26 +00:00
|
|
|
ppi_setpin(fd, pgm->pinno[PIN_AVR_BUFF], 1);
|
2001-01-24 19:10:34 +00:00
|
|
|
|
2001-10-14 23:17:26 +00:00
|
|
|
LED_OFF(fd, pgm->pinno[PIN_LED_RDY]);
|
2001-02-08 01:42:09 +00:00
|
|
|
|
2001-01-19 02:46:50 +00:00
|
|
|
close(fd);
|
|
|
|
|
|
|
|
fprintf(stderr, "\n%s done. Thank you.\n\n", progname);
|
|
|
|
|
|
|
|
return exitrc;
|
|
|
|
}
|
|
|
|
|