mirror of
https://github.com/mariusgreuel/avrdude.git
synced 2025-12-17 11:04:16 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1c7bc8c83 |
@@ -1,17 +1,10 @@
|
||||
AVRDUDE was written by:
|
||||
|
||||
Brian S. Dean <bsd@bdmicro.com>
|
||||
Brian S. Dean <bsd@bsdhome.com>.
|
||||
|
||||
Contributors:
|
||||
|
||||
Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
Eric Weddington <ericw@evcohs.com>
|
||||
Jan-Hinnerk Reichert <hinni@despammed.com>
|
||||
Alex Shepherd <maillists@ajsystems.co.nz>
|
||||
Martin Thomas <mthomas@rhrk.uni-kl.de>
|
||||
Eric Weddington <eric@ecentral.com>
|
||||
Theodore A. Roth <troth@openavr.org>
|
||||
Michael Holzt <kju-avr@fqdn.org>
|
||||
Colin O'Flynn <coflynn@newae.com>
|
||||
|
||||
For minor contributions, please see the ChangeLog files.
|
||||
|
||||
|
||||
1367
avrdude/ChangeLog
1367
avrdude/ChangeLog
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# avrdude - A Downloader/Uploader for AVR device programmers
|
||||
# Copyright (C) 2003, 2004 Theodore A. Roth <troth@openavr.org>
|
||||
# Copyright (C) 2003 Theodore A. Roth <troth@openavr.org>
|
||||
#
|
||||
# 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
|
||||
@@ -24,8 +24,8 @@
|
||||
EXTRA_DIST = \
|
||||
ChangeLog-2001 \
|
||||
ChangeLog-2002 \
|
||||
ChangeLog-2003 \
|
||||
avrdude.1 \
|
||||
avrdude.pdf \
|
||||
avrdude.spec \
|
||||
bootstrap
|
||||
|
||||
@@ -34,11 +34,8 @@ CLEANFILES = \
|
||||
config_gram.h \
|
||||
lexer.c
|
||||
|
||||
#SUBDIRS = doc @WINDOWS_DIRS@
|
||||
#DIST_SUBDIRS = doc windows
|
||||
|
||||
SUBDIRS = @SUBDIRS_AC@
|
||||
DIST_SUBDIRS = @DIST_SUBDIRS_AC@
|
||||
SUBDIRS = doc @WINDOWS_DIRS@
|
||||
DIST_SUBDIRS = doc windows
|
||||
|
||||
AM_YFLAGS = -d
|
||||
|
||||
@@ -55,23 +52,13 @@ avrdude_SOURCES = \
|
||||
avr.h \
|
||||
avr910.c \
|
||||
avr910.h \
|
||||
avrpart.c \
|
||||
avrpart.h \
|
||||
bitbang.c \
|
||||
bitbang.h \
|
||||
butterfly.c \
|
||||
butterfly.h \
|
||||
config.c \
|
||||
config.h \
|
||||
confwin.c \
|
||||
confwin.h \
|
||||
crc16.c \
|
||||
crc16.h \
|
||||
fileio.c \
|
||||
fileio.h \
|
||||
jtagmkII.c \
|
||||
jtagmkII.h \
|
||||
jtagmkII_private.h \
|
||||
linux_ppdev.h \
|
||||
lists.c \
|
||||
lists.h \
|
||||
@@ -84,23 +71,14 @@ avrdude_SOURCES = \
|
||||
ppi.c \
|
||||
ppi.h \
|
||||
ppiwin.c \
|
||||
safemode.c \
|
||||
safemode.h \
|
||||
serial.h \
|
||||
serbb.h \
|
||||
serbb_posix.c \
|
||||
serbb_win32.c \
|
||||
ser_posix.c \
|
||||
ser_win32.c \
|
||||
stk500.c \
|
||||
stk500.h \
|
||||
stk500_private.h \
|
||||
stk500v2.c \
|
||||
stk500v2.h \
|
||||
stk500v2_private.h \
|
||||
term.c \
|
||||
term.h \
|
||||
usb_libusb.c
|
||||
term.h
|
||||
|
||||
man_MANS = avrdude.1
|
||||
|
||||
|
||||
86
avrdude/NEWS
86
avrdude/NEWS
@@ -5,92 +5,6 @@ Approximate change log for AVRDUDE by version.
|
||||
(For more detailed changes, see the ChangeLog file.)
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Current:
|
||||
|
||||
|
||||
|
||||
Version 5.0:
|
||||
|
||||
* Support for JTAGICE MkII device
|
||||
|
||||
* Support for STK500 Version 2 Protocol
|
||||
|
||||
* New devices supported:
|
||||
|
||||
- AT90CAN128
|
||||
- ATmega329x/649x
|
||||
- ATmega164/324/644
|
||||
- AT90PWM2/3,
|
||||
- ATmega164/324/644
|
||||
- ATmega329x/649x
|
||||
- ATtiny25/45/85
|
||||
|
||||
* Support for serial bit-bang adapters: Ponyprog serial, UISP DASA,
|
||||
UISP DASA3.
|
||||
|
||||
* DAPA programmer pinout supported
|
||||
|
||||
* New "safemode" feature where fuse bits are verified before exit
|
||||
and if possible recovered if they have changed. This is intended
|
||||
to protect against changed fuses which were not requested which is
|
||||
reported to sometimes happen due to improper power supply or other
|
||||
reasons.
|
||||
|
||||
* Various fixes for avr910 and butterfly programmers
|
||||
|
||||
* Full support for AVR109 boot loaders (butterfly)
|
||||
|
||||
* Adding -q -q suppresses most terminal output
|
||||
|
||||
|
||||
Version 4.4.0:
|
||||
|
||||
* Native Win32 support: The windows build doesn't need Cygwin
|
||||
anymore. Additionally, the delay timing on windows should be
|
||||
more accurate now.
|
||||
Contributed by Martin Thomas
|
||||
|
||||
* Add support for
|
||||
- ATmega48, ATmega88 (contributed by Galen Seitz)
|
||||
- ATtiny2313 (contributed by Bob Paddock)
|
||||
- ATtiny13 (contributed by Pawel Moll)
|
||||
|
||||
* Added command to change the SCK of STK500-programmers. Now it
|
||||
is possible to program uC with slow oscillator.
|
||||
Contributed by Galen Seitz
|
||||
|
||||
* Baudrate for serial programmers (STK500 and AVR910) is
|
||||
configurable in the config or at the command-line.
|
||||
This way some more tweaked bootloaders and programmers can be used.
|
||||
|
||||
* Deprecated options have been removed.
|
||||
Now the "-U" option must be used.
|
||||
|
||||
* MacOS X now supported by default.
|
||||
|
||||
Version 4.3.0:
|
||||
|
||||
* Added support for "Butterfly" evaluation board.
|
||||
|
||||
* Make cycle-count work with AVR910-programmers.
|
||||
|
||||
* Added "Troubleshooting"-Appendix to the manual.
|
||||
|
||||
* Add ATmega8515 support.
|
||||
Contributed by: Matthias Wei<65>er <matthias@matwei.de>
|
||||
|
||||
* Add ATmega64 support.
|
||||
Contributed by: Erik Christiansen <erik@dd.nec.com.au>
|
||||
|
||||
* Improved polling algorithm to speed up
|
||||
programming of byte oriented parallel programmers.
|
||||
Contributed by: Jan-Hinnerk Reichert <jan-hinnerk_reichert@hamburg.de>
|
||||
|
||||
* Add "fuse" and "lock" definitions for the AT90S8535.
|
||||
|
||||
* STK500 skips empty pages in paged write resulting in faster downloads
|
||||
when there are empty blocks in between code (such as files that contain
|
||||
application code and bootloader code).
|
||||
|
||||
Version 4.2.0:
|
||||
|
||||
|
||||
608
avrdude/avr.c
608
avrdude/avr.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -25,15 +25,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include "avr.h"
|
||||
#include "config.h"
|
||||
#include "lists.h"
|
||||
#include "pindefs.h"
|
||||
#include "ppi.h"
|
||||
#include "safemode.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
@@ -45,6 +43,250 @@ extern PROGRAMMER * pgm;
|
||||
extern int do_cycles;
|
||||
|
||||
|
||||
AVRPART * avr_new_part(void)
|
||||
{
|
||||
AVRPART * p;
|
||||
|
||||
p = (AVRPART *)malloc(sizeof(AVRPART));
|
||||
if (p == NULL) {
|
||||
fprintf(stderr, "new_part(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
p->id[0] = 0;
|
||||
p->desc[0] = 0;
|
||||
p->reset_disposition = RESET_DEDICATED;
|
||||
p->retry_pulse = PIN_AVR_SCK;
|
||||
p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK;
|
||||
p->config_file[0] = 0;
|
||||
p->lineno = 0;
|
||||
|
||||
p->mem = lcreat(NULL, 0);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OPCODE * avr_new_opcode(void)
|
||||
{
|
||||
OPCODE * m;
|
||||
|
||||
m = (OPCODE *)malloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
fprintf(stderr, "avr_new_opcode(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AVRMEM * avr_new_memtype(void)
|
||||
{
|
||||
AVRMEM * m;
|
||||
|
||||
m = (AVRMEM *)malloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
fprintf(stderr, "avr_new_memtype(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
AVRMEM * avr_dup_mem(AVRMEM * m)
|
||||
{
|
||||
AVRMEM * n;
|
||||
|
||||
n = avr_new_memtype();
|
||||
|
||||
*n = *m;
|
||||
|
||||
n->buf = (unsigned char *)malloc(n->size);
|
||||
if (n->buf == NULL) {
|
||||
fprintf(stderr,
|
||||
"avr_dup_mem(): out of memory (memsize=%d)\n",
|
||||
n->size);
|
||||
exit(1);
|
||||
}
|
||||
memset(n->buf, 0, n->size);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
AVRPART * avr_dup_part(AVRPART * d)
|
||||
{
|
||||
AVRPART * p;
|
||||
LISTID save;
|
||||
LNODEID ln;
|
||||
|
||||
p = avr_new_part();
|
||||
save = p->mem;
|
||||
|
||||
*p = *d;
|
||||
|
||||
p->mem = save;
|
||||
|
||||
for (ln=lfirst(d->mem); ln; ln=lnext(ln)) {
|
||||
ladd(p->mem, avr_dup_mem(ldata(ln)));
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
|
||||
{
|
||||
AVRMEM * m, * match;
|
||||
LNODEID ln;
|
||||
int matches;
|
||||
int l;
|
||||
|
||||
l = strlen(desc);
|
||||
matches = 0;
|
||||
match = NULL;
|
||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
if (strncmp(desc, m->desc, l) == 0) {
|
||||
match = m;
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
|
||||
if (matches == 1)
|
||||
return match;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_bits()
|
||||
*
|
||||
* Set instruction bits in the specified command based on the opcode.
|
||||
*/
|
||||
int avr_set_bits(OPCODE * op, unsigned char * cmd)
|
||||
{
|
||||
int i, j, bit;
|
||||
unsigned char mask;
|
||||
|
||||
for (i=0; i<32; i++) {
|
||||
if (op->bit[i].type == AVR_CMDBIT_VALUE) {
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
if (op->bit[i].value)
|
||||
cmd[j] = cmd[j] | mask;
|
||||
else
|
||||
cmd[j] = cmd[j] & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_addr()
|
||||
*
|
||||
* Set address bits in the specified command based on the opcode, and
|
||||
* the address.
|
||||
*/
|
||||
int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr)
|
||||
{
|
||||
int i, j, bit;
|
||||
unsigned long value;
|
||||
unsigned char mask;
|
||||
|
||||
for (i=0; i<32; i++) {
|
||||
if (op->bit[i].type == AVR_CMDBIT_ADDRESS) {
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
value = addr >> op->bit[i].bitno & 0x01;
|
||||
if (value)
|
||||
cmd[j] = cmd[j] | mask;
|
||||
else
|
||||
cmd[j] = cmd[j] & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_input()
|
||||
*
|
||||
* Set input data bits in the specified command based on the opcode,
|
||||
* and the data byte.
|
||||
*/
|
||||
int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data)
|
||||
{
|
||||
int i, j, bit;
|
||||
unsigned char value;
|
||||
unsigned char mask;
|
||||
|
||||
for (i=0; i<32; i++) {
|
||||
if (op->bit[i].type == AVR_CMDBIT_INPUT) {
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
value = data >> op->bit[i].bitno & 0x01;
|
||||
if (value)
|
||||
cmd[j] = cmd[j] | mask;
|
||||
else
|
||||
cmd[j] = cmd[j] & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_get_output()
|
||||
*
|
||||
* Retreive output data bits from the command results based on the
|
||||
* opcode data.
|
||||
*/
|
||||
int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data)
|
||||
{
|
||||
int i, j, bit;
|
||||
unsigned char value;
|
||||
unsigned char mask;
|
||||
|
||||
for (i=0; i<32; i++) {
|
||||
if (op->bit[i].type == AVR_CMDBIT_OUTPUT) {
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
value = ((res[j] & mask) >> bit) & 0x01;
|
||||
value = value << op->bit[i].bitno;
|
||||
if (value)
|
||||
*data = *data | value;
|
||||
else
|
||||
*data = *data & ~value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char * value)
|
||||
{
|
||||
@@ -262,7 +504,7 @@ int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
|
||||
/*
|
||||
* since we don't know what voltage the target AVR is powered by, be
|
||||
* conservative and delay the max amount the spec says to wait
|
||||
* conservative and delay the max amount the spec says to wait
|
||||
*/
|
||||
usleep(mem->max_write_delay);
|
||||
|
||||
@@ -279,14 +521,11 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned char r;
|
||||
int ready;
|
||||
int tries;
|
||||
unsigned long start_time;
|
||||
unsigned long prog_time;
|
||||
unsigned char b;
|
||||
unsigned short caddr;
|
||||
OPCODE * writeop;
|
||||
int rc;
|
||||
int readok=0;
|
||||
struct timeval tv;
|
||||
|
||||
if (!mem->paged) {
|
||||
/*
|
||||
@@ -376,6 +615,13 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
tries = 0;
|
||||
ready = 0;
|
||||
while (!ready) {
|
||||
usleep(mem->min_write_delay);
|
||||
rc = avr_read_byte(pgm, p, mem, addr, &r);
|
||||
if (rc != 0) {
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
pgm->err_led(pgm, ON);
|
||||
return -4;
|
||||
}
|
||||
|
||||
if ((data == mem->readback[0]) ||
|
||||
(data == mem->readback[1])) {
|
||||
@@ -393,29 +639,6 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
return -5;
|
||||
}
|
||||
}
|
||||
else {
|
||||
gettimeofday (&tv, NULL);
|
||||
start_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
do {
|
||||
/*
|
||||
* Do polling, but timeout after max_write_delay.
|
||||
*/
|
||||
rc = avr_read_byte(pgm, p, mem, addr, &r);
|
||||
if (rc != 0) {
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
pgm->err_led(pgm, ON);
|
||||
return -4;
|
||||
}
|
||||
gettimeofday (&tv, NULL);
|
||||
prog_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
} while ((r != data) &&
|
||||
((prog_time-start_time) < mem->max_write_delay));
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we either have a valid readback or the
|
||||
* max_write_delay is expired.
|
||||
*/
|
||||
|
||||
if (r == data) {
|
||||
ready = 1;
|
||||
@@ -428,6 +651,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
* memory bits but not all. We only actually power-off the
|
||||
* device if the data read back does not match what we wrote.
|
||||
*/
|
||||
usleep(mem->max_write_delay); /* maximum write delay */
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
fprintf(stderr,
|
||||
"%s: this device must be powered off and back on to continue\n",
|
||||
@@ -480,31 +704,8 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char data)
|
||||
{
|
||||
|
||||
unsigned char safemode_lfuse;
|
||||
unsigned char safemode_hfuse;
|
||||
unsigned char safemode_efuse;
|
||||
unsigned char safemode_fuse;
|
||||
int rc;
|
||||
|
||||
/* If we write the fuses, then we need to tell safemode that they *should* change */
|
||||
safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||
|
||||
if (strcmp(mem->desc, "fuse")==0) {
|
||||
safemode_fuse = data;
|
||||
}
|
||||
if (strcmp(mem->desc, "lfuse")==0) {
|
||||
safemode_lfuse = data;
|
||||
}
|
||||
if (strcmp(mem->desc, "hfuse")==0) {
|
||||
safemode_hfuse = data;
|
||||
}
|
||||
if (strcmp(mem->desc, "efuse")==0) {
|
||||
safemode_efuse = data;
|
||||
}
|
||||
|
||||
safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||
|
||||
if (pgm->write_byte) {
|
||||
rc = pgm->write_byte(pgm, p, mem, addr, data);
|
||||
if (rc == 0) {
|
||||
@@ -611,12 +812,11 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
if (werror) {
|
||||
/*
|
||||
* make sure the error led stay on if there was a previous write
|
||||
* error, otherwise it gets cleared in avr_write_byte()
|
||||
* error, otherwise it gets cleared in avr_write_byte()
|
||||
*/
|
||||
pgm->err_led(pgm, ON);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -632,7 +832,7 @@ int avr_signature(PROGRAMMER * pgm, AVRPART * p)
|
||||
report_progress (0,1,"Reading");
|
||||
rc = avr_read(pgm, p, "signature", 0, 0);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr,
|
||||
fprintf(stderr,
|
||||
"%s: error reading signature data for part \"%s\", rc=%d\n",
|
||||
progname, p->desc, rc);
|
||||
return -1;
|
||||
@@ -643,12 +843,35 @@ int avr_signature(PROGRAMMER * pgm, AVRPART * p)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocate and initialize memory buffers for each of the device's
|
||||
* defined memory regions.
|
||||
*/
|
||||
int avr_initmem(AVRPART * p)
|
||||
{
|
||||
LNODEID ln;
|
||||
AVRMEM * m;
|
||||
|
||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
m->buf = (unsigned char *) malloc(m->size);
|
||||
if (m->buf == NULL) {
|
||||
fprintf(stderr, "%s: can't alloc buffer for %s size of %d bytes\n",
|
||||
progname, m->desc, m->size);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Verify the memory buffer of p with that of v. The byte range of v,
|
||||
* may be a subset of p. The byte range of p should cover the whole
|
||||
* chip's memory size.
|
||||
*
|
||||
* Return the number of bytes verified, or -1 if they don't match.
|
||||
* Return the number of bytes verified, or -1 if they don't match.
|
||||
*/
|
||||
int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size)
|
||||
{
|
||||
@@ -706,37 +929,54 @@ int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size)
|
||||
int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles)
|
||||
{
|
||||
AVRMEM * a;
|
||||
unsigned int cycle_count = 0;
|
||||
unsigned char v1;
|
||||
int cycle_count;
|
||||
unsigned char v1, v2, v3, v4;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
a = avr_locate_mem(p, "eeprom");
|
||||
if (a == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=4; i>0; i--) {
|
||||
rc = avr_read_byte(pgm, p, a, a->size-i, &v1);
|
||||
rc = avr_read_byte(pgm, p, a, a->size-4, &v1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
return -1;
|
||||
}
|
||||
cycle_count = (cycle_count << 8) | v1;
|
||||
|
||||
rc = avr_read_byte(pgm, p, a, a->size-3, &v2);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the EEPROM is erased, the cycle count reads 0xffffffff.
|
||||
* In this case we return a cycle_count of zero.
|
||||
* So, the calling function don't have to care about whether or not
|
||||
* the cycle count was initialized.
|
||||
*/
|
||||
if (cycle_count == 0xffffffff) {
|
||||
cycle_count = 0;
|
||||
rc = avr_read_byte(pgm, p, a, a->size-2, &v3);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*cycles = (int) cycle_count;
|
||||
rc = avr_read_byte(pgm, p, a, a->size-1, &v4);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((v1 == 0xff) && (v2 == 0xff) && (v3 != 0xff) && (v4 != 0xff)) {
|
||||
v1 = 0;
|
||||
v2 = 0;
|
||||
}
|
||||
|
||||
cycle_count = (((unsigned int)v1) << 24) |
|
||||
(((unsigned int)v2) << 16) |
|
||||
(((unsigned int)v3) << 8) |
|
||||
v4;
|
||||
|
||||
*cycles = cycle_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -745,56 +985,214 @@ int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles)
|
||||
int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles)
|
||||
{
|
||||
AVRMEM * a;
|
||||
unsigned char v1;
|
||||
unsigned char v1, v2, v3, v4;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
a = avr_locate_mem(p, "eeprom");
|
||||
if (a == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=1; i<=4; i++) {
|
||||
v1 = cycles & 0xff;
|
||||
cycles = cycles >> 8;
|
||||
v4 = cycles & 0x0ff;
|
||||
v3 = (cycles & 0x0ff00) >> 8;
|
||||
v2 = (cycles & 0x0ff0000) >> 16;
|
||||
v1 = (cycles & 0x0ff000000) >> 24;
|
||||
|
||||
rc = avr_write_byte(pgm, p, a, a->size-i, v1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
return -1;
|
||||
}
|
||||
rc = avr_write_byte(pgm, p, a, a->size-4, v1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
return -1;
|
||||
}
|
||||
rc = avr_write_byte(pgm, p, a, a->size-3, v2);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
return -1;
|
||||
}
|
||||
rc = avr_write_byte(pgm, p, a, a->size-2, v3);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
return -1;
|
||||
}
|
||||
rc = avr_write_byte(pgm, p, a, a->size-1, v4);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
|
||||
|
||||
char * avr_op_str(int op)
|
||||
{
|
||||
int cycles;
|
||||
int rc;
|
||||
switch (op) {
|
||||
case AVR_OP_READ : return "READ"; break;
|
||||
case AVR_OP_WRITE : return "WRITE"; break;
|
||||
case AVR_OP_READ_LO : return "READ_LO"; break;
|
||||
case AVR_OP_READ_HI : return "READ_HI"; break;
|
||||
case AVR_OP_WRITE_LO : return "WRITE_LO"; break;
|
||||
case AVR_OP_WRITE_HI : return "WRITE_HI"; break;
|
||||
case AVR_OP_LOADPAGE_LO : return "LOADPAGE_LO"; break;
|
||||
case AVR_OP_LOADPAGE_HI : return "LOADPAGE_HI"; break;
|
||||
case AVR_OP_WRITEPAGE : return "WRITEPAGE"; break;
|
||||
case AVR_OP_CHIP_ERASE : return "CHIP_ERASE"; break;
|
||||
case AVR_OP_PGM_ENABLE : return "PGM_ENABLE"; break;
|
||||
default : return "<unknown opcode>"; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_cycles) {
|
||||
rc = avr_get_cycle_count(pgm, p, &cycles);
|
||||
/*
|
||||
* Don't update the cycle counter, if read failed
|
||||
*/
|
||||
if(rc != 0) {
|
||||
do_cycles = 0;
|
||||
|
||||
char * bittype(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case AVR_CMDBIT_IGNORE : return "IGNORE"; break;
|
||||
case AVR_CMDBIT_VALUE : return "VALUE"; break;
|
||||
case AVR_CMDBIT_ADDRESS : return "ADDRESS"; break;
|
||||
case AVR_CMDBIT_INPUT : return "INPUT"; break;
|
||||
case AVR_CMDBIT_OUTPUT : return "OUTPUT"; break;
|
||||
default : return "<unknown bit type>"; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type,
|
||||
int verbose)
|
||||
{
|
||||
int i, j;
|
||||
char * optr;
|
||||
|
||||
if (m == NULL) {
|
||||
fprintf(f,
|
||||
"%s Page Polled\n"
|
||||
"%sMemory Type Paged Size Size #Pages MinW MaxW ReadBack\n"
|
||||
"%s----------- ------ ------ ---- ------ ----- ----- ---------\n",
|
||||
prefix, prefix, prefix);
|
||||
}
|
||||
else {
|
||||
if (verbose > 2) {
|
||||
fprintf(f,
|
||||
"%s Page Polled\n"
|
||||
"%sMemory Type Paged Size Size #Pages MinW MaxW ReadBack\n"
|
||||
"%s----------- ------ ------ ---- ------ ----- ----- ---------\n",
|
||||
prefix, prefix, prefix);
|
||||
}
|
||||
fprintf(f,
|
||||
"%s%-11s %-6s %6d %4d %5d %5d %5d 0x%02x 0x%02x\n",
|
||||
prefix, m->desc,
|
||||
m->paged ? "yes" : "no",
|
||||
m->size,
|
||||
m->page_size,
|
||||
m->num_pages,
|
||||
m->min_write_delay,
|
||||
m->max_write_delay,
|
||||
m->readback[0],
|
||||
m->readback[1]);
|
||||
if (verbose > 2) {
|
||||
fprintf(stderr,
|
||||
"%s Memory Ops:\n"
|
||||
"%s Oeration Inst Bit Bit Type Bitno Value\n"
|
||||
"%s ----------- -------- -------- ----- -----\n",
|
||||
prefix, prefix, prefix);
|
||||
for (i=0; i<AVR_OP_MAX; i++) {
|
||||
if (m->op[i]) {
|
||||
for (j=31; j>=0; j--) {
|
||||
if (j==31)
|
||||
optr = avr_op_str(i);
|
||||
else
|
||||
optr = " ";
|
||||
fprintf(f,
|
||||
"%s %-11s %8d %8s %5d %5d\n",
|
||||
prefix, optr, j,
|
||||
bittype(m->op[i]->bit[j].type),
|
||||
m->op[i]->bit[j].bitno,
|
||||
m->op[i]->bit[j].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = pgm->chip_erase(pgm, p);
|
||||
|
||||
/*
|
||||
* Don't update the cycle counter, if erase failed
|
||||
*/
|
||||
if (do_cycles && (rc == 0)) {
|
||||
cycles++;
|
||||
fprintf(stderr, "%s: erase-rewrite cycle count is now %d\n",
|
||||
progname, cycles);
|
||||
avr_put_cycle_count(pgm, p, cycles);
|
||||
char * reset_disp_str(int r)
|
||||
{
|
||||
switch (r) {
|
||||
case RESET_DEDICATED : return "dedicated";
|
||||
case RESET_IO : return "possible i/o";
|
||||
default : return "<invalid>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char * pin_name(int pinno)
|
||||
{
|
||||
switch (pinno) {
|
||||
case PIN_AVR_RESET : return "RESET";
|
||||
case PIN_AVR_MISO : return "MISO";
|
||||
case PIN_AVR_MOSI : return "MOSI";
|
||||
case PIN_AVR_SCK : return "SCK";
|
||||
default : return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose)
|
||||
{
|
||||
int i;
|
||||
char * buf;
|
||||
char * px;
|
||||
LNODEID ln;
|
||||
AVRMEM * m;
|
||||
|
||||
fprintf(f,
|
||||
"%sAVR Part : %s\n"
|
||||
"%sChip Erase delay : %d us\n"
|
||||
"%sPAGEL : P%02X\n"
|
||||
"%sBS2 : P%02X\n"
|
||||
"%sRESET disposition : %s\n"
|
||||
"%sRETRY pulse : %s\n"
|
||||
"%sserial program mode : %s\n"
|
||||
"%sparallel program mode : %s\n"
|
||||
"%sMemory Detail :\n\n",
|
||||
prefix, p->desc,
|
||||
prefix, p->chip_erase_delay,
|
||||
prefix, p->pagel,
|
||||
prefix, p->bs2,
|
||||
prefix, reset_disp_str(p->reset_disposition),
|
||||
prefix, pin_name(p->retry_pulse),
|
||||
prefix, (p->flags & AVRPART_SERIALOK) ? "yes" : "no",
|
||||
prefix, (p->flags & AVRPART_PARALLELOK) ?
|
||||
((p->flags & AVRPART_PSEUDOPARALLEL) ? "psuedo" : "yes") : "no",
|
||||
prefix);
|
||||
|
||||
px = prefix;
|
||||
i = strlen(prefix) + 5;
|
||||
buf = (char *)malloc(i);
|
||||
if (buf == NULL) {
|
||||
/* ugh, this is not important enough to bail, just ignore it */
|
||||
}
|
||||
else {
|
||||
strcpy(buf, prefix);
|
||||
strcat(buf, " ");
|
||||
px = buf;
|
||||
}
|
||||
|
||||
if (verbose <= 2) {
|
||||
avr_mem_display(px, f, NULL, 0, verbose);
|
||||
}
|
||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
avr_mem_display(px, f, m, i, verbose);
|
||||
}
|
||||
|
||||
return rc;
|
||||
if (buf)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "avrpart.h"
|
||||
#include "lists.h"
|
||||
#include "pgm.h"
|
||||
|
||||
|
||||
@@ -32,10 +33,29 @@
|
||||
extern struct avrpart parts[];
|
||||
|
||||
|
||||
int avr_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
|
||||
AVRPART * avr_find_part(char * p);
|
||||
|
||||
AVRPART * avr_new_part(void);
|
||||
|
||||
OPCODE * avr_new_opcode(void);
|
||||
|
||||
AVRMEM * avr_new_memtype(void);
|
||||
|
||||
AVRPART * avr_dup_part(AVRPART * d);
|
||||
|
||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc);
|
||||
|
||||
int avr_txrx_bit(int fd, int bit);
|
||||
|
||||
unsigned char avr_txrx(int fd, unsigned char byte);
|
||||
|
||||
int avr_set_bits(OPCODE * op, unsigned char * cmd);
|
||||
|
||||
int avr_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char * value);
|
||||
|
||||
int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
int verbose);
|
||||
|
||||
int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
@@ -44,21 +64,28 @@ int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char data);
|
||||
|
||||
int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
int verbose);
|
||||
|
||||
int avr_signature(PROGRAMMER * pgm, AVRPART * p);
|
||||
|
||||
char * avr_memtstr(int memtype);
|
||||
|
||||
int avr_initmem(AVRPART * p);
|
||||
|
||||
int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size);
|
||||
|
||||
void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type,
|
||||
int verbose);
|
||||
|
||||
void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose);
|
||||
|
||||
int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles);
|
||||
|
||||
int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles);;
|
||||
|
||||
int avr_mem_hiaddr(AVRMEM * mem);
|
||||
|
||||
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p);
|
||||
|
||||
extern void report_progress (int completed, int total, char *hdr);
|
||||
|
||||
#endif
|
||||
|
||||
230
avrdude/avr910.c
230
avrdude/avr910.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003 Theodore A. Roth <troth@openavr.org>
|
||||
*
|
||||
* 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
|
||||
@@ -30,8 +30,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "avr.h"
|
||||
#include "pgm.h"
|
||||
@@ -43,30 +41,36 @@ extern int do_cycles;
|
||||
|
||||
static char has_auto_incr_addr;
|
||||
|
||||
/* These two defines are only for debugging. Will remove them once it starts
|
||||
working. */
|
||||
|
||||
#define show_func_info() \
|
||||
fprintf(stderr, "%s: line %d: called %s()\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__)
|
||||
|
||||
#define no_show_func_info()
|
||||
|
||||
|
||||
static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
{
|
||||
return serial_send(pgm->fd, (unsigned char *)buf, len);
|
||||
no_show_func_info();
|
||||
|
||||
return serial_send(pgm->fd, buf, len);
|
||||
}
|
||||
|
||||
|
||||
static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
{
|
||||
int rv;
|
||||
no_show_func_info();
|
||||
|
||||
rv = serial_recv(pgm->fd, (unsigned char *)buf, len);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: avr910_recv(): programmer is not responding\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
return serial_recv(pgm->fd, buf, len);
|
||||
}
|
||||
|
||||
|
||||
static int avr910_drain(PROGRAMMER * pgm, int display)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return serial_drain(pgm->fd, display);
|
||||
}
|
||||
|
||||
@@ -84,19 +88,56 @@ static void avr910_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg)
|
||||
}
|
||||
|
||||
|
||||
static int avr910_rdy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int avr910_err_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int avr910_pgm_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int avr910_vfy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* issue the 'chip erase' command to the AVR device
|
||||
*/
|
||||
static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
avr910_send(pgm, "e", 1);
|
||||
avr910_vfy_cmd_sent(pgm, "chip erase");
|
||||
|
||||
/*
|
||||
* avr910 firmware may not delay long enough
|
||||
*/
|
||||
usleep (p->chip_erase_delay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -120,10 +161,38 @@ static void avr910_leave_prog_mode(PROGRAMMER * pgm)
|
||||
*/
|
||||
static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* apply power to the AVR processor
|
||||
*/
|
||||
static void avr910_powerup(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* remove power from the AVR processor
|
||||
*/
|
||||
static void avr910_powerdown(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* initialize the AVR device and prepare it to accept commands
|
||||
*/
|
||||
@@ -134,9 +203,10 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
char hw[2];
|
||||
char buf[10];
|
||||
char type;
|
||||
char c;
|
||||
unsigned char c;
|
||||
int dev_supported = 0;
|
||||
AVRPART * part;
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
/* Get the programmer identifier. Programmer returns exactly 7 chars
|
||||
_without_ the null.*/
|
||||
@@ -177,9 +247,7 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
avr910_recv(pgm, &c, 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
part = locate_part_by_avr910_devcode(part_list, c);
|
||||
|
||||
fprintf(stderr, " Device code: 0x%02x = %s\n", c, part ? part->desc : "(unknown)");
|
||||
fprintf(stderr, " Device code: 0x%02x\n", c);
|
||||
|
||||
/* FIXME: Need to lookup devcode and report the device. */
|
||||
|
||||
@@ -209,8 +277,30 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
}
|
||||
|
||||
|
||||
static int avr910_save(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void avr910_restore(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void avr910_disable(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return;
|
||||
@@ -219,6 +309,8 @@ static void avr910_disable(PROGRAMMER * pgm)
|
||||
|
||||
static void avr910_enable(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return;
|
||||
@@ -232,7 +324,9 @@ static void avr910_enable(PROGRAMMER * pgm)
|
||||
static int avr910_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
char buf[5];
|
||||
unsigned char buf[5];
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
/* FIXME: Insert version check here */
|
||||
|
||||
@@ -254,28 +348,23 @@ static int avr910_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
}
|
||||
|
||||
|
||||
static int avr910_open(PROGRAMMER * pgm, char * port)
|
||||
static void avr910_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
/*
|
||||
* If baudrate was not specified use 19.200 Baud
|
||||
*/
|
||||
if(pgm->baudrate == 0) {
|
||||
pgm->baudrate = 19200;
|
||||
}
|
||||
no_show_func_info();
|
||||
|
||||
strcpy(pgm->port, port);
|
||||
pgm->fd = serial_open(port, pgm->baudrate);
|
||||
pgm->fd = serial_open(port, 19200);
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
avr910_drain (pgm, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void avr910_close(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
avr910_leave_prog_mode(pgm);
|
||||
|
||||
serial_close(pgm->fd);
|
||||
@@ -285,13 +374,15 @@ static void avr910_close(PROGRAMMER * pgm)
|
||||
|
||||
static void avr910_display(PROGRAMMER * pgm, char * p)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void avr910_set_addr(PROGRAMMER * pgm, unsigned long addr)
|
||||
{
|
||||
char cmd[3];
|
||||
unsigned char cmd[3];
|
||||
|
||||
cmd[0] = 'A';
|
||||
cmd[1] = (addr >> 8) & 0xff;
|
||||
@@ -302,10 +393,26 @@ static void avr910_set_addr(PROGRAMMER * pgm, unsigned long addr)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For some reason, if we don't do this when writing to flash, the first byte
|
||||
* of flash is not programmed. I susect that the board got out of sync after
|
||||
* the erase and sending another command gets us back in sync. -TRoth
|
||||
*/
|
||||
static void avr910_write_setup(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||
{
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
avr910_send(pgm, "y", 1);
|
||||
avr910_vfy_cmd_sent(pgm, "clear LED");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int avr910_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned long addr, unsigned char value)
|
||||
{
|
||||
char cmd[2];
|
||||
unsigned char cmd[2];
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
if (addr & 0x01) {
|
||||
@@ -347,7 +454,7 @@ static int avr910_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
cached = 0;
|
||||
}
|
||||
else {
|
||||
char buf[2];
|
||||
unsigned char buf[2];
|
||||
|
||||
avr910_set_addr(pgm, addr >> 1);
|
||||
|
||||
@@ -358,7 +465,7 @@ static int avr910_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
|
||||
if ((addr & 0x01) == 0) {
|
||||
*value = buf[1];
|
||||
// cached = 1;
|
||||
cached = 1;
|
||||
cvalue = buf[0];
|
||||
caddr = addr;
|
||||
}
|
||||
@@ -376,7 +483,7 @@ static int avr910_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
{
|
||||
avr910_set_addr(pgm, addr);
|
||||
avr910_send(pgm, "d", 1);
|
||||
avr910_recv(pgm, (char *)value, 1);
|
||||
avr910_recv(pgm, value, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -385,6 +492,8 @@ static int avr910_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
static int avr910_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned long addr, unsigned char * value)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
return avr910_read_byte_flash(pgm, p, m, addr, value);
|
||||
}
|
||||
@@ -401,13 +510,15 @@ static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
unsigned char cmd[] = {'c', 'C'};
|
||||
char buf[2];
|
||||
unsigned char buf[2];
|
||||
unsigned int addr = 0;
|
||||
unsigned int max_addr = n_bytes;
|
||||
unsigned int page_addr;
|
||||
int page_bytes = page_size;
|
||||
int page_wr_cmd_pending = 0;
|
||||
|
||||
avr910_write_setup(pgm, p, m);
|
||||
|
||||
page_addr = addr;
|
||||
avr910_set_addr(pgm, addr>>1);
|
||||
|
||||
@@ -421,25 +532,21 @@ static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
addr++;
|
||||
page_bytes--;
|
||||
|
||||
if (m->paged && (page_bytes == 0)) {
|
||||
if ((has_auto_incr_addr != 'Y') && ((addr & 0x01) == 0)) {
|
||||
avr910_set_addr(pgm, addr>>1);
|
||||
}
|
||||
else if (m->paged && (page_bytes == 0)) {
|
||||
/* Send the "Issue Page Write" if we have sent a whole page. */
|
||||
|
||||
avr910_set_addr(pgm, page_addr>>1);
|
||||
avr910_send(pgm, "m", 1);
|
||||
avr910_vfy_cmd_sent(pgm, "flush page");
|
||||
|
||||
page_wr_cmd_pending = 0;
|
||||
usleep(m->max_write_delay);
|
||||
avr910_set_addr(pgm, addr>>1);
|
||||
|
||||
/* Set page address for next page. */
|
||||
|
||||
page_addr = addr;
|
||||
page_bytes = page_size;
|
||||
}
|
||||
else if ((has_auto_incr_addr != 'Y') && ((addr & 0x01) == 0)) {
|
||||
avr910_set_addr(pgm, addr>>1);
|
||||
}
|
||||
|
||||
report_progress (addr, max_addr, NULL);
|
||||
}
|
||||
@@ -451,7 +558,6 @@ static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
avr910_set_addr(pgm, page_addr>>1);
|
||||
avr910_send(pgm, "m", 1);
|
||||
avr910_vfy_cmd_sent(pgm, "flush final page");
|
||||
usleep(m->max_write_delay);
|
||||
}
|
||||
|
||||
return addr;
|
||||
@@ -461,7 +567,7 @@ static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p,
|
||||
AVRMEM * m, int page_size, int n_bytes)
|
||||
{
|
||||
char cmd[2];
|
||||
unsigned char cmd[2];
|
||||
unsigned int addr = 0;
|
||||
unsigned int max_addr = n_bytes;
|
||||
|
||||
@@ -473,7 +579,6 @@ static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p,
|
||||
cmd[1] = m->buf[addr];
|
||||
avr910_send(pgm, cmd, sizeof(cmd));
|
||||
avr910_vfy_cmd_sent(pgm, "write byte");
|
||||
usleep(m->max_write_delay);
|
||||
|
||||
addr++;
|
||||
|
||||
@@ -488,7 +593,7 @@ static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p,
|
||||
}
|
||||
|
||||
|
||||
static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
@@ -506,11 +611,11 @@ static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
char cmd;
|
||||
unsigned char cmd;
|
||||
int rd_size;
|
||||
unsigned int addr = 0;
|
||||
unsigned int max_addr;
|
||||
char buf[2];
|
||||
unsigned char buf[2];
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
cmd = 'R';
|
||||
@@ -538,7 +643,7 @@ static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
m->buf[addr*2+1] = buf[0]; /* MSB */
|
||||
}
|
||||
else {
|
||||
avr910_recv(pgm, (char *)&m->buf[addr], 1);
|
||||
avr910_recv(pgm, &m->buf[addr], 1);
|
||||
}
|
||||
|
||||
addr++;
|
||||
@@ -557,13 +662,15 @@ static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
|
||||
static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
if (m->size < 3) {
|
||||
fprintf(stderr, "%s: memsize too small for sig byte read", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
avr910_send(pgm, "s", 1);
|
||||
avr910_recv(pgm, (char *)m->buf, 3);
|
||||
avr910_recv(pgm, m->buf, 3);
|
||||
|
||||
return 3;
|
||||
}
|
||||
@@ -571,15 +678,25 @@ static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||
|
||||
void avr910_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
strcpy(pgm->type, "avr910");
|
||||
|
||||
/*
|
||||
* mandatory functions
|
||||
*/
|
||||
pgm->rdy_led = avr910_rdy_led;
|
||||
pgm->err_led = avr910_err_led;
|
||||
pgm->pgm_led = avr910_pgm_led;
|
||||
pgm->vfy_led = avr910_vfy_led;
|
||||
pgm->initialize = avr910_initialize;
|
||||
pgm->display = avr910_display;
|
||||
pgm->save = avr910_save;
|
||||
pgm->restore = avr910_restore;
|
||||
pgm->enable = avr910_enable;
|
||||
pgm->disable = avr910_disable;
|
||||
pgm->powerup = avr910_powerup;
|
||||
pgm->powerdown = avr910_powerdown;
|
||||
pgm->program_enable = avr910_program_enable;
|
||||
pgm->chip_erase = avr910_chip_erase;
|
||||
pgm->cmd = avr910_cmd;
|
||||
@@ -590,6 +707,7 @@ void avr910_initpgm(PROGRAMMER * pgm)
|
||||
* optional functions
|
||||
*/
|
||||
|
||||
pgm->write_setup = avr910_write_setup;
|
||||
pgm->write_byte = avr910_write_byte;
|
||||
pgm->read_byte = avr910_read_byte;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003 Theodore A. Roth <troth@openavr.org>
|
||||
*
|
||||
* 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
|
||||
@@ -22,7 +22,7 @@
|
||||
#ifndef __avr910_h__
|
||||
#define __avr910_h__
|
||||
|
||||
#include "avrpart.h"
|
||||
#include "config.h"
|
||||
|
||||
void avr910_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\"
|
||||
.\" avrdude - A Downloader/Uploader for AVR device programmers
|
||||
.\" Copyright (C) 2001, 2002, 2003, 2005 Joerg Wunsch
|
||||
.\" Copyright (C) 2001, 2002, 2003 Joerg Wunsch
|
||||
.\"
|
||||
.\" 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
|
||||
@@ -19,7 +19,7 @@
|
||||
.\"
|
||||
.\" $Id$
|
||||
.\"
|
||||
.Dd DATE September 18, 2005
|
||||
.Dd DATE July 24, 2003
|
||||
.Os
|
||||
.Dt AVRDUDE 1
|
||||
.Sh NAME
|
||||
@@ -28,8 +28,6 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Fl p Ar partno
|
||||
.Op Fl b Ar baudrate
|
||||
.Op Fl B Ar bitclock
|
||||
.Op Fl c Ar programmer-id
|
||||
.Op Fl C Ar config-file
|
||||
.Op Fl D
|
||||
@@ -37,13 +35,15 @@
|
||||
.Oo Fl E Ar exitspec Ns
|
||||
.Op \&, Ns Ar exitspec
|
||||
.Oc
|
||||
.Op Fl f Ar format
|
||||
.Op Fl F
|
||||
.Op Fl i Ar filename
|
||||
.Op Fl m Ar memtype
|
||||
.Op Fl o Ar filename
|
||||
.Op Fl n
|
||||
.Op Fl P Ar port
|
||||
.Op Fl q
|
||||
.Op Fl s
|
||||
.Op Fl t
|
||||
.Op Fl u
|
||||
.Op Fl U Ar memtype:op:filename:filefmt
|
||||
.Op Fl v
|
||||
.Op Fl V
|
||||
@@ -54,16 +54,10 @@
|
||||
is a program for downloading code and data to Atmel AVR
|
||||
microcontrollers.
|
||||
.Nm Avrdude
|
||||
supports Atmel's STK500 programmer,
|
||||
Atmel's JTAG ICE mkII,
|
||||
programmers complying to AppNote AVR910 and AVR109 (including the Butterfly),
|
||||
as well as a simple hard-wired
|
||||
supports Atmel's STK500 programmer as well as a simple hard-wired
|
||||
programmer connected directly to a
|
||||
.Xr ppi 4
|
||||
or
|
||||
.Xr parport 4
|
||||
parallel port, or to a standard serial port.
|
||||
In the simplest case, the hardware consists just of a
|
||||
parallel port. In the simplest case, the hardware consists just of a
|
||||
cable connecting the respective AVR signal lines to the parallel port.
|
||||
.Pp
|
||||
The MCU is programmed in
|
||||
@@ -85,27 +79,14 @@ signal is available to control a buffer/driver IC 74LS367 (or
|
||||
74HCT367). The latter can be useful to decouple the parallel port
|
||||
from the MCU when in-system programming is used.
|
||||
.Pp
|
||||
A number of equally simple bit-bang programming adapters that connect
|
||||
to a serial port are supported as well, among them the popular
|
||||
Ponyprog serial adapter, and the DASA and DASA3 adapters that used to
|
||||
be supported by uisp(1).
|
||||
Note that these adapters are meant to be attached to a physical serial
|
||||
port.
|
||||
Connecting to a serial port emulated on top of USB is likely to not
|
||||
work at all, or to work abysmally slow.
|
||||
See the file
|
||||
.Pa ${PREFIX}/share/doc/avrdude/avrdude.pdf
|
||||
for a schematic of the
|
||||
.Xr ppi 4
|
||||
based programming hardware.
|
||||
.Pp
|
||||
Atmel's STK500 programmer is also supported and connects to a serial
|
||||
port.
|
||||
Both, firmware versions 1.x and 2.x can be handled, but require a
|
||||
different programmer type specification (by now).
|
||||
.Pp
|
||||
The simple serial programmer described in Atmel's application note
|
||||
AVR910, and the bootloader described in Atmel's application note
|
||||
AVR109 (which is also used by the AVR Butterfly evaluation board), are
|
||||
supported on a serial port.
|
||||
.Pp
|
||||
Atmel's JTAG ICE mkII is supported as well to up- or download memory
|
||||
areas from/to an AVR target (no support for on-chip debugging).
|
||||
.Pp
|
||||
Input files can be provided, and output files can be written in
|
||||
different file formats, such as raw binary files containing the data
|
||||
@@ -155,9 +136,7 @@ the format. Currently, the following MCU types are understood:
|
||||
.TS
|
||||
ll.
|
||||
\fBOption tag\fP \fBOfficial part name\fP
|
||||
c128 AT90CAN128
|
||||
pwm2 AT90PWM2
|
||||
pwm3 AT90PWM3
|
||||
t15 ATtiny15
|
||||
1200 AT90S1200
|
||||
2313 AT90S2313
|
||||
2333 AT90S2333
|
||||
@@ -167,53 +146,17 @@ pwm3 AT90PWM3
|
||||
4434 AT90S4434
|
||||
8515 AT90S8515
|
||||
8535 AT90S8535
|
||||
m103 ATmega103
|
||||
m128 ATmega128
|
||||
m16 ATmega16
|
||||
m161 ATmega161
|
||||
m162 ATmega162
|
||||
m163 ATmega163
|
||||
m164 ATmega164
|
||||
m169 ATmega169
|
||||
m32 ATmega32
|
||||
m324 ATmega324
|
||||
m329 ATmega329
|
||||
m3290 ATmega3290
|
||||
m48 ATmega48
|
||||
m64 ATmega64
|
||||
m644 ATmega644
|
||||
m649 ATmega649
|
||||
m6490 ATmega6490
|
||||
m8 ATmega8
|
||||
m8515 ATmega8515
|
||||
m8535 ATmega8535
|
||||
m88 ATmega88
|
||||
t12 ATtiny12
|
||||
t13 ATtiny13
|
||||
t15 ATtiny15
|
||||
t2313 ATtiny2313
|
||||
t25 ATtiny25
|
||||
t26 ATtiny26
|
||||
t45 ATtiny45
|
||||
t85 ATtiny85
|
||||
m163 ATMEGA163
|
||||
m169 ATMEGA169
|
||||
m128 ATMEGA128
|
||||
m103 ATMEGA103
|
||||
m16 ATMEGA16
|
||||
m8 ATMEGA8
|
||||
.TE
|
||||
.Bl -tag -width "(*) "
|
||||
.It "(*)"
|
||||
The AT90S2323 and ATtiny22 use the same algorithm.
|
||||
The AT90S2323 uses the same algorithm.
|
||||
.El
|
||||
.It Fl b Ar baudrate
|
||||
Override the RS-232 connection baud rate specified in the respective
|
||||
programmer's entry of the configuration file.
|
||||
.It Fl B Ar bitclock
|
||||
Specify the bit clock period for the JTAG interface (JTAG ICE only).
|
||||
The value is a floating-point number in microseconds.
|
||||
The default value of the JTAG ICE results in about 1 microsecond bit
|
||||
clock period, suitable for target MCUs running at 4 MHz clock and
|
||||
above.
|
||||
Unlike certain parameters in the STK500, the JTAG ICE resets all its
|
||||
parameters to default values when the programming software signs
|
||||
off from the ICE, so for MCUs running at lower clock speeds, this
|
||||
parameter must be specified on the command-line.
|
||||
.It Fl c Ar programmer-id
|
||||
Use the pin configuration specified by the argument. Pin
|
||||
configurations are read from the config file (see the
|
||||
@@ -246,6 +189,11 @@ option with flash memory is specified,
|
||||
will perform a chip erase before starting any of the programming
|
||||
operations, since it generally is a mistake to program the flash
|
||||
without performing an erase first. This option disables that.
|
||||
However, to remain backward compatible, the
|
||||
.Fl i ,
|
||||
and
|
||||
.Fl m
|
||||
options automatically disable the auto erase feature.
|
||||
.It Fl e
|
||||
Causes a chip erase to be executed. This will reset the contents of the
|
||||
flash ROM and EEPROM to the value
|
||||
@@ -309,130 +257,11 @@ pins of the parallel port down at program exit.
|
||||
Multiple
|
||||
.Ar exitspec
|
||||
arguments can be separated with commas.
|
||||
.It Fl F
|
||||
Normally,
|
||||
.Nm
|
||||
tries to verify that the device signature read from the part is
|
||||
reasonable before continuing. Since it can happen from time to time
|
||||
that a device has a broken (erased or overwritten) device signature
|
||||
but is otherwise operating normally, this options is provided to
|
||||
override the check.
|
||||
.It Fl n
|
||||
No-write - disables actually writing data to the MCU (useful for debugging
|
||||
.Nm avrdude
|
||||
).
|
||||
.It Fl P Ar port
|
||||
Use
|
||||
.Ar port
|
||||
to identify the device to which the programmer is attached. By
|
||||
default the
|
||||
.Pa /dev/ppi0
|
||||
port is used, but if the programmer type normally connects to the
|
||||
serial port, the
|
||||
.Pa /dev/cuaa0
|
||||
port is the default. If you need to use a different parallel or
|
||||
serial port, use this option to specify the alternate port name.
|
||||
.Pp
|
||||
For the JTAG ICE mkII, if
|
||||
.Nm
|
||||
has been configured with libusb support,
|
||||
.Ar port
|
||||
can alternatively be specified as
|
||||
.Ar usb Ns Op \&: Ns Ar serialno .
|
||||
This will cause
|
||||
.Nm
|
||||
to search a JTAG ICE mkII on USB.
|
||||
If
|
||||
.Ar serialno
|
||||
is also specified, it will be matched against the serial number read
|
||||
from any JTAG ICE mkII found on USB.
|
||||
The match is done after stripping any existing colons from the given
|
||||
serial number, and right-to-left, so only the least significant bytes
|
||||
from the serial number need to be given.
|
||||
.It Fl q
|
||||
Disable (or quell) output of the progress bar while reading or writing
|
||||
to the device. Specify it a second time for even quieter operation.
|
||||
.It Fl s
|
||||
Disable safemode prompting. When safemode discovers that one or more
|
||||
fuse bits have unintentionally changed, it will prompt for
|
||||
confirmation regarding whether or not it should attempt to recover the
|
||||
fuse bit(s). Specifying this flag disables the prompt and assumes
|
||||
that the fuse bit(s) should be recovered without asking for
|
||||
confirmation first.
|
||||
.It Fl t
|
||||
Tells
|
||||
.Nm
|
||||
to enter the interactive ``terminal'' mode instead of up- or downloading
|
||||
files. See below for a detailed description of the terminal mode.
|
||||
.It Fl u
|
||||
Disable the safemode fuse bit checks. Safemode is enabled by default
|
||||
and is intended to prevent unintentional fuse bit changes. When
|
||||
enabled, safemode will issue a warning if the any fuse bits are found
|
||||
to be different at program exit than they were when
|
||||
.Nm
|
||||
was invoked. Safemode won't alter fuse bits itself, but rather will
|
||||
prompt for instructions, unless the terminal is non-interactive, in
|
||||
which case safemode is disabled. See the
|
||||
.Fl s
|
||||
option to disable safemode prompting.
|
||||
.It Xo Fl U Ar memtype Ns
|
||||
.Ar \&: Ns Ar op Ns
|
||||
.Ar \&: Ns Ar filename Ns
|
||||
.Op \&: Ns Ar format
|
||||
.Xc
|
||||
Perform a memory operation as indicated. The
|
||||
.Ar memtype
|
||||
field specifies the memory type to operate on.
|
||||
The available memory types are device-dependant, the actual
|
||||
configuration can be viewed with the
|
||||
.Cm part
|
||||
command in terminal mode.
|
||||
Typically, a device's memory configuration at least contains
|
||||
the memory types
|
||||
.Ar flash
|
||||
and
|
||||
.Ar eeprom .
|
||||
All memory types currently known are:
|
||||
.Bl -tag -width "calibration" -compact
|
||||
.It calibration
|
||||
One or more bytes of RC oscillator calibration data.
|
||||
.It eeprom
|
||||
The EEPROM of the device.
|
||||
.It efuse
|
||||
The extended fuse byte.
|
||||
.It flash
|
||||
The flash ROM of the device.
|
||||
.It fuse
|
||||
The fuse byte in devices that have only a single fuse byte.
|
||||
.It hfuse
|
||||
The high fuse byte.
|
||||
.It lfuse
|
||||
The low fuse byte.
|
||||
.It lock
|
||||
The lock byte.
|
||||
.It signature
|
||||
The three device signature bytes (device ID).
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Ar op
|
||||
field specifies what operation to perform:
|
||||
.Bl -tag -width noreset
|
||||
.It Ar r
|
||||
read device memory and write to the specified file
|
||||
.It Ar w
|
||||
read data from the specified file and write to the device memory
|
||||
.It Ar v
|
||||
read data from both the device and the specified file and perform a verify
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Ar filename
|
||||
field indicates the name of the file to read or write.
|
||||
The
|
||||
.Ar format
|
||||
field is optional and contains the format of the file to read or
|
||||
write.
|
||||
.It Fl f Ar format
|
||||
(Deprecated, use
|
||||
.Fl U
|
||||
instead.) This option specifies the file format for the input or
|
||||
output files to be processed.
|
||||
.Ar Format
|
||||
can be one of:
|
||||
.Bl -tag -width sss
|
||||
@@ -454,13 +283,110 @@ provided at
|
||||
.Pp
|
||||
The default is to use auto detection for input files, and raw binary
|
||||
format for output files.
|
||||
Note that if
|
||||
.It Fl F
|
||||
Normally,
|
||||
.Nm
|
||||
tries to verify that the device signature read from the part is
|
||||
reasonable before continuing. Since it can happen from time to time
|
||||
that a device has a broken (erased or overwritten) device signature
|
||||
but is otherwise operating normally, this options is provided to
|
||||
override the check.
|
||||
.It Fl i Ar filename
|
||||
(Deprecated, use
|
||||
.Fl U
|
||||
instead.) Specifies the input file to be programmed into the MCU.
|
||||
Can be specified as
|
||||
.Ql \&-
|
||||
to use
|
||||
.Em stdin
|
||||
as the input.
|
||||
.It Fl I Ar data
|
||||
(Deprecated, use
|
||||
.Fl U
|
||||
instead.) Same as specifying
|
||||
.Fl i
|
||||
and
|
||||
.Fl f Ar m
|
||||
together, i.e., this is a shortcut for using immediate file input mode
|
||||
where the filename field is used as the data itself. Useful for
|
||||
programming single byte memories such as fuse bytes without having to
|
||||
use single byte files or enter interactive terminal mode.
|
||||
.It Fl m Ar memtype
|
||||
(Deprecated, use
|
||||
.Fl U
|
||||
instead.) Specifies which program area of the MCU to read or write;
|
||||
allowable values depend on the MCU being programmed, but most support
|
||||
at least
|
||||
.Em eeprom
|
||||
for the EEPROM, and
|
||||
.Em flash
|
||||
for the flash ROM. Use the
|
||||
.Fl v
|
||||
option on the command line or the
|
||||
.Ar part
|
||||
command from terminal mode to display all the memory types supported
|
||||
by a particular device. The default is
|
||||
.Em flash .
|
||||
.It Fl n
|
||||
No-write - disables actually writing data to the MCU (useful for debugging
|
||||
.Nm avrdude
|
||||
).
|
||||
.It Fl o Ar filename
|
||||
(Deprecated, use
|
||||
.Fl U
|
||||
instead.) Specifies the name of the output file to write, and causes
|
||||
the respective memory area to be read from the MCU. Can be specified
|
||||
as
|
||||
.Ql \&-
|
||||
to write to
|
||||
.Em stdout .
|
||||
.It Fl P Ar port
|
||||
Use
|
||||
.Ar port
|
||||
to identify the device to which the programmer is attached. By
|
||||
default the
|
||||
.Pa /dev/ppi0
|
||||
port is used, but if the programmer type normally connects to the
|
||||
serial port, the
|
||||
.Pa /dev/cuaa0
|
||||
port is the default. If you need to use a different parallel or
|
||||
serial port, use this option to specify the alternate port name.
|
||||
.It Fl q
|
||||
Disable (or quell) output of the progress bar while reading or writing
|
||||
to the device.
|
||||
.It Fl t
|
||||
Tells
|
||||
.Nm
|
||||
to enter the interactive ``terminal'' mode instead of up- or downloading
|
||||
files. See below for a detailed description of the terminal mode.
|
||||
.It Xo Fl U Ar memtype Ns
|
||||
.Ar \&: Ns Ar op Ns
|
||||
.Ar \&: Ns Ar filename Ns
|
||||
.Op \&: Ns Ar format
|
||||
.Xc
|
||||
Perform a memory operation as indicated. The
|
||||
.Ar memtype
|
||||
field specifies the memory type to operate on. The
|
||||
.Ar op
|
||||
field specifies what operation to perform:
|
||||
.Bl -tag -width noreset
|
||||
.It Ar r
|
||||
read device memory and write to the specified file
|
||||
.It Ar w
|
||||
read data from the specified file and write to the device memory
|
||||
.It Ar v
|
||||
read data from both the device and the specified file and perform a verify
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Ar filename
|
||||
contains a colon, the
|
||||
field indicates the name of the file to read or write.
|
||||
The
|
||||
.Ar format
|
||||
field is no longer optional since the filename part following the colon
|
||||
would otherwise be misinterpreted as
|
||||
.Ar format .
|
||||
field is optional and contains the format of the file to read or
|
||||
write. See the
|
||||
.Fl f
|
||||
option for possible values.
|
||||
.It Fl v
|
||||
Enable verbose output.
|
||||
.It Fl V
|
||||
@@ -533,9 +459,7 @@ does not implement the command.
|
||||
.It Ar sig
|
||||
Display the device signature bytes.
|
||||
.It Ar part
|
||||
Display the current part settings and parameters. Includes chip
|
||||
specific information including all memory types supported by the
|
||||
device, read/write timing, etc.
|
||||
Display the current part settings.
|
||||
.It Ar vtarg voltage
|
||||
Set the target's supply voltage to
|
||||
.Ar voltage
|
||||
@@ -562,25 +486,9 @@ by 1E3.
|
||||
.It Ar fosc off
|
||||
Turn the master oscillator off.
|
||||
.Em Only supported on the STK500 programmer.
|
||||
.It Ar sck period
|
||||
.Em STK500 programmer only:
|
||||
Set the SCK clock period to
|
||||
.Ar period
|
||||
microseconds.
|
||||
.Pp
|
||||
.Em JTAG ICE only:
|
||||
Set the JTAG ICE bit clock period to
|
||||
.Ar period
|
||||
microseconds.
|
||||
Note that unlike STK500 settings, this setting will be reverted to
|
||||
its default value (approximately 1 microsecond) when the programming
|
||||
software signs off from the JTAG ICE.
|
||||
.It Ar parms
|
||||
.Em STK500 programmer only:
|
||||
Display the current voltage and master oscillator parameters.
|
||||
.Pp
|
||||
.Em JTAG ICE only:
|
||||
Display the current target supply voltage and JTAG bit clock rate/period.
|
||||
.Em Only supported on the STK500 programmer.
|
||||
.It Ar \&?
|
||||
.It Ar help
|
||||
Give a short on-line summary of the available commands.
|
||||
@@ -637,17 +545,4 @@ This man page by
|
||||
.ie t J\(:org Wunsch.
|
||||
.el Joerg Wunsch.
|
||||
.Sh BUGS
|
||||
Please report bugs via
|
||||
.Dl "http://savannah.nongnu.org/bugs/?group=avrdude" .
|
||||
.Pp
|
||||
The JTAGICE mkII programmer currently cannot write to the flash ROM
|
||||
one byte at a time.
|
||||
For that reason, updating the flash ROM from terminal mode does not
|
||||
work.
|
||||
.Pp
|
||||
The device IDs used by AVR910 and AVR109 do not match, so the
|
||||
avr109 (aka. butterfly) programmer might report
|
||||
.Dl "selected device is not supported by programmer" .
|
||||
Use the -F option to force
|
||||
.Nm
|
||||
to contiue anway.
|
||||
Please report bugs to avrdude-dev@nongnu.org.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
BIN
avrdude/avrdude.pdf
Normal file
BIN
avrdude/avrdude.pdf
Normal file
Binary file not shown.
@@ -1,537 +0,0 @@
|
||||
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 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$ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "avrpart.h"
|
||||
#include "pindefs.h"
|
||||
|
||||
extern char * progname;
|
||||
|
||||
|
||||
/***
|
||||
*** Elementary functions dealing with OPCODE structures
|
||||
***/
|
||||
|
||||
OPCODE * avr_new_opcode(void)
|
||||
{
|
||||
OPCODE * m;
|
||||
|
||||
m = (OPCODE *)malloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
fprintf(stderr, "avr_new_opcode(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_bits()
|
||||
*
|
||||
* Set instruction bits in the specified command based on the opcode.
|
||||
*/
|
||||
int avr_set_bits(OPCODE * op, unsigned char * cmd)
|
||||
{
|
||||
int i, j, bit;
|
||||
unsigned char mask;
|
||||
|
||||
for (i=0; i<32; i++) {
|
||||
if (op->bit[i].type == AVR_CMDBIT_VALUE) {
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
if (op->bit[i].value)
|
||||
cmd[j] = cmd[j] | mask;
|
||||
else
|
||||
cmd[j] = cmd[j] & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_addr()
|
||||
*
|
||||
* Set address bits in the specified command based on the opcode, and
|
||||
* the address.
|
||||
*/
|
||||
int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr)
|
||||
{
|
||||
int i, j, bit;
|
||||
unsigned long value;
|
||||
unsigned char mask;
|
||||
|
||||
for (i=0; i<32; i++) {
|
||||
if (op->bit[i].type == AVR_CMDBIT_ADDRESS) {
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
value = addr >> op->bit[i].bitno & 0x01;
|
||||
if (value)
|
||||
cmd[j] = cmd[j] | mask;
|
||||
else
|
||||
cmd[j] = cmd[j] & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_set_input()
|
||||
*
|
||||
* Set input data bits in the specified command based on the opcode,
|
||||
* and the data byte.
|
||||
*/
|
||||
int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data)
|
||||
{
|
||||
int i, j, bit;
|
||||
unsigned char value;
|
||||
unsigned char mask;
|
||||
|
||||
for (i=0; i<32; i++) {
|
||||
if (op->bit[i].type == AVR_CMDBIT_INPUT) {
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
value = data >> op->bit[i].bitno & 0x01;
|
||||
if (value)
|
||||
cmd[j] = cmd[j] | mask;
|
||||
else
|
||||
cmd[j] = cmd[j] & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* avr_get_output()
|
||||
*
|
||||
* Retreive output data bits from the command results based on the
|
||||
* opcode data.
|
||||
*/
|
||||
int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data)
|
||||
{
|
||||
int i, j, bit;
|
||||
unsigned char value;
|
||||
unsigned char mask;
|
||||
|
||||
for (i=0; i<32; i++) {
|
||||
if (op->bit[i].type == AVR_CMDBIT_OUTPUT) {
|
||||
j = 3 - i / 8;
|
||||
bit = i % 8;
|
||||
mask = 1 << bit;
|
||||
value = ((res[j] & mask) >> bit) & 0x01;
|
||||
value = value << op->bit[i].bitno;
|
||||
if (value)
|
||||
*data = *data | value;
|
||||
else
|
||||
*data = *data & ~value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char * avr_op_str(int op)
|
||||
{
|
||||
switch (op) {
|
||||
case AVR_OP_READ : return "READ"; break;
|
||||
case AVR_OP_WRITE : return "WRITE"; break;
|
||||
case AVR_OP_READ_LO : return "READ_LO"; break;
|
||||
case AVR_OP_READ_HI : return "READ_HI"; break;
|
||||
case AVR_OP_WRITE_LO : return "WRITE_LO"; break;
|
||||
case AVR_OP_WRITE_HI : return "WRITE_HI"; break;
|
||||
case AVR_OP_LOADPAGE_LO : return "LOADPAGE_LO"; break;
|
||||
case AVR_OP_LOADPAGE_HI : return "LOADPAGE_HI"; break;
|
||||
case AVR_OP_WRITEPAGE : return "WRITEPAGE"; break;
|
||||
case AVR_OP_CHIP_ERASE : return "CHIP_ERASE"; break;
|
||||
case AVR_OP_PGM_ENABLE : return "PGM_ENABLE"; break;
|
||||
default : return "<unknown opcode>"; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char * bittype(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case AVR_CMDBIT_IGNORE : return "IGNORE"; break;
|
||||
case AVR_CMDBIT_VALUE : return "VALUE"; break;
|
||||
case AVR_CMDBIT_ADDRESS : return "ADDRESS"; break;
|
||||
case AVR_CMDBIT_INPUT : return "INPUT"; break;
|
||||
case AVR_CMDBIT_OUTPUT : return "OUTPUT"; break;
|
||||
default : return "<unknown bit type>"; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***
|
||||
*** Elementary functions dealing with AVRMEM structures
|
||||
***/
|
||||
|
||||
AVRMEM * avr_new_memtype(void)
|
||||
{
|
||||
AVRMEM * m;
|
||||
|
||||
m = (AVRMEM *)malloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
fprintf(stderr, "avr_new_memtype(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocate and initialize memory buffers for each of the device's
|
||||
* defined memory regions.
|
||||
*/
|
||||
int avr_initmem(AVRPART * p)
|
||||
{
|
||||
LNODEID ln;
|
||||
AVRMEM * m;
|
||||
|
||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
m->buf = (unsigned char *) malloc(m->size);
|
||||
if (m->buf == NULL) {
|
||||
fprintf(stderr, "%s: can't alloc buffer for %s size of %d bytes\n",
|
||||
progname, m->desc, m->size);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AVRMEM * avr_dup_mem(AVRMEM * m)
|
||||
{
|
||||
AVRMEM * n;
|
||||
|
||||
n = avr_new_memtype();
|
||||
|
||||
*n = *m;
|
||||
|
||||
n->buf = (unsigned char *)malloc(n->size);
|
||||
if (n->buf == NULL) {
|
||||
fprintf(stderr,
|
||||
"avr_dup_mem(): out of memory (memsize=%d)\n",
|
||||
n->size);
|
||||
exit(1);
|
||||
}
|
||||
memset(n->buf, 0, n->size);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
|
||||
{
|
||||
AVRMEM * m, * match;
|
||||
LNODEID ln;
|
||||
int matches;
|
||||
int l;
|
||||
|
||||
l = strlen(desc);
|
||||
matches = 0;
|
||||
match = NULL;
|
||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
if (strncmp(desc, m->desc, l) == 0) {
|
||||
match = m;
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
|
||||
if (matches == 1)
|
||||
return match;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type,
|
||||
int verbose)
|
||||
{
|
||||
int i, j;
|
||||
char * optr;
|
||||
|
||||
if (m == NULL) {
|
||||
fprintf(f,
|
||||
"%s Block Poll Page Polled\n"
|
||||
"%sMemory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
|
||||
"%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
|
||||
prefix, prefix, prefix);
|
||||
}
|
||||
else {
|
||||
if (verbose > 2) {
|
||||
fprintf(f,
|
||||
"%s Block Poll Page Polled\n"
|
||||
"%sMemory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
|
||||
"%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
|
||||
prefix, prefix, prefix);
|
||||
}
|
||||
fprintf(f,
|
||||
"%s%-11s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
|
||||
prefix, m->desc, m->mode, m->delay, m->blocksize, m->pollindex,
|
||||
m->paged ? "yes" : "no",
|
||||
m->size,
|
||||
m->page_size,
|
||||
m->num_pages,
|
||||
m->min_write_delay,
|
||||
m->max_write_delay,
|
||||
m->readback[0],
|
||||
m->readback[1]);
|
||||
if (verbose > 2) {
|
||||
fprintf(stderr,
|
||||
"%s Memory Ops:\n"
|
||||
"%s Oeration Inst Bit Bit Type Bitno Value\n"
|
||||
"%s ----------- -------- -------- ----- -----\n",
|
||||
prefix, prefix, prefix);
|
||||
for (i=0; i<AVR_OP_MAX; i++) {
|
||||
if (m->op[i]) {
|
||||
for (j=31; j>=0; j--) {
|
||||
if (j==31)
|
||||
optr = avr_op_str(i);
|
||||
else
|
||||
optr = " ";
|
||||
fprintf(f,
|
||||
"%s %-11s %8d %8s %5d %5d\n",
|
||||
prefix, optr, j,
|
||||
bittype(m->op[i]->bit[j].type),
|
||||
m->op[i]->bit[j].bitno,
|
||||
m->op[i]->bit[j].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Elementary functions dealing with AVRPART structures
|
||||
*/
|
||||
|
||||
|
||||
AVRPART * avr_new_part(void)
|
||||
{
|
||||
AVRPART * p;
|
||||
|
||||
p = (AVRPART *)malloc(sizeof(AVRPART));
|
||||
if (p == NULL) {
|
||||
fprintf(stderr, "new_part(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
p->id[0] = 0;
|
||||
p->desc[0] = 0;
|
||||
p->reset_disposition = RESET_DEDICATED;
|
||||
p->retry_pulse = PIN_AVR_SCK;
|
||||
p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK | AVRPART_ENABLEPAGEPROGRAMMING;
|
||||
p->config_file[0] = 0;
|
||||
p->lineno = 0;
|
||||
|
||||
p->mem = lcreat(NULL, 0);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
AVRPART * avr_dup_part(AVRPART * d)
|
||||
{
|
||||
AVRPART * p;
|
||||
LISTID save;
|
||||
LNODEID ln;
|
||||
|
||||
p = avr_new_part();
|
||||
save = p->mem;
|
||||
|
||||
*p = *d;
|
||||
|
||||
p->mem = save;
|
||||
|
||||
for (ln=lfirst(d->mem); ln; ln=lnext(ln)) {
|
||||
ladd(p->mem, avr_dup_mem(ldata(ln)));
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
AVRPART * locate_part(LISTID parts, char * partdesc)
|
||||
{
|
||||
LNODEID ln1;
|
||||
AVRPART * p = NULL;
|
||||
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;
|
||||
}
|
||||
|
||||
AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode)
|
||||
{
|
||||
LNODEID ln1;
|
||||
AVRPART * p = NULL;
|
||||
|
||||
for (ln1=lfirst(parts); ln1; ln1=lnext(ln1)) {
|
||||
p = ldata(ln1);
|
||||
if (p->avr910_devcode == devcode)
|
||||
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);
|
||||
fprintf(f, "%s%-4s = %-15s [%s:%d]\n",
|
||||
prefix, p->id, p->desc, p->config_file, p->lineno);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
char * reset_disp_str(int r)
|
||||
{
|
||||
switch (r) {
|
||||
case RESET_DEDICATED : return "dedicated";
|
||||
case RESET_IO : return "possible i/o";
|
||||
default : return "<invalid>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char * pin_name(int pinno)
|
||||
{
|
||||
switch (pinno) {
|
||||
case PIN_AVR_RESET : return "RESET";
|
||||
case PIN_AVR_MISO : return "MISO";
|
||||
case PIN_AVR_MOSI : return "MOSI";
|
||||
case PIN_AVR_SCK : return "SCK";
|
||||
default : return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose)
|
||||
{
|
||||
int i;
|
||||
char * buf;
|
||||
char * px;
|
||||
LNODEID ln;
|
||||
AVRMEM * m;
|
||||
|
||||
fprintf(f,
|
||||
"%sAVR Part : %s\n"
|
||||
"%sChip Erase delay : %d us\n"
|
||||
"%sPAGEL : P%02X\n"
|
||||
"%sBS2 : P%02X\n"
|
||||
"%sRESET disposition : %s\n"
|
||||
"%sRETRY pulse : %s\n"
|
||||
"%sserial program mode : %s\n"
|
||||
"%sparallel program mode : %s\n"
|
||||
"%sTimeout : %d\n"
|
||||
"%sStabDelay : %d\n"
|
||||
"%sCmdexeDelay : %d\n"
|
||||
"%sSyncLoops : %d\n"
|
||||
"%sByteDelay : %d\n"
|
||||
"%sPollIndex : %d\n"
|
||||
"%sPollValue : 0x%02x\n"
|
||||
"%sMemory Detail :\n\n",
|
||||
prefix, p->desc,
|
||||
prefix, p->chip_erase_delay,
|
||||
prefix, p->pagel,
|
||||
prefix, p->bs2,
|
||||
prefix, reset_disp_str(p->reset_disposition),
|
||||
prefix, pin_name(p->retry_pulse),
|
||||
prefix, (p->flags & AVRPART_SERIALOK) ? "yes" : "no",
|
||||
prefix, (p->flags & AVRPART_PARALLELOK) ?
|
||||
((p->flags & AVRPART_PSEUDOPARALLEL) ? "psuedo" : "yes") : "no",
|
||||
prefix, p->timeout,
|
||||
prefix, p->stabdelay,
|
||||
prefix, p->cmdexedelay,
|
||||
prefix, p->synchloops,
|
||||
prefix, p->bytedelay,
|
||||
prefix, p->pollindex,
|
||||
prefix, p->pollvalue,
|
||||
prefix);
|
||||
|
||||
px = prefix;
|
||||
i = strlen(prefix) + 5;
|
||||
buf = (char *)malloc(i);
|
||||
if (buf == NULL) {
|
||||
/* ugh, this is not important enough to bail, just ignore it */
|
||||
}
|
||||
else {
|
||||
strcpy(buf, prefix);
|
||||
strcat(buf, " ");
|
||||
px = buf;
|
||||
}
|
||||
|
||||
if (verbose <= 2) {
|
||||
avr_mem_display(px, f, NULL, 0, verbose);
|
||||
}
|
||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
avr_mem_display(px, f, m, i, verbose);
|
||||
}
|
||||
|
||||
if (buf)
|
||||
free(buf);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2003 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
|
||||
@@ -26,9 +26,6 @@
|
||||
|
||||
#include "lists.h"
|
||||
|
||||
|
||||
extern LISTID part_list;
|
||||
|
||||
/*
|
||||
* AVR serial programming instructions
|
||||
*/
|
||||
@@ -78,9 +75,6 @@ typedef struct opcode {
|
||||
#define AVRPART_SERIALOK 0x0001 /* part supports serial programming */
|
||||
#define AVRPART_PARALLELOK 0x0002 /* part supports parallel programming */
|
||||
#define AVRPART_PSEUDOPARALLEL 0x0004 /* part has pseudo parallel support */
|
||||
#define AVRPART_HAS_JTAG 0x0008 /* part has a JTAG i/f */
|
||||
#define AVRPART_ALLOWFULLPAGEBITSTREAM 0x0010 /* JTAG ICE mkII param. */
|
||||
#define AVRPART_ENABLEPAGEPROGRAMMING 0x0020 /* JTAG ICE mkII param. */
|
||||
|
||||
#define AVR_DESCLEN 64
|
||||
#define AVR_IDLEN 32
|
||||
@@ -97,22 +91,6 @@ typedef struct avrpart {
|
||||
this pin (PIN_AVR_*) */
|
||||
unsigned flags; /* see AVRPART_ masks */
|
||||
|
||||
int timeout; /* stk500 v2 xml file parameter */
|
||||
int stabdelay; /* stk500 v2 xml file parameter */
|
||||
int cmdexedelay; /* stk500 v2 xml file parameter */
|
||||
int synchloops; /* stk500 v2 xml file parameter */
|
||||
int bytedelay; /* stk500 v2 xml file parameter */
|
||||
int pollindex; /* stk500 v2 xml file parameter */
|
||||
unsigned char pollvalue; /* stk500 v2 xml file parameter */
|
||||
int predelay; /* stk500 v2 xml file parameter */
|
||||
int postdelay; /* stk500 v2 xml file parameter */
|
||||
int pollmethod; /* stk500 v2 xml file parameter */
|
||||
|
||||
unsigned char idr; /* JTAG ICE mkII XML file parameter */
|
||||
unsigned char rampz; /* JTAG ICE mkII XML file parameter */
|
||||
unsigned char spmcr; /* JTAG ICE mkII XML file parameter */
|
||||
unsigned short eecr; /* JTAC ICE mkII XML file parameter */
|
||||
|
||||
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
||||
|
||||
LISTID mem; /* avr memory definitions */
|
||||
@@ -134,38 +112,8 @@ typedef struct avrmem {
|
||||
back on, see errata
|
||||
http://www.atmel.com/atmel/acrobat/doc1280.pdf */
|
||||
unsigned char readback[2]; /* polled read-back values */
|
||||
|
||||
int mode; /* stk500 v2 xml file parameter */
|
||||
int delay; /* stk500 v2 xml file parameter */
|
||||
int blocksize; /* stk500 v2 xml file parameter */
|
||||
int readsize; /* stk500 v2 xml file parameter */
|
||||
int pollindex; /* stk500 v2 xml file parameter */
|
||||
|
||||
unsigned char * buf; /* pointer to memory buffer */
|
||||
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
||||
} AVRMEM;
|
||||
|
||||
/* Functions for OPCODE structures */
|
||||
OPCODE * avr_new_opcode(void);
|
||||
int avr_set_bits(OPCODE * op, unsigned char * cmd);
|
||||
int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr);
|
||||
int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data);
|
||||
int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data);
|
||||
|
||||
/* Functions for AVRMEM structures */
|
||||
AVRMEM * avr_new_memtype(void);
|
||||
int avr_initmem(AVRPART * p);
|
||||
AVRMEM * avr_dup_mem(AVRMEM * m);
|
||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc);
|
||||
void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type,
|
||||
int verbose);
|
||||
|
||||
/* Functions for AVRPART structures */
|
||||
AVRPART * avr_new_part(void);
|
||||
AVRPART * avr_dup_part(AVRPART * d);
|
||||
AVRPART * locate_part(LISTID parts, char * partdesc);
|
||||
AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode);
|
||||
void list_parts(FILE * f, char * prefix, LISTID parts);
|
||||
void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,280 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.org>
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "avr.h"
|
||||
#include "pindefs.h"
|
||||
#include "pgm.h"
|
||||
#include "par.h"
|
||||
#include "serbb.h"
|
||||
|
||||
#define SLOW_TOGGLE 0
|
||||
|
||||
extern char * progname;
|
||||
extern int do_cycles;
|
||||
extern int verbose;
|
||||
|
||||
static int bitbang_setpin(PROGRAMMER * pgm, int pin, int value)
|
||||
{
|
||||
if ( pgm->flag )
|
||||
serbb_setpin(pgm->fd,pin,value);
|
||||
else
|
||||
par_setpin(pgm->fd,pin,value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int bitbang_getpin(PROGRAMMER * pgm, int pin)
|
||||
{
|
||||
if ( pgm->flag )
|
||||
return serbb_getpin(pgm->fd,pin);
|
||||
else
|
||||
return par_getpin(pgm->fd,pin);
|
||||
}
|
||||
|
||||
|
||||
static int bitbang_highpulsepin(PROGRAMMER * pgm, int pin)
|
||||
{
|
||||
if ( pgm->flag )
|
||||
return serbb_highpulsepin(pgm->fd,pin);
|
||||
else
|
||||
return par_highpulsepin(pgm->fd,pin);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* transmit and receive a byte of data to/from the AVR device
|
||||
*/
|
||||
static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
|
||||
{
|
||||
int i;
|
||||
unsigned char r, b, rbyte;
|
||||
|
||||
rbyte = 0;
|
||||
for (i=7; i>=0; i--) {
|
||||
/*
|
||||
* Write and read one bit on SPI.
|
||||
* Some notes on timing: Let T be the time it takes to do
|
||||
* one bitbang_setpin()-call resp. par clrpin()-call, then
|
||||
* - SCK is high for 2T
|
||||
* - SCK is low for 2T
|
||||
* - MOSI setuptime is 1T
|
||||
* - MOSI holdtime is 3T
|
||||
* - SCK low to MISO read is 2T to 3T
|
||||
* So we are within programming specs (expect for AT90S1200),
|
||||
* if and only if T>t_CLCL (t_CLCL=clock period of target system).
|
||||
*
|
||||
* Due to the delay introduced by "IN" and "OUT"-commands,
|
||||
* T is greater than 1us (more like 2us) on x86-architectures.
|
||||
* So programming works safely down to 1MHz target clock.
|
||||
*/
|
||||
|
||||
b = (byte >> i) & 0x01;
|
||||
|
||||
/* set the data input line as desired */
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_MOSI], b);
|
||||
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_SCK], 1);
|
||||
|
||||
/*
|
||||
* read the result bit (it is either valid from a previous falling
|
||||
* edge or it is ignored in the current context)
|
||||
*/
|
||||
r = bitbang_getpin(pgm, pgm->pinno[PIN_AVR_MISO]);
|
||||
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_SCK], 0);
|
||||
|
||||
rbyte |= r << i;
|
||||
}
|
||||
|
||||
return rbyte;
|
||||
}
|
||||
|
||||
|
||||
int bitbang_rdy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_LED_RDY], !value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bitbang_err_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_LED_ERR], !value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bitbang_pgm_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_LED_PGM], !value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bitbang_vfy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_LED_VFY], !value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* transmit an AVR device command and return the results; 'cmd' and
|
||||
* 'res' must point to at least a 4 byte data buffer
|
||||
*/
|
||||
int bitbang_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
res[i] = bitbang_txrx(pgm, cmd[i]);
|
||||
}
|
||||
|
||||
if(verbose >= 2)
|
||||
{
|
||||
fprintf(stderr, "bitbang_cmd(): [ ");
|
||||
for(i = 0; i < 4; i++)
|
||||
fprintf(stderr, "%02X ", cmd[i]);
|
||||
fprintf(stderr, "] [ ");
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
fprintf(stderr, "%02X ", res[i]);
|
||||
}
|
||||
fprintf(stderr, "]\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* issue the 'chip erase' command to the AVR device
|
||||
*/
|
||||
int bitbang_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
|
||||
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
|
||||
fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
|
||||
p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pgm->pgm_led(pgm, ON);
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
|
||||
avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
usleep(p->chip_erase_delay);
|
||||
pgm->initialize(pgm, p);
|
||||
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* issue the 'program enable' command to the AVR device
|
||||
*/
|
||||
int bitbang_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
|
||||
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
|
||||
fprintf(stderr, "program enable instruction not defined for part \"%s\"\n",
|
||||
p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd);
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
|
||||
if (res[2] != cmd[1])
|
||||
return -2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize the AVR device and prepare it to accept commands
|
||||
*/
|
||||
int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
int rc;
|
||||
int tries;
|
||||
|
||||
pgm->powerup(pgm);
|
||||
usleep(20000);
|
||||
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_SCK], 0);
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0);
|
||||
usleep(20000);
|
||||
|
||||
bitbang_highpulsepin(pgm, pgm->pinno[PIN_AVR_RESET]);
|
||||
|
||||
usleep(20000); /* 20 ms XXX should be a per-chip parameter */
|
||||
|
||||
/*
|
||||
* Enable programming mode. If we are programming an AT90S1200, we
|
||||
* can only issue the command and hope it worked. If we are using
|
||||
* one of the other chips, the chip will echo 0x53 when issuing the
|
||||
* third byte of the command. In this case, try up to 32 times in
|
||||
* order to possibly get back into sync with the chip if we are out
|
||||
* of sync.
|
||||
*/
|
||||
if (strcmp(p->desc, "AT90S1200")==0) {
|
||||
pgm->program_enable(pgm, p);
|
||||
}
|
||||
else {
|
||||
tries = 0;
|
||||
do {
|
||||
rc = pgm->program_enable(pgm, p);
|
||||
if ((rc == 0)||(rc == -1))
|
||||
break;
|
||||
bitbang_highpulsepin(pgm, pgm->pinno[p->retry_pulse/*PIN_AVR_SCK*/]);
|
||||
tries++;
|
||||
} while (tries < 65);
|
||||
|
||||
/*
|
||||
* can't sync with the device, maybe it's not attached?
|
||||
*/
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: AVR device not responding\n", progname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.org>
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
#ifndef bitbang_h
|
||||
#define bitbang_h
|
||||
|
||||
int bitbang_setpin(int fd, int pin, int value);
|
||||
int bitbang_getpin(int fd, int pin);
|
||||
int bitbang_highpulsepin(int fd, int pin);
|
||||
|
||||
int bitbang_rdy_led (PROGRAMMER * pgm, int value);
|
||||
int bitbang_err_led (PROGRAMMER * pgm, int value);
|
||||
int bitbang_pgm_led (PROGRAMMER * pgm, int value);
|
||||
int bitbang_vfy_led (PROGRAMMER * pgm, int value);
|
||||
int bitbang_cmd (PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4]);
|
||||
int bitbang_chip_erase (PROGRAMMER * pgm, AVRPART * p);
|
||||
int bitbang_program_enable (PROGRAMMER * pgm, AVRPART * p);
|
||||
void bitbang_powerup (PROGRAMMER * pgm);
|
||||
void bitbang_powerdown (PROGRAMMER * pgm);
|
||||
int bitbang_initialize (PROGRAMMER * pgm, AVRPART * p);
|
||||
void bitbang_disable (PROGRAMMER * pgm);
|
||||
void bitbang_enable (PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
@@ -1,11 +1,11 @@
|
||||
#! /bin/sh
|
||||
|
||||
# autoconf-2.59 is required
|
||||
# autoconf-2.57 is required
|
||||
|
||||
: ${AUTOHEADER="autoheader${AC_VER}"}
|
||||
: ${AUTOCONF="autoconf${AC_VER}"}
|
||||
|
||||
# automake-1.9.x is required
|
||||
# automake-1.7.x is required
|
||||
|
||||
: ${ACLOCAL="aclocal${AM_VER}"}
|
||||
: ${AUTOMAKE="automake${AM_VER}"}
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
AUTOCONF_VER=`(${AUTOCONF} --version 2>/dev/null | head -n 1 | \
|
||||
cut -d ' ' -f 4) 2>/dev/null`
|
||||
if [ "$AUTOCONF_VER" != "2.59" ]
|
||||
if [ "$AUTOCONF_VER" != "2.57" ]
|
||||
then
|
||||
echo "You need to use autoconf version 2.59."
|
||||
echo "You need to use autoconf version 2.57."
|
||||
echo "You are using `${AUTOCONF} --version | head -n 1`."
|
||||
exit 1
|
||||
fi
|
||||
@@ -25,9 +25,9 @@ fi
|
||||
|
||||
AUTOMAKE_VER=`(${AUTOMAKE} --version | head -n 1 | \
|
||||
cut -d ' ' -f 4 | cut -d '.' -f -2) 2>/dev/null`
|
||||
if [ "$AUTOMAKE_VER" != "1.9" ]
|
||||
if [ "$AUTOMAKE_VER" != "1.7" ]
|
||||
then
|
||||
echo "You need to use automake version 1.9."
|
||||
echo "You need to use automake version 1.7 (preferrably 1.7.3)."
|
||||
echo "You are using `${AUTOMAKE} --version | head -n 1`."
|
||||
exit 1
|
||||
fi
|
||||
@@ -38,8 +38,6 @@ export ACLOCAL AUTOHEADER AUTOCONF AUTOMAKE
|
||||
|
||||
set -x
|
||||
|
||||
rm -rf autom4te.cache
|
||||
|
||||
${ACLOCAL}
|
||||
${AUTOHEADER}
|
||||
${AUTOCONF}
|
||||
|
||||
@@ -1,693 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2005 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
/*
|
||||
* avrdude interface for the serial programming mode of the Atmel butterfly
|
||||
* evaluation board. This board features a bootloader which uses a protocol
|
||||
* very similar, but not identical, to the one described in application note
|
||||
* avr910.
|
||||
*
|
||||
* Actually, the butterfly uses a predecessor of the avr910 protocol
|
||||
* which is described in application notes avr109 (generic AVR
|
||||
* bootloader) and avr911 (opensource programmer). This file now
|
||||
* fully handles the features present in avr109. It should probably
|
||||
* be renamed to avr109, but we rather stick with the old name inside
|
||||
* the file. We'll provide aliases for "avr109" and "avr911" in
|
||||
* avrdude.conf so users could call it by these name as well.
|
||||
*/
|
||||
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "avr.h"
|
||||
#include "pgm.h"
|
||||
#include "butterfly.h"
|
||||
#include "serial.h"
|
||||
|
||||
extern char * progname;
|
||||
extern int do_cycles;
|
||||
|
||||
static char has_auto_incr_addr;
|
||||
static unsigned buffersize = 0;
|
||||
|
||||
/* These two defines are only for debugging. Will remove them once it starts
|
||||
working. */
|
||||
|
||||
#define show_func_info() \
|
||||
fprintf(stderr, "%s: line %d: called %s()\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__)
|
||||
|
||||
#define no_show_func_info()
|
||||
|
||||
|
||||
static int butterfly_send(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return serial_send(pgm->fd, (unsigned char *)buf, len);
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_recv(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
rv = serial_recv(pgm->fd, (unsigned char *)buf, len);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: butterfly_recv(): programmer is not responding\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_drain(PROGRAMMER * pgm, int display)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return serial_drain(pgm->fd, display);
|
||||
}
|
||||
|
||||
|
||||
static void butterfly_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg)
|
||||
{
|
||||
char c;
|
||||
|
||||
butterfly_recv(pgm, &c, 1);
|
||||
if (c != '\r') {
|
||||
fprintf(stderr, "%s: error: programmer did not respond to command: %s\n",
|
||||
progname, errmsg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_rdy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_err_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_pgm_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_vfy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* issue the 'chip erase' command to the butterfly board
|
||||
*/
|
||||
static int butterfly_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
butterfly_send(pgm, "e", 1);
|
||||
butterfly_vfy_cmd_sent(pgm, "chip erase");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void butterfly_enter_prog_mode(PROGRAMMER * pgm)
|
||||
{
|
||||
butterfly_send(pgm, "P", 1);
|
||||
butterfly_vfy_cmd_sent(pgm, "enter prog mode");
|
||||
}
|
||||
|
||||
|
||||
static void butterfly_leave_prog_mode(PROGRAMMER * pgm)
|
||||
{
|
||||
butterfly_send(pgm, "L", 1);
|
||||
butterfly_vfy_cmd_sent(pgm, "leave prog mode");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* issue the 'program enable' command to the AVR device
|
||||
*/
|
||||
static int butterfly_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* apply power to the AVR processor
|
||||
*/
|
||||
static void butterfly_powerup(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* remove power from the AVR processor
|
||||
*/
|
||||
static void butterfly_powerdown(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* Do nothing. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* initialize the AVR device and prepare it to accept commands
|
||||
*/
|
||||
static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
char id[8];
|
||||
char sw[2];
|
||||
char hw[2];
|
||||
char buf[10];
|
||||
char type;
|
||||
char c;
|
||||
int dev_supported = 0;
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
/*
|
||||
* Send some ESC to activate butterfly bootloader. This is not needed
|
||||
* for plain avr109 bootloaders but does not harm there either.
|
||||
*/
|
||||
fprintf(stderr, "Connecting to programmer: ");
|
||||
do {
|
||||
putc('.', stderr);
|
||||
butterfly_send(pgm, "\033", 1);
|
||||
butterfly_drain(pgm, 0);
|
||||
butterfly_send(pgm, "S", 1);
|
||||
butterfly_recv(pgm, &c, 1);
|
||||
if (c != '?') {
|
||||
putc('\n', stderr);
|
||||
/*
|
||||
* Got a useful response, continue getting the programmer
|
||||
* identifier. Programmer returns exactly 7 chars _without_
|
||||
* the null.
|
||||
*/
|
||||
id[0] = c;
|
||||
butterfly_recv(pgm, &id[1], sizeof(id)-2);
|
||||
id[sizeof(id)-1] = '\0';
|
||||
}
|
||||
} while (c == '?');
|
||||
|
||||
/* Get the HW and SW versions to see if the programmer is present. */
|
||||
|
||||
butterfly_send(pgm, "V", 1);
|
||||
butterfly_recv(pgm, sw, sizeof(sw));
|
||||
|
||||
butterfly_send(pgm, "v", 1);
|
||||
butterfly_recv(pgm, hw, 1); /* first, read only _one_ byte */
|
||||
if (hw[0]!='?') {
|
||||
butterfly_recv(pgm, &hw[1], 1);/* now, read second byte */
|
||||
};
|
||||
|
||||
/* Get the programmer type (serial or parallel). Expect serial. */
|
||||
|
||||
butterfly_send(pgm, "p", 1);
|
||||
butterfly_recv(pgm, &type, 1);
|
||||
|
||||
fprintf(stderr, "Found programmer: Id = \"%s\"; type = %c\n", id, type);
|
||||
fprintf(stderr, " Software Version = %c.%c; ", sw[0], sw[1]);
|
||||
if (hw[0]=='?') {
|
||||
fprintf(stderr, "No Hardware Version given.\n");
|
||||
} else {
|
||||
fprintf(stderr, "Hardware Version = %c.%c\n", hw[0], hw[1]);
|
||||
};
|
||||
|
||||
/* See if programmer supports autoincrement of address. */
|
||||
|
||||
butterfly_send(pgm, "a", 1);
|
||||
butterfly_recv(pgm, &has_auto_incr_addr, 1);
|
||||
if (has_auto_incr_addr == 'Y')
|
||||
fprintf(stderr, "Programmer supports auto addr increment.\n");
|
||||
|
||||
/* Check support for buffered memory access, abort if not available */
|
||||
|
||||
butterfly_send(pgm, "b", 1);
|
||||
butterfly_recv(pgm, &c, 1);
|
||||
if (c != 'Y') {
|
||||
fprintf(stderr,
|
||||
"%s: error: buffered memory access not supported. Maybe it isn't\n"\
|
||||
"a butterfly/AVR109 but a AVR910 device?\n", progname);
|
||||
exit(1);
|
||||
};
|
||||
butterfly_recv(pgm, &c, 1);
|
||||
buffersize = c<<8;
|
||||
butterfly_recv(pgm, &c, 1);
|
||||
buffersize += c;
|
||||
fprintf(stderr,
|
||||
"Programmer supports buffered memory access with buffersize=%i bytes.\n",
|
||||
buffersize);
|
||||
|
||||
/* Get list of devices that the programmer supports. */
|
||||
|
||||
butterfly_send(pgm, "t", 1);
|
||||
fprintf(stderr, "\nProgrammer supports the following devices:\n");
|
||||
while (1) {
|
||||
butterfly_recv(pgm, &c, 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
fprintf(stderr, " Device code: 0x%02x\n", (unsigned int)(unsigned char)c);
|
||||
|
||||
/* FIXME: Need to lookup devcode and report the device. */
|
||||
|
||||
if (p->avr910_devcode == (int)(unsigned char)c)
|
||||
dev_supported = 1;
|
||||
};
|
||||
fprintf(stderr,"\n");
|
||||
|
||||
if (!dev_supported) {
|
||||
/* FIXME: if nothing matched, we should rather compare the device
|
||||
signatures. */
|
||||
fprintf(stderr,
|
||||
"%s: error: selected device is not supported by programmer: %s\n",
|
||||
progname, p->id);
|
||||
}
|
||||
|
||||
/* Tell the programmer which part we selected. */
|
||||
|
||||
buf[0] = 'T';
|
||||
buf[1] = p->avr910_devcode;
|
||||
|
||||
butterfly_send(pgm, buf, 2);
|
||||
butterfly_vfy_cmd_sent(pgm, "select device");
|
||||
|
||||
if (dev_supported)
|
||||
butterfly_enter_prog_mode(pgm);
|
||||
|
||||
return dev_supported? 0: -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void butterfly_disable(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
butterfly_leave_prog_mode(pgm);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void butterfly_enable(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
strcpy(pgm->port, port);
|
||||
/*
|
||||
* If baudrate was not specified use 19200 Baud
|
||||
*/
|
||||
if(pgm->baudrate == 0) {
|
||||
pgm->baudrate = 19200;
|
||||
}
|
||||
pgm->fd = serial_open(port, pgm->baudrate);
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
butterfly_drain (pgm, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void butterfly_close(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* "exit programmer" added by Martin Thomas 2/2004 */
|
||||
butterfly_send(pgm, "E", 1);
|
||||
|
||||
serial_close(pgm->fd);
|
||||
pgm->fd = -1;
|
||||
}
|
||||
|
||||
|
||||
static void butterfly_display(PROGRAMMER * pgm, char * p)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void butterfly_set_addr(PROGRAMMER * pgm, unsigned long addr)
|
||||
{
|
||||
char cmd[3];
|
||||
|
||||
cmd[0] = 'A';
|
||||
cmd[1] = (addr >> 8) & 0xff;
|
||||
cmd[2] = addr & 0xff;
|
||||
|
||||
butterfly_send(pgm, cmd, sizeof(cmd));
|
||||
butterfly_vfy_cmd_sent(pgm, "set addr");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int butterfly_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned long addr, unsigned char value)
|
||||
{
|
||||
char cmd[6];
|
||||
int size;
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
if ((strcmp(m->desc, "flash") == 0) || (strcmp(m->desc, "eeprom") == 0))
|
||||
{
|
||||
cmd[0] = 'B';
|
||||
cmd[1] = 0;
|
||||
if ((cmd[3] = toupper(m->desc[0])) == 'E') { /* write to eeprom */
|
||||
cmd[2] = 1;
|
||||
cmd[4] = value;
|
||||
size = 5;
|
||||
} else { /* write to flash */
|
||||
/* @@@ not yet implemented */
|
||||
cmd[2] = 2;
|
||||
size = 6;
|
||||
return -1;
|
||||
}
|
||||
butterfly_set_addr(pgm, addr);
|
||||
}
|
||||
else if (strcmp(m->desc, "lock") == 0)
|
||||
{
|
||||
cmd[0] = 'l';
|
||||
cmd[1] = value;
|
||||
size = 2;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
butterfly_send(pgm, cmd, size);
|
||||
butterfly_vfy_cmd_sent(pgm, "write byte");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned long addr, unsigned char * value)
|
||||
{
|
||||
static int cached = 0;
|
||||
static unsigned char cvalue;
|
||||
static unsigned long caddr;
|
||||
|
||||
if (cached && ((caddr + 1) == addr)) {
|
||||
*value = cvalue;
|
||||
cached = 0;
|
||||
}
|
||||
else {
|
||||
char buf[2];
|
||||
|
||||
butterfly_set_addr(pgm, addr >> 1);
|
||||
|
||||
butterfly_send(pgm, "g\000\002F", 4);
|
||||
|
||||
/* Read back the program mem word (MSB first) */
|
||||
butterfly_recv(pgm, buf, sizeof(buf));
|
||||
|
||||
if ((addr & 0x01) == 0) {
|
||||
*value = buf[1];
|
||||
cached = 1;
|
||||
cvalue = buf[0];
|
||||
caddr = addr;
|
||||
}
|
||||
else {
|
||||
*value = buf[0];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned long addr, unsigned char * value)
|
||||
{
|
||||
butterfly_set_addr(pgm, addr);
|
||||
butterfly_send(pgm, "g\000\001E", 4);
|
||||
butterfly_recv(pgm, (char *)value, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int butterfly_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned long addr, unsigned char * value)
|
||||
{
|
||||
char cmd;
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
return butterfly_read_byte_flash(pgm, p, m, addr, value);
|
||||
}
|
||||
|
||||
if (strcmp(m->desc, "eeprom") == 0) {
|
||||
return butterfly_read_byte_eeprom(pgm, p, m, addr, value);
|
||||
}
|
||||
|
||||
if (strcmp(m->desc, "lfuse") == 0) {
|
||||
cmd = 'F';
|
||||
}
|
||||
else if (strcmp(m->desc, "hfuse") == 0) {
|
||||
cmd = 'N';
|
||||
}
|
||||
else if (strcmp(m->desc, "efuse") == 0) {
|
||||
cmd = 'Q';
|
||||
}
|
||||
else if (strcmp(m->desc, "lock") == 0) {
|
||||
cmd = 'r';
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
butterfly_send(pgm, &cmd, 1);
|
||||
butterfly_recv(pgm, (char *)value, 1);
|
||||
|
||||
return *value == '?'? -1: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int butterfly_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
unsigned int addr = 0;
|
||||
unsigned int max_addr = n_bytes;
|
||||
char *cmd;
|
||||
unsigned int blocksize = buffersize;
|
||||
|
||||
if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom"))
|
||||
return -2;
|
||||
|
||||
if (m->desc[0] == 'e')
|
||||
blocksize = 1; /* Write to eeprom single bytes only */
|
||||
|
||||
butterfly_set_addr(pgm, addr);
|
||||
|
||||
#if 0
|
||||
usleep(1000000);
|
||||
butterfly_send(pgm, "y", 1);
|
||||
butterfly_vfy_cmd_sent(pgm, "clear LED");
|
||||
#endif
|
||||
|
||||
cmd = malloc(4+blocksize);
|
||||
if (!cmd) return -1;
|
||||
cmd[0] = 'B';
|
||||
cmd[3] = toupper(m->desc[0]);
|
||||
|
||||
while (addr < max_addr) {
|
||||
if ((max_addr - addr) < blocksize) {
|
||||
blocksize = max_addr - addr;
|
||||
};
|
||||
memcpy(&cmd[4], &m->buf[addr], blocksize);
|
||||
cmd[1] = (blocksize >> 8) & 0xff;
|
||||
cmd[2] = blocksize & 0xff;
|
||||
|
||||
butterfly_send(pgm, cmd, 4+blocksize);
|
||||
butterfly_vfy_cmd_sent(pgm, "write block");
|
||||
|
||||
addr += blocksize;
|
||||
|
||||
report_progress (addr, max_addr, NULL);
|
||||
} /* while */
|
||||
free(cmd);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int butterfly_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
unsigned int addr = 0;
|
||||
unsigned int max_addr = n_bytes;
|
||||
int rd_size = 1;
|
||||
|
||||
/* check parameter syntax: only "flash" or "eeprom" is allowed */
|
||||
if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom"))
|
||||
return -2;
|
||||
|
||||
{ /* use buffered mode */
|
||||
char cmd[4];
|
||||
int blocksize = buffersize;
|
||||
|
||||
cmd[0] = 'g';
|
||||
cmd[3] = toupper(m->desc[0]);
|
||||
|
||||
butterfly_set_addr(pgm, addr);
|
||||
while (addr < max_addr) {
|
||||
if ((max_addr - addr) < blocksize) {
|
||||
blocksize = max_addr - addr;
|
||||
};
|
||||
cmd[1] = (blocksize >> 8) & 0xff;
|
||||
cmd[2] = blocksize & 0xff;
|
||||
|
||||
butterfly_send(pgm, cmd, 4);
|
||||
butterfly_recv(pgm, (char *)&m->buf[addr], blocksize);
|
||||
|
||||
addr += blocksize;
|
||||
|
||||
report_progress (addr, max_addr, NULL);
|
||||
} /* while */
|
||||
}
|
||||
|
||||
return addr * rd_size;
|
||||
}
|
||||
|
||||
|
||||
/* Signature byte reads are always 3 bytes. */
|
||||
static int butterfly_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||
{
|
||||
unsigned char tmp;
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
if (m->size < 3) {
|
||||
fprintf(stderr, "%s: memsize too small for sig byte read", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
butterfly_send(pgm, "s", 1);
|
||||
butterfly_recv(pgm, (char *)m->buf, 3);
|
||||
/* Returned signature has wrong order. */
|
||||
tmp = m->buf[2];
|
||||
m->buf[2] = m->buf[0];
|
||||
m->buf[0] = tmp;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
void butterfly_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
strcpy(pgm->type, "avr910");
|
||||
|
||||
/*
|
||||
* mandatory functions
|
||||
*/
|
||||
pgm->rdy_led = butterfly_rdy_led;
|
||||
pgm->err_led = butterfly_err_led;
|
||||
pgm->pgm_led = butterfly_pgm_led;
|
||||
pgm->vfy_led = butterfly_vfy_led;
|
||||
pgm->initialize = butterfly_initialize;
|
||||
pgm->display = butterfly_display;
|
||||
pgm->enable = butterfly_enable;
|
||||
pgm->disable = butterfly_disable;
|
||||
pgm->powerup = butterfly_powerup;
|
||||
pgm->powerdown = butterfly_powerdown;
|
||||
pgm->program_enable = butterfly_program_enable;
|
||||
pgm->chip_erase = butterfly_chip_erase;
|
||||
/* pgm->cmd not supported, use default error message */
|
||||
pgm->open = butterfly_open;
|
||||
pgm->close = butterfly_close;
|
||||
|
||||
/*
|
||||
* optional functions
|
||||
*/
|
||||
|
||||
pgm->write_byte = butterfly_write_byte;
|
||||
pgm->read_byte = butterfly_read_byte;
|
||||
|
||||
pgm->paged_write = butterfly_paged_write;
|
||||
pgm->paged_load = butterfly_paged_load;
|
||||
|
||||
pgm->read_sig_bytes = butterfly_read_sig_bytes;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
#ifndef __butterfly_h__
|
||||
#define __butterfly_h__
|
||||
|
||||
void butterfly_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif /* __butterfly_h__ */
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -47,6 +47,8 @@ extern FILE * yyin;
|
||||
extern PROGRAMMER * current_prog;
|
||||
extern AVRPART * current_part;
|
||||
extern AVRMEM * current_mem;
|
||||
extern LISTID programmers;
|
||||
extern LISTID part_list;
|
||||
extern int lineno;
|
||||
extern char * infile;
|
||||
extern LISTID string_list;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -29,28 +29,19 @@
|
||||
#include "config.h"
|
||||
#include "lists.h"
|
||||
#include "par.h"
|
||||
#include "serbb.h"
|
||||
#include "pindefs.h"
|
||||
#include "ppi.h"
|
||||
#include "pgm.h"
|
||||
#include "stk500.h"
|
||||
#include "stk500v2.h"
|
||||
#include "avr910.h"
|
||||
#include "butterfly.h"
|
||||
#include "avr.h"
|
||||
#include "jtagmkII.h"
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
#define strtok_r( _s, _sep, _lasts ) \
|
||||
( *(_lasts) = strtok( (_s), (_sep) ) )
|
||||
#endif
|
||||
|
||||
extern char * progname;
|
||||
|
||||
int yylex(void);
|
||||
int yyerror(char * errmsg);
|
||||
|
||||
static int assign_pin(int pinno, TOKEN * v, int invert);
|
||||
static int assign_pin(int pinno, TOKEN * v);
|
||||
static int which_opcode(TOKEN * opcode);
|
||||
static int parse_cmdbits(OPCODE * op);
|
||||
|
||||
@@ -73,7 +64,6 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_PAGE_SIZE
|
||||
%token K_PAGED
|
||||
|
||||
%token K_BAUDRATE
|
||||
%token K_BS2
|
||||
%token K_BUFF
|
||||
%token K_CHIP_ERASE_DELAY
|
||||
@@ -90,7 +80,6 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_FLASH
|
||||
%token K_ID
|
||||
%token K_IO
|
||||
%token K_JTAG_MKII
|
||||
%token K_LOADPAGE
|
||||
%token K_MAX_WRITE_DELAY
|
||||
%token K_MIN_WRITE_DELAY
|
||||
@@ -111,14 +100,11 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_READMEM
|
||||
%token K_RESET
|
||||
%token K_RETRY_PULSE
|
||||
%token K_SERBB
|
||||
%token K_SERIAL
|
||||
%token K_SCK
|
||||
%token K_SIZE
|
||||
%token K_STK500
|
||||
%token K_STK500V2
|
||||
%token K_AVR910
|
||||
%token K_BUTTERFLY
|
||||
%token K_TYPE
|
||||
%token K_VCC
|
||||
%token K_VFYLED
|
||||
@@ -127,41 +113,9 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_NO
|
||||
%token K_YES
|
||||
|
||||
/* stk500 v2 xml file parameters */
|
||||
%token K_TIMEOUT
|
||||
%token K_STABDELAY
|
||||
%token K_CMDEXEDELAY
|
||||
%token K_SYNCHLOOPS
|
||||
%token K_BYTEDELAY
|
||||
%token K_POLLVALUE
|
||||
%token K_POLLINDEX
|
||||
%token K_PREDELAY
|
||||
%token K_POSTDELAY
|
||||
%token K_POLLMETHOD
|
||||
%token K_MODE
|
||||
%token K_DELAY
|
||||
%token K_BLOCKSIZE
|
||||
%token K_READSIZE
|
||||
|
||||
/* JTAG ICE mkII specific parameters */
|
||||
%token K_ALLOWFULLPAGEBITSTREAM /*
|
||||
* Internal parameter for the JTAG
|
||||
* ICE; describes the internal JTAG
|
||||
* streaming behaviour inside the MCU.
|
||||
* 1 for all older chips, 0 for newer
|
||||
* MCUs.
|
||||
*/
|
||||
%token K_ENABLEPAGEPROGRAMMING /* ? yes for mega256*, mega406 */
|
||||
%token K_HAS_JTAG /* MCU has JTAG i/f. */
|
||||
%token K_IDR /* address of OCD register in IO space */
|
||||
%token K_RAMPZ /* address of RAMPZ reg. in IO space */
|
||||
%token K_SPMCR /* address of SPMC[S]R in memory space */
|
||||
%token K_EECR /* address of EECR in memory space */
|
||||
|
||||
%token TKN_COMMA
|
||||
%token TKN_EQUAL
|
||||
%token TKN_SEMI
|
||||
%token TKN_TILDE
|
||||
%token TKN_NUMBER
|
||||
%token TKN_STRING
|
||||
%token TKN_ID
|
||||
@@ -328,42 +282,18 @@ prog_parm :
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_SERBB {
|
||||
{
|
||||
serbb_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_STK500 {
|
||||
{
|
||||
stk500_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_STK500V2 {
|
||||
{
|
||||
stk500v2_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_AVR910 {
|
||||
{
|
||||
avr910_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_BUTTERFLY {
|
||||
{
|
||||
butterfly_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_JTAG_MKII {
|
||||
{
|
||||
jtagmkII_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_DESC TKN_EQUAL TKN_STRING {
|
||||
strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN);
|
||||
current_prog->desc[PGM_DESCLEN-1] = 0;
|
||||
@@ -420,33 +350,16 @@ prog_parm :
|
||||
}
|
||||
} |
|
||||
|
||||
K_BAUDRATE TKN_EQUAL TKN_NUMBER {
|
||||
{
|
||||
current_prog->baudrate = $3->value.number;
|
||||
}
|
||||
} |
|
||||
|
||||
K_RESET TKN_EQUAL TKN_NUMBER { free_token($1);
|
||||
assign_pin(PIN_AVR_RESET, $3, 0); } |
|
||||
assign_pin(PIN_AVR_RESET, $3); } |
|
||||
K_SCK TKN_EQUAL TKN_NUMBER { free_token($1);
|
||||
assign_pin(PIN_AVR_SCK, $3, 0); } |
|
||||
K_MOSI TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MOSI, $3, 0); } |
|
||||
K_MISO TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MISO, $3, 0); } |
|
||||
K_ERRLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_ERR, $3, 0); } |
|
||||
K_RDYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_RDY, $3, 0); } |
|
||||
K_PGMLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_PGM, $3, 0); } |
|
||||
K_VFYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_VFY, $3, 0); } |
|
||||
|
||||
K_RESET TKN_EQUAL TKN_TILDE TKN_NUMBER { free_token($1);
|
||||
assign_pin(PIN_AVR_RESET, $4, 1); } |
|
||||
K_SCK TKN_EQUAL TKN_TILDE TKN_NUMBER { free_token($1);
|
||||
assign_pin(PIN_AVR_SCK, $4, 1); } |
|
||||
K_MOSI TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_AVR_MOSI, $4, 1); } |
|
||||
K_MISO TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_AVR_MISO, $4, 1); } |
|
||||
K_ERRLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_ERR, $4, 1); } |
|
||||
K_RDYLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_RDY, $4, 1); } |
|
||||
K_PGMLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_PGM, $4, 1); } |
|
||||
K_VFYLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_VFY, $4, 1); }
|
||||
assign_pin(PIN_AVR_SCK, $3); } |
|
||||
K_MOSI TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MOSI, $3); } |
|
||||
K_MISO TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MISO, $3); } |
|
||||
K_ERRLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_ERR, $3); } |
|
||||
K_RDYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_RDY, $3); } |
|
||||
K_PGMLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_PGM, $3); } |
|
||||
K_VFYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_VFY, $3); }
|
||||
;
|
||||
|
||||
|
||||
@@ -550,120 +463,6 @@ part_parm :
|
||||
free_tokens(2, $1, $3);
|
||||
} |
|
||||
|
||||
K_TIMEOUT TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->timeout = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_STABDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->stabdelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_CMDEXEDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->cmdexedelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_SYNCHLOOPS TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->synchloops = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_BYTEDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->bytedelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_POLLVALUE TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->pollvalue = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_POLLINDEX TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->pollindex = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_PREDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->predelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_POSTDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->postdelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_POLLMETHOD TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->pollmethod = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HAS_JTAG TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
current_part->flags |= AVRPART_HAS_JTAG;
|
||||
else if ($3->primary == K_NO)
|
||||
current_part->flags &= ~AVRPART_HAS_JTAG;
|
||||
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_ALLOWFULLPAGEBITSTREAM TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
current_part->flags |= AVRPART_ALLOWFULLPAGEBITSTREAM;
|
||||
else if ($3->primary == K_NO)
|
||||
current_part->flags &= ~AVRPART_ALLOWFULLPAGEBITSTREAM;
|
||||
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_ENABLEPAGEPROGRAMMING TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
current_part->flags |= AVRPART_ENABLEPAGEPROGRAMMING;
|
||||
else if ($3->primary == K_NO)
|
||||
current_part->flags &= ~AVRPART_ENABLEPAGEPROGRAMMING;
|
||||
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_IDR TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->idr = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_RAMPZ TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->rampz = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_SPMCR TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->spmcr = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_EECR TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->eecr = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_SERIAL TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
@@ -811,38 +610,6 @@ mem_spec :
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
|
||||
K_MODE TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_mem->mode = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_DELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_mem->delay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_BLOCKSIZE TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_mem->blocksize = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_READSIZE TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_mem->readsize = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_POLLINDEX TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_mem->pollindex = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
|
||||
opcode TKN_EQUAL string_list {
|
||||
{
|
||||
int opnum;
|
||||
@@ -874,7 +641,7 @@ static char * vtypestr(int type)
|
||||
#endif
|
||||
|
||||
|
||||
static int assign_pin(int pinno, TOKEN * v, int invert)
|
||||
static int assign_pin(int pinno, TOKEN * v)
|
||||
{
|
||||
int value;
|
||||
|
||||
@@ -887,8 +654,6 @@ static int assign_pin(int pinno, TOKEN * v, int invert)
|
||||
progname, lineno, infile);
|
||||
exit(1);
|
||||
}
|
||||
if (invert)
|
||||
value |= PIN_INVERSE;
|
||||
|
||||
current_prog->pinno[pinno] = value;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# avrdude - A Downloader/Uploader for AVR device programmers
|
||||
# Copyright (C) 2003, 2004 Theodore A. Roth <troth@openavr.org>
|
||||
# Copyright (C) 2003 Theodore A. Roth <troth@openavr.org>
|
||||
#
|
||||
# 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
|
||||
@@ -24,7 +24,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT(avrdude, 5.0, avrdude-dev@nongnu.org)
|
||||
AC_INIT(avrdude, 4.2.0, avrdude-dev@nongnu.org)
|
||||
|
||||
AC_CANONICAL_BUILD
|
||||
AC_CANONICAL_HOST
|
||||
@@ -44,9 +44,6 @@ AM_PROG_LEX
|
||||
AC_CHECK_LIB([termcap], [tputs])
|
||||
AC_CHECK_LIB([ncurses], [tputs])
|
||||
AC_CHECK_LIB([readline], [readline])
|
||||
# usb_get_string_simple is only available in recent enough
|
||||
# versions of libusb, so use that as a decision base.
|
||||
AC_CHECK_LIB([usb], [usb_get_string_simple])
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
@@ -81,32 +78,7 @@ else
|
||||
DOC_INST_DIR='$(DESTDIR)$(datadir)/doc/avrdude'
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
[doc],
|
||||
AC_HELP_STRING(
|
||||
[--enable-doc],
|
||||
[Enable building documents(default)]),
|
||||
[case "${enableval}" in
|
||||
yes) enabled_doc=yes ;;
|
||||
no) enabled_doc=no ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for disable-doc option) ;;
|
||||
esac],
|
||||
[enabled_doc=no])
|
||||
|
||||
if test "$enabled_doc" = "yes"; then
|
||||
|
||||
SUBDIRS_AC='doc @WINDOWS_DIRS@'
|
||||
DIST_SUBDIRS_AC='doc windows'
|
||||
else
|
||||
|
||||
SUBDIRS_AC='@WINDOWS_DIRS@'
|
||||
DIST_SUBDIRS_AC='windows'
|
||||
fi
|
||||
|
||||
AC_SUBST(DOC_INST_DIR, $DOC_INST_DIR)
|
||||
AC_SUBST(SUBDIRS_AC, $SUBDIRS_AC)
|
||||
AC_SUBST(DIST_SUBDIRS_AC, $DIST_SUBDIRS_AC)
|
||||
|
||||
|
||||
# Find the parallel serial device files based on target system
|
||||
# If a system doesn't have a PC style parallel, mark it as unknown.
|
||||
@@ -149,8 +121,6 @@ AC_SUBST(DEFAULT_SER_PORT, $DEFAULT_SER_PORT)
|
||||
case $target in
|
||||
*-*-mingw32* | *-*-cygwin* | *-*-windows*)
|
||||
WINDOWS_DIRS="windows"
|
||||
CFLAGS="-mno-cygwin -DWIN32NATIVE"
|
||||
LDFLAGS="-static"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(WINDOWS_DIRS,$WINDOWS_DIRS)
|
||||
@@ -161,16 +131,11 @@ if test "$GCC" = yes; then
|
||||
fi
|
||||
AC_SUBST(ENABLE_WARNINGS,$ENABLE_WARNINGS)
|
||||
|
||||
if test "$enabled_doc" = "yes"; then
|
||||
AC_CONFIG_FILES([doc/Makefile])
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
windows/Makefile
|
||||
avrdude.spec
|
||||
avrdude.conf
|
||||
Makefile
|
||||
doc/Makefile
|
||||
windows/Makefile
|
||||
avrdude.spec
|
||||
avrdude.conf
|
||||
Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Eric B. Weddington <eric@ecentral.com>
|
||||
* Copyright (C) 2003 Eric B. Weddington <eric@ecentral.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
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
#if defined(__CYGWIN__)
|
||||
|
||||
#include <limits.h>
|
||||
#include <windows.h>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Eric B. Weddington <eric@ecentral.com>
|
||||
* Copyright (C) 2003 Eric B. Weddington <eric@ecentral.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
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
#if defined(__CYGWIN__)
|
||||
#ifndef __confwin_h__
|
||||
#define __confwin_h__
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Derived from CRC algorithm for JTAG ICE mkII, published in Atmel
|
||||
* Appnote AVR067. Converted from C++ to C.
|
||||
*/
|
||||
#include "crc16.h"
|
||||
|
||||
/* CRC16 Definitions */
|
||||
const unsigned short crc_table[256] = {
|
||||
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
|
||||
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
|
||||
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
|
||||
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
|
||||
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
|
||||
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
|
||||
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
||||
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
|
||||
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
|
||||
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
|
||||
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
|
||||
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
|
||||
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
|
||||
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
||||
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
|
||||
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
|
||||
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
|
||||
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
|
||||
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
|
||||
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
|
||||
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
||||
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
|
||||
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
|
||||
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
|
||||
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
|
||||
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
|
||||
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
|
||||
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
||||
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
|
||||
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
|
||||
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
|
||||
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
|
||||
};
|
||||
|
||||
/* CRC calculation macros */
|
||||
#define CRC_INIT 0xFFFF
|
||||
#define CRC(crcval,newchar) crcval = (crcval >> 8) ^ \
|
||||
crc_table[(crcval ^ newchar) & 0x00ff]
|
||||
|
||||
unsigned short
|
||||
crcsum(const unsigned char* message, unsigned long length,
|
||||
unsigned short crc)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
CRC(crc, message[i]);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
int
|
||||
crcverify(const unsigned char* message, unsigned long length)
|
||||
{
|
||||
/*
|
||||
* Returns true if the last two bytes in a message is the crc of the
|
||||
* preceding bytes.
|
||||
*/
|
||||
unsigned short expected;
|
||||
|
||||
expected = crcsum(message, length - 2, CRC_INIT);
|
||||
return (expected & 0xff) == message[length - 2] &&
|
||||
((expected >> 8) & 0xff) == message[length - 1];
|
||||
}
|
||||
|
||||
void
|
||||
crcappend(unsigned char* message, unsigned long length)
|
||||
{
|
||||
unsigned long crc;
|
||||
|
||||
crc = crcsum(message, length, CRC_INIT);
|
||||
message[length] = (unsigned char)(crc & 0xff);
|
||||
message[length+1] = (unsigned char)((crc >> 8) & 0xff);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef CRC16_H
|
||||
#define CRC16_H
|
||||
/*
|
||||
* Derived from CRC algorithm for JTAG ICE mkII, published in Atmel
|
||||
* Appnote AVR067. Converted from C++ to C.
|
||||
*/
|
||||
|
||||
extern unsigned short crcsum(const unsigned char* message,
|
||||
unsigned long length,
|
||||
unsigned short crc);
|
||||
/*
|
||||
* Verify that the last two bytes is a (LSB first) valid CRC of the
|
||||
* message.
|
||||
*/
|
||||
extern int crcverify(const unsigned char* message,
|
||||
unsigned long length);
|
||||
/*
|
||||
* Append a two byte CRC (LSB first) to message. length is size of
|
||||
* message excluding crc. Space for the CRC bytes must be allocated
|
||||
* in advance!
|
||||
*/
|
||||
extern void crcappend(unsigned char* message,
|
||||
unsigned long length);
|
||||
|
||||
#endif
|
||||
@@ -29,16 +29,10 @@ info_TEXINFOS = avrdude.texi
|
||||
|
||||
all-local: info html ps pdf
|
||||
|
||||
html: avrdude-html/avrdude.html
|
||||
|
||||
avrdude-html/avrdude.html: $(srcdir)/$(info_TEXINFOS)
|
||||
html:
|
||||
mkdir -p avrdude-html
|
||||
texi2html -split_node $(srcdir)/$(info_TEXINFOS)
|
||||
if [ -e ./avrdude.html -o -e ./avrdude_1.html ]; then \
|
||||
mkdir -p avrdude-html ; \
|
||||
mv -f *.html avrdude-html ; \
|
||||
else \
|
||||
mv -f avrdude avrdude-html; \
|
||||
fi;
|
||||
mv *.html avrdude-html
|
||||
|
||||
clean-local:
|
||||
rm -rf avrdude-html *.info
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
|
||||
General:
|
||||
|
||||
- Man page needs updated for avr910 info.
|
||||
|
||||
- avr910 needs a little bit of work to support setting fuse byte (note that it
|
||||
can only deal with a _single_ fuse byte.
|
||||
|
||||
- Website needs to link to docs:
|
||||
http://savannah.nongnu.org/download/avrdude/doc/avrdude-html/
|
||||
|
||||
- Add "skip empty pages" optimization on avr910 paged write. The stk500 has
|
||||
this optimization already.
|
||||
- Add avr910 device codes for more devices. Some where posted here:
|
||||
http://www.avrfreaks.com/phorum/read.php?f=3&i=40925&t=40717#40925
|
||||
but uisp seems to have a more comprehensive list.
|
||||
|
||||
- Fix "overfull \hbox" issues in building documentation.
|
||||
Windows:
|
||||
|
||||
- FIXME: term.c: terminal_get_input(): strip newlines in non-readline input
|
||||
code.
|
||||
|
||||
- FIXME: avr910.c: avr910_cmd(): Insert version check here.
|
||||
|
||||
- FIXME: ser_posix.c: serial_close(): Should really restore the terminal to
|
||||
original state here.
|
||||
|
||||
- FIXME: main.c, par.c: exitspecs don't work if RESET-pin is controlled over
|
||||
PPICTRL.
|
||||
|
||||
- transfer ppi-speedtuning to the windows version (CAVEAT: This will make
|
||||
programming too fast for chips with 500kHz clock)
|
||||
|
||||
- make SCK-period configurable for PPI-programmers
|
||||
- Use Windows API for stk500 serial port communications on Windows port.
|
||||
This might remove dependency on Cygwin.
|
||||
|
||||
- Add ability to find all parallel port names available and base addresses
|
||||
of available ports.
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
@setfilename avrdude.info
|
||||
@settitle AVRDUDE
|
||||
@finalout
|
||||
|
||||
@include version.texi
|
||||
|
||||
@@ -28,7 +27,7 @@ This file documents the avrdude program.
|
||||
|
||||
For avrdude version @value{VERSION}, @value{UPDATED}.
|
||||
|
||||
Copyright @copyright{} 2003,2005 Brian Dean
|
||||
Copyright @copyright{} 2003 Brian Dean
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
@@ -63,7 +62,7 @@ by the Free Software Foundation.
|
||||
|
||||
@vfill
|
||||
|
||||
Copyright @copyright{} 2003,2005 Brian S. Dean
|
||||
Copyright @copyright{} 2003 Brian S. Dean
|
||||
@sp 2
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
@@ -98,11 +97,10 @@ For avrdude version @value{VERSION}, @value{UPDATED}.
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
* Command Line Options::
|
||||
* Terminal Mode Operation::
|
||||
* Command Line Options::
|
||||
* Terminal Mode Operation::
|
||||
* Configuration File::
|
||||
* Platform Dependent Information::
|
||||
* Troubleshooting::
|
||||
* Platform Dependent Information::
|
||||
@end menu
|
||||
|
||||
@c
|
||||
@@ -129,46 +127,24 @@ from the contents of a file, while interactive mode is useful for
|
||||
exploring memory contents, modifing individual bytes of eeprom,
|
||||
programming fuse/lock bits, etc.
|
||||
|
||||
AVRDUDE supports six basic programmer types: Atmel's STK500,
|
||||
Atmel's JTAG ICE mkII, appnote
|
||||
avr910, appnote avr109 (including the AVR Butterfly),
|
||||
serial bit-bang adapters,
|
||||
and the PPI (parallel port interface). PPI represents a class
|
||||
AVRDUDE supports three basic programmer types: Atmel's STK500, appnote
|
||||
avr910 and the PPI (parallel port interface). PPI represents a class
|
||||
of simple programmers where the programming lines are directly
|
||||
connected to the PC parallel port. Several pin configurations exist
|
||||
for several variations of the PPI programmers, and AVRDUDE can be be
|
||||
configured to work with them by either specifying the appropriate
|
||||
programmer on the command line or by creating a new entry in its
|
||||
configuration file. All that's usually required for a new entry is to
|
||||
tell AVRDUDE which pins to use for each programming function.
|
||||
tell AVRDUDE which pins to use for each programming function.
|
||||
|
||||
A number of equally simple bit-bang programming adapters that connect
|
||||
to a serial port are supported as well, among them the popular
|
||||
Ponyprog serial adapter, and the DASA and DASA3 adapters that used to
|
||||
be supported by uisp(1). Note that these adapters are meant to be
|
||||
attached to a physical serial port. Connecting to a serial port
|
||||
emulated on top of USB is likely to not work at all, or to work
|
||||
abysmally slow.
|
||||
|
||||
The STK500, JTAG ICE, avr910, and avr109/butterfly use the serial port to communicate with the PC.
|
||||
The STK500, JTAG ICE, and avr910 contain on-board logic to control the programming of the target
|
||||
device.
|
||||
The avr109 bootloader implements a protocol similar to avr910, but is
|
||||
actually implemented in the boot area of the target's flash ROM, as
|
||||
opposed to being an external device.
|
||||
The fundamental difference between the two types lies in the
|
||||
protocol used to control the programmer. The avr910 protocol is very
|
||||
The STK500 and avr910 use the serial port to communicate with the PC
|
||||
and contains on-board logic to control the programming of the target
|
||||
device. The fundamental difference between the two types lies in the
|
||||
protocol used to control the programmer. The av910 protocol is very
|
||||
simplistic and can easily be used as the basis for a simple, home made
|
||||
programer since the firmware is available online. On the other hand,
|
||||
the STK500 protocol is more robust and complicated and the firmware is
|
||||
not openly available.
|
||||
The JTAG ICE also uses a serial communication protocol which is similar
|
||||
to the STK500 firmware version 2 one. However, as the JTAG ICE is
|
||||
intented to allow on-chip debugging as well as memory programming, the
|
||||
protocol is more sophisticated.
|
||||
(This protocol can also be run on top of USB.)
|
||||
Only the memory programming functionality of the JTAG ICE is supported
|
||||
by AVRDUDE.
|
||||
|
||||
@menu
|
||||
* History::
|
||||
@@ -210,8 +186,8 @@ Roth.
|
||||
@cindex options
|
||||
|
||||
@menu
|
||||
* Option Descriptions::
|
||||
* Example Command Line Invocations::
|
||||
* Option Descriptions::
|
||||
* Example Command Line Invocations::
|
||||
@end menu
|
||||
|
||||
@c
|
||||
@@ -235,7 +211,7 @@ following options are recognized:
|
||||
@item -p @var{partno}
|
||||
This is the only mandatory option and it tells AVRDUDE what type of part
|
||||
(MCU) that is connected to the programmer. The @var{partno} parameter
|
||||
is the part's id listed in the configuration file. Specify -p ? to list
|
||||
is the part's id listed in the configuration file. Specify -p ? to list
|
||||
all parts in the configuration file. If a part is unknown
|
||||
to AVRDUDE, it means that there is no config file entry for that part,
|
||||
but it can be added to the configuration file if you have the Atmel
|
||||
@@ -243,15 +219,6 @@ datasheet so that you can enter the programming specifications.
|
||||
Currently, the following MCU types are understood:
|
||||
|
||||
@table @code
|
||||
@itemx c128
|
||||
AT90CAN128
|
||||
|
||||
@itemx pwm2
|
||||
AT90PWM2
|
||||
|
||||
@itemx pwm3
|
||||
AT90PWM3
|
||||
|
||||
@itemx 1200
|
||||
AT90S1200
|
||||
|
||||
@@ -280,110 +247,41 @@ AT90S8515
|
||||
AT90S8535
|
||||
|
||||
@itemx m103
|
||||
ATmega103
|
||||
ATMEGA103
|
||||
|
||||
@itemx m128
|
||||
ATmega128
|
||||
ATMEGA128
|
||||
|
||||
@itemx m16
|
||||
ATmega16
|
||||
|
||||
@itemx m161
|
||||
ATmega161
|
||||
|
||||
@itemx m162
|
||||
ATmega162
|
||||
ATMEGA16
|
||||
|
||||
@itemx m163
|
||||
ATmega163
|
||||
|
||||
@itemx m164
|
||||
ATmega164
|
||||
ATMEGA163
|
||||
|
||||
@itemx m169
|
||||
ATmega169
|
||||
ATMEGA169
|
||||
|
||||
@itemx m32
|
||||
ATmega32
|
||||
|
||||
@itemx m324
|
||||
ATmega324
|
||||
|
||||
@itemx m329
|
||||
ATmega329
|
||||
|
||||
@itemx m3290
|
||||
ATmega3290
|
||||
|
||||
@itemx m48
|
||||
ATmega48
|
||||
|
||||
@itemx m64
|
||||
ATmega64
|
||||
|
||||
@itemx m644
|
||||
ATmega644
|
||||
|
||||
@itemx m649
|
||||
ATmega649
|
||||
|
||||
@itemx m6490
|
||||
ATmega6490
|
||||
ATMEGA32
|
||||
|
||||
@itemx m8
|
||||
ATmega8
|
||||
|
||||
@itemx m8515
|
||||
ATmega8515
|
||||
ATMEGA8
|
||||
|
||||
@itemx m8535
|
||||
ATmega8535
|
||||
|
||||
@itemx m88
|
||||
ATmega88
|
||||
ATMEGA8535
|
||||
|
||||
@itemx t12
|
||||
ATtiny12
|
||||
|
||||
@itemx t13
|
||||
ATtiny13
|
||||
|
||||
@itemx t15
|
||||
ATtiny15
|
||||
|
||||
@itemx t2313
|
||||
ATtiny2313
|
||||
|
||||
@itemx t25
|
||||
ATtiny25
|
||||
|
||||
@itemx t26
|
||||
ATtiny26
|
||||
|
||||
@itemx t45
|
||||
ATtiny45
|
||||
|
||||
@itemx t85
|
||||
ATtiny85
|
||||
ATTINY26
|
||||
|
||||
@end table
|
||||
|
||||
(*) The AT90S2323 and ATtiny22 use the same algorithm.
|
||||
|
||||
@item -b @var{baudrate}
|
||||
Override the RS-232 connection baud rate specified in the respective
|
||||
programmer's entry of the configuration file.
|
||||
|
||||
@item -B @var{bitclock}
|
||||
Specify the bit clock period for the JTAG interface (JTAG ICE only).
|
||||
The value is a floating-point number in microseconds.
|
||||
The default value of the JTAG ICE results in about 1 microsecond bit
|
||||
clock period, suitable for target MCUs running at 4 MHz clock and
|
||||
above.
|
||||
Unlike certain parameters in the STK500, the JTAG ICE resets all its
|
||||
parameters to default values when the programming software signs
|
||||
off from the ICE, so for MCUs running at lower clock speeds, this
|
||||
parameter must be specified on the command-line.
|
||||
(*) The AT90S2323 uses the same algorithm.
|
||||
|
||||
@item -c @var{programmer-id}
|
||||
Specify the programmer to be used. AVRDUDE knows about several common
|
||||
@@ -399,23 +297,14 @@ Currently, the following programmer ids are understood and supported:
|
||||
|
||||
@table @code
|
||||
|
||||
@itemx abcmini
|
||||
ABCmini Board, aka Dick Smith HOTCHIP
|
||||
|
||||
@itemx alf
|
||||
Nightshade ALF-PgmAVR, http://nightshade.homeip.net/
|
||||
|
||||
@itemx avr109
|
||||
Atmel AppNote AVR109 Boot Loader
|
||||
|
||||
@itemx avr910
|
||||
Atmel Low Cost Serial Programmer
|
||||
|
||||
@itemx avr911
|
||||
Atmel AppNote AVR911 AVROSP (an alias for avr109)
|
||||
|
||||
@itemx avrisp
|
||||
Atmel AVR ISP
|
||||
Atmel AVR ISP
|
||||
|
||||
@itemx bascom
|
||||
Bascom SAMPLE programming cable
|
||||
@@ -423,21 +312,8 @@ Bascom SAMPLE programming cable
|
||||
@itemx bsd
|
||||
Brian Dean's Programmer, http://www.bsdhome.com/avrdude/
|
||||
|
||||
@itemx butterfly
|
||||
Atmel Butterfly Development Board
|
||||
|
||||
@itemx dt006
|
||||
Dontronics DT006
|
||||
|
||||
@item jtagmkII
|
||||
@itemx jtag2slow
|
||||
Atmel JTAG ICE mkII (default speed 19200 Bd)
|
||||
|
||||
@itemx jtag2fast
|
||||
Atmel JTAG ICE mkII, running at 115200 Bd
|
||||
|
||||
@itemx jtag2
|
||||
Same as before.
|
||||
Dontronics DT006
|
||||
|
||||
@itemx pavr
|
||||
Jason Kyle's pAVR Serial Programmer
|
||||
@@ -445,20 +321,17 @@ Jason Kyle's pAVR Serial Programmer
|
||||
@itemx picoweb
|
||||
Picoweb Programming Cable, http://www.picoweb.net/
|
||||
|
||||
@itemx pony-stk200
|
||||
Pony Prog STK200
|
||||
@itemx pony
|
||||
stk200 = Pony Prog STK200
|
||||
|
||||
@itemx sp12
|
||||
Steve Bolt's Programmer
|
||||
Steve Bolt's Programmer
|
||||
|
||||
@itemx stk200
|
||||
STK200
|
||||
STK200
|
||||
|
||||
@itemx stk500
|
||||
Atmel STK500
|
||||
|
||||
@itemx stk500v2
|
||||
Atmel STK500, running a verrsion 2.x firmware
|
||||
Atmel STK500
|
||||
|
||||
@end table
|
||||
|
||||
@@ -474,14 +347,6 @@ specified, AVRDUDE reads the configuration file from
|
||||
/usr/local/etc/avrdude.conf (FreeBSD and Linux). See Appendix A for
|
||||
the method of searching for the configuration file for Windows.
|
||||
|
||||
@item -D
|
||||
Disable auto erase for flash. When the -U option with flash memory is
|
||||
specified, avrdude will perform a chip erase before starting any of the
|
||||
programming operations, since it generally is a mistake to program the flash
|
||||
without performing an erase first. This option disables that. However, to
|
||||
remain backward compatible, the -i, and -m options automatically disable the
|
||||
auto erase feature.
|
||||
|
||||
@item -e
|
||||
Causes a chip erase to be executed. This will reset the contents of the
|
||||
flash ROM and EEPROM to the value `0xff', and is basically a
|
||||
@@ -514,7 +379,7 @@ The `/RESET' line will be deactivated at program exit, thus allowing the
|
||||
MCU target program to run while the programming hardware remains
|
||||
connected.
|
||||
|
||||
@itemx vcc
|
||||
@itemx vcc
|
||||
This option will leave those parallel port pins active (i. e. high) that
|
||||
can be used to supply `Vcc' power to the MCU.
|
||||
|
||||
@@ -527,104 +392,10 @@ program exit.
|
||||
Multiple @var{exitspec} arguments can be separated with commas.
|
||||
|
||||
|
||||
@item -F
|
||||
Normally, AVRDUDE tries to verify that the device signature read from
|
||||
the part is reasonable before continuing. Since it can happen from time
|
||||
to time that a device has a broken (erased or overwritten) device
|
||||
signature but is otherwise operating normally, this options is provided
|
||||
to override the check.
|
||||
|
||||
@item -n
|
||||
No-write - disables actually writing data to the MCU (useful for
|
||||
debugging AVRDUDE).
|
||||
|
||||
@item -P @var{port}
|
||||
Use port to identify the device to which the programmer is attached.
|
||||
Normally, the default parallel port is used, but if the programmer type
|
||||
normally connects to the serial port, the default serial port will be
|
||||
used. See Appendix A, Platform Dependent Information, to find out the
|
||||
default port names for your platform. If you need to use a different
|
||||
parallel or serial port, use this option to specify the alternate port name.
|
||||
|
||||
For the JTAG ICE mkII, if AVRDUDE has been built with libusb support,
|
||||
@var{port} may alternatively be specified as
|
||||
@var{usb}[:@var{serialno}]. In that case, the JTAG ICE mkII will be
|
||||
looked up on USB. If @var{serialno} is also specified, it will be
|
||||
matched against the serial number read from any JTAG ICE mkII found on
|
||||
USB. The match is done after stripping any existing colons from the
|
||||
given serial number, and right-to-left, so only the least significant
|
||||
bytes from the serial number need to be given.
|
||||
|
||||
@item -q
|
||||
Disable (or quell) output of the progress bar while reading or writing
|
||||
to the device. Specify it a second time for even quieter operation.
|
||||
|
||||
@item -u
|
||||
Disables the default behaviour of reading out the fuses three times before
|
||||
programming, then verifying at the end of programming that the fuses have not
|
||||
changed. If you want to change fuses you will need to specify this option,
|
||||
as avrdude will see the fuses have changed (even though you wanted to) and
|
||||
will change them back for your "saftey". This option was designed to
|
||||
prevent cases of fuse bits magically changing (usually called @emph{safemode}).
|
||||
|
||||
@item -t
|
||||
Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up-
|
||||
or downloading files. See below for a detailed description of the
|
||||
terminal mode.
|
||||
|
||||
@item -U @var{memtype}:@var{op}:@var{filename}[:@var{format}]
|
||||
Perform a memory operation, equivalent to specifing the @option{-m},
|
||||
@option{-i} or @option{-o}, and @option{-f} options, except that
|
||||
multiple @option{-U} optins can be specified in order to operate on
|
||||
mulitple memories on the same command-line invocation. The
|
||||
@var{memtype} field specifies the memory type to operate on. Use
|
||||
the @option{-v} option on the command line or the @code{part} command from
|
||||
terminal mode to display all the memory types supported by a particular
|
||||
device.
|
||||
Typically, a device's memory configuration at least contains
|
||||
the memory types
|
||||
@code{flash}
|
||||
and
|
||||
@code{eeprom}.
|
||||
All memory types currently known are:
|
||||
@table @code
|
||||
@item calibration
|
||||
One or more bytes of RC oscillator calibration data.
|
||||
@item eeprom
|
||||
The EEPROM of the device.
|
||||
@item efuse
|
||||
The extended fuse byte.
|
||||
@item flash
|
||||
The flash ROM of the device.
|
||||
@item fuse
|
||||
The fuse byte in devices that have only a single fuse byte.
|
||||
@item hfuse
|
||||
The high fuse byte.
|
||||
@item lfuse
|
||||
The low fuse byte.
|
||||
@item lock
|
||||
The lock byte.
|
||||
@item signature
|
||||
The three device signature bytes (device ID).
|
||||
@end table
|
||||
|
||||
The @var{op} field specifies what operation to perform:
|
||||
|
||||
@table @code
|
||||
@itemx r
|
||||
read the specified device memory and write to the specified file
|
||||
|
||||
@itemx w
|
||||
read the specified file and write it to the specified device memory
|
||||
|
||||
@itemx v
|
||||
read the specified device memory and the specified file and perform a verify operation
|
||||
|
||||
@end table
|
||||
|
||||
The @var{filename} field indicates the name of the file to read or
|
||||
write. The @var{format} field is optional and contains the format of
|
||||
the file to read or write. Possible values are:
|
||||
@item -f @var{format}
|
||||
This option specifies the file format for the input or output files to
|
||||
be processed. Format can be one of:
|
||||
|
||||
@table @code
|
||||
@itemx i
|
||||
@@ -655,9 +426,74 @@ at stdin.
|
||||
The default is to use auto detection for input files, and raw binary
|
||||
format for output files.
|
||||
|
||||
Note that if @var{filename} contains a colon, the @var{format} field is
|
||||
no longer optional since the filename part following the colon would
|
||||
otherwise be misinterpreted as @var{format}.
|
||||
@item -F
|
||||
Normally, AVRDUDE tries to verify that the device signature read from
|
||||
the part is reasonable before continuing. Since it can happen from time
|
||||
to time that a device has a broken (erased or overwritten) device
|
||||
signature but is otherwise operating normally, this options is provided
|
||||
to override the check.
|
||||
|
||||
@item -i @var{filename}
|
||||
Specifies the input file to be programmed into the MCU. Can be
|
||||
specified as `-' to use stdin as the input.
|
||||
|
||||
@item -m @var{memtype}
|
||||
Specifies which program area of the MCU to read or write; allowable
|
||||
values depend on the MCU being programmed, but most support at least
|
||||
@code{eeprom} for the EEPROM, and @code{flash} for the flash ROM. Use
|
||||
the @option{-v} option on the command line or the @code{part} command from
|
||||
terminal mode to display all the memory types supported by a particular
|
||||
device. The default is @code{flash}.
|
||||
|
||||
@item -n
|
||||
No-write - disables actually writing data to the MCU (useful for
|
||||
debugging AVRDUDE).
|
||||
|
||||
@item -o @var{filename}
|
||||
Specifies the name of the output file to write, and causes the
|
||||
respective memory area to be read from the MCU. Can be specified as `-'
|
||||
to write to stdout.
|
||||
|
||||
@item -P @var{port}
|
||||
Use port to identify the device to which the programmer is attached. By
|
||||
default the @code{/dev/ppi0} port is used, but if the programmer type
|
||||
normally connects to the serial port, the @code{/dev/cuaa0} port is the
|
||||
default. If you need to use a different parallel or serial port, use
|
||||
this option to specify the alternate port name.
|
||||
|
||||
@item -q
|
||||
Disable (or quell) output of the progress bar while reading or writing
|
||||
to the device.
|
||||
|
||||
@item -t
|
||||
Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up-
|
||||
or downloading files. See below for a detailed description of the
|
||||
terminal mode.
|
||||
|
||||
@item -U @var{memtype}:@var{op}:@var{filename}[:@var{format}]
|
||||
Perform a memory operation, equivalent to specifing the @option{-m},
|
||||
@option{-i} or @option{-o}, and @option{-f} options, except that
|
||||
multiple @option{-U} optins can be specified in order to operate on
|
||||
mulitple memories on the same command-line invocation. The
|
||||
@var{memtype} field specifies the memory type to operate on. The
|
||||
@var{op} field specifies what operation to perform:
|
||||
|
||||
@table @code
|
||||
@itemx r
|
||||
read the specified device memory and write to the specified file
|
||||
|
||||
@itemx w
|
||||
read the specified file and write it to the specified device memory
|
||||
|
||||
@itemx v
|
||||
read the specified device memory and the specified file and perform a verify operation
|
||||
|
||||
@end table
|
||||
|
||||
The @var{filename} field indicates the name of the file to read or
|
||||
write. The @var{format} field is optional and contains the format of
|
||||
the file to read or write. See the @option{-f} option for possible
|
||||
values.
|
||||
|
||||
@item -v
|
||||
Enable verbose output.
|
||||
@@ -688,7 +524,6 @@ should not be used.
|
||||
|
||||
@end table
|
||||
|
||||
@page
|
||||
@c
|
||||
@c Node
|
||||
@c
|
||||
@@ -729,23 +564,20 @@ Reading | ################################################## | 100% 6.83s
|
||||
avrdude: verifying ...
|
||||
avrdude: 19278 bytes of flash verified
|
||||
|
||||
avrdude: safemode: Fuses OK
|
||||
|
||||
avrdude done. Thank you.
|
||||
|
||||
%
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
@page
|
||||
@noindent
|
||||
Upload the flash memory from the ATmega128 connected to the STK500
|
||||
programmer and save it in raw binary format in the file named
|
||||
@code{c:/diag flash.bin}:
|
||||
@code{diag.flash}:
|
||||
|
||||
@example
|
||||
@cartouche
|
||||
% avrdude -p m128 -c stk500 -U flash:r:"c:/diag flash.bin":r
|
||||
% avrdude -p m128 -c stk500 -U flash:r:diag.flash:r
|
||||
|
||||
avrdude: AVR device initialized and ready to accept instructions
|
||||
|
||||
@@ -756,9 +588,7 @@ avrdude: reading flash memory:
|
||||
|
||||
Reading | ################################################## | 100% 46.10s
|
||||
|
||||
avrdude: writing output file "c:/diag flash.bin"
|
||||
|
||||
avrdude: safemode: Fuses OK
|
||||
avrdude: writing output file "diag.flash"
|
||||
|
||||
avrdude done. Thank you.
|
||||
|
||||
@@ -766,7 +596,6 @@ avrdude done. Thank you.
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
@page
|
||||
@noindent
|
||||
Using the default programmer, download the file @code{diag.hex} to
|
||||
flash, @code{eeprom.hex} to EEPROM, and set the Extended, High, and Low
|
||||
@@ -775,7 +604,7 @@ fuse bytes to 0xff, 0x89, and 0x2e respectively:
|
||||
@example
|
||||
@cartouche
|
||||
|
||||
% avrdude -p m128 -u -U flash:w:diag.hex \
|
||||
% avrdude -p m128 -U flash:w:diag.hex \
|
||||
> -U eeprom:w:eeprom.hex \
|
||||
> -U efuse:w:0xff:m \
|
||||
> -U hfuse:w:0x89:m \
|
||||
@@ -815,29 +644,6 @@ avrdude done. Thank you.
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
@page
|
||||
@noindent
|
||||
Connect to the JTAG ICE mkII which serial number ends up in 1C37 via
|
||||
USB, and enter terminal mode:
|
||||
|
||||
@example
|
||||
@cartouche
|
||||
|
||||
% avrdude -c jtag2 -p m649 -P usb:1c:37 -t
|
||||
|
||||
avrdude: AVR device initialized and ready to accept instructions
|
||||
|
||||
Reading | ################################################## | 100% 0.03s
|
||||
|
||||
avrdude: Device signature = 0x1e9603
|
||||
|
||||
[ ... terminal mode output skipped for brevity ... ]
|
||||
|
||||
avrdude done. Thank you.
|
||||
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
|
||||
|
||||
@c
|
||||
@@ -895,9 +701,7 @@ command.
|
||||
Display the device signature bytes.
|
||||
|
||||
@item part
|
||||
Display the current part settings and parameters. Includes chip
|
||||
specific information including all memory types supported by the
|
||||
device, read/write timing, etc.
|
||||
Display the current part settings.
|
||||
|
||||
@item ?
|
||||
@itemx help
|
||||
@@ -930,23 +734,9 @@ multiplies by 1E6, a trailing letter @var{k} by 1E3.
|
||||
@item fosc off
|
||||
Turn the master oscillator off.
|
||||
|
||||
@item sck @var{period}
|
||||
@emph{STK500 only:}
|
||||
Set the SCK clock period to @var{period} microseconds.
|
||||
|
||||
@emph{JTAG ICE only:}
|
||||
Set the JTAG ICE bit clock period to @var{period} microseconds.
|
||||
Note that unlike STK500 settings, this setting will be reverted to
|
||||
its default value (approximately 1 microsecond) when the programming
|
||||
software signs off from the JTAG ICE.
|
||||
|
||||
@item parms
|
||||
@emph{STK500 only:}
|
||||
Display the current voltage and master oscillator parameters.
|
||||
|
||||
@emph{JTAG ICE only:}
|
||||
Display the current target supply voltage and JTAG bit clock rate/period.
|
||||
|
||||
@end table
|
||||
|
||||
@c
|
||||
@@ -1016,13 +806,11 @@ avrdude>
|
||||
@noindent
|
||||
Program the fuse bits of an ATmega128 (disable M103 compatibility,
|
||||
enable high speed external crystal, enable brown-out detection, slowly
|
||||
rising power). Note since we are working with fuse bits the -u (unsafe)
|
||||
option is specified, which allows you to modify the fuse bits. First
|
||||
display the factory defaults, then reprogram:
|
||||
rising power). First display the factory defaults, then reprogram:
|
||||
|
||||
@example
|
||||
@cartouche
|
||||
% avrdude -p m128 -u -c stk500 -t
|
||||
% avrdude -p m128 -c stk500 -t
|
||||
|
||||
avrdude: AVR device initialized and ready to accept instructions
|
||||
avrdude: Device signature = 0x1e9702
|
||||
@@ -1122,18 +910,17 @@ The format of the programmer definition is as follows:
|
||||
@example
|
||||
programmer
|
||||
id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
|
||||
desc = <description> ; # quoted string
|
||||
type = par | stk500 ; # programmer type
|
||||
baudrate = <num> ; # baudrate for serial ports
|
||||
vcc = <num1> [, <num2> ... ] ; # pin number(s)
|
||||
reset = <num> ; # pin number
|
||||
sck = <num> ; # pin number
|
||||
mosi = <num> ; # pin number
|
||||
miso = <num> ; # pin number
|
||||
errled = <num> ; # pin number
|
||||
rdyled = <num> ; # pin number
|
||||
pgmled = <num> ; # pin number
|
||||
vfyled = <num> ; # pin number
|
||||
desc = <description> ; # quoted string
|
||||
type = par | stk500 ; # programmer type
|
||||
vcc = <num1> [, <num2> ... ] ; # pin number(s)
|
||||
reset = <num> ; # pin number
|
||||
sck = <num> ; # pin number
|
||||
mosi = <num> ; # pin number
|
||||
miso = <num> ; # pin number
|
||||
errled = <num> ; # pin number
|
||||
rdyled = <num> ; # pin number
|
||||
pgmled = <num> ; # pin number
|
||||
vfyled = <num> ; # pin number
|
||||
;
|
||||
@end example
|
||||
|
||||
@@ -1180,7 +967,7 @@ part
|
||||
@end example
|
||||
|
||||
@menu
|
||||
* Instruction Format::
|
||||
* Instruction Format::
|
||||
@end menu
|
||||
|
||||
@c
|
||||
@@ -1228,7 +1015,7 @@ instruction for an AT90S2313 AVR part could be encoded as:
|
||||
|
||||
@example
|
||||
|
||||
read = "1 0 1 0 0 0 0 0 x x x x x x x x",
|
||||
read = "1 0 1 0 0 0 0 0 x x x x x x x x",
|
||||
"x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
|
||||
|
||||
write = "1 1 0 0 0 0 0 0 x x x x x x x x",
|
||||
@@ -1248,7 +1035,7 @@ write = "1 1 0 0 0 0 0 0 x x x x x x x x",
|
||||
@itemize @bullet
|
||||
@item
|
||||
The @code{devicecode} parameter is the device code used by the STK500
|
||||
and is obtained from the software section (@code{avr061.zip}) of
|
||||
and are obtained from the software section (@code{avr061.zip} of
|
||||
Atmel's AVR061 application note available from
|
||||
@url{http://www.atmel.com/atmel/acrobat/doc2525.pdf}.
|
||||
|
||||
@@ -1277,36 +1064,18 @@ problem with the at90s4433/2333's; see the at90s4433 errata at:
|
||||
|
||||
@url{http://www.atmel.com/atmel/acrobat/doc1280.pdf}
|
||||
|
||||
@item
|
||||
The boot loader from application note AVR109 (and thus also the AVR
|
||||
Butterfly) does not support writing of fuse bits. Writing lock bits
|
||||
is supported, but is restricted to the boot lock bits (BLBxx). These
|
||||
are restrictions imposed by the underlying SPM instruction that is used
|
||||
to program the device from inside the boot loader. Note that programming
|
||||
the boot lock bits can result in a ``shoot-into-your-foot'' scenario as
|
||||
the only way to unprogram these bits is a chip erase, which will also
|
||||
erase the boot loader code.
|
||||
|
||||
The boot loader implements the ``chip erase'' function by erasing the
|
||||
flash pages of the application section.
|
||||
|
||||
Reading fuse and lock bits is fully supported.
|
||||
|
||||
Note that due to the unability to write the fuse bits, the safemode
|
||||
functionality does not make sense for these boot loaders.
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
@c
|
||||
@c Node
|
||||
@c
|
||||
@node Platform Dependent Information, Troubleshooting, Configuration File, Top
|
||||
@node Platform Dependent Information, , Configuration File, Top
|
||||
@appendix Platform Dependent Information
|
||||
|
||||
@menu
|
||||
* Unix::
|
||||
* Windows::
|
||||
* Unix::
|
||||
* Windows::
|
||||
@end menu
|
||||
|
||||
@c
|
||||
@@ -1742,89 +1511,4 @@ line driven and for writing the batch files.
|
||||
|
||||
@end itemize
|
||||
|
||||
@c
|
||||
@c Node
|
||||
@c
|
||||
@node Troubleshooting, ,Platform Dependent Information ,Top
|
||||
@appendix Troubleshooting
|
||||
|
||||
@noindent
|
||||
In general, please report any bugs encountered via
|
||||
@url{http://savannah.nongnu.org/bugs/?group=avrdude}.
|
||||
|
||||
|
||||
@itemize @bullet
|
||||
|
||||
@item
|
||||
Problem: I'm using a serial programmer under Windows and get the following
|
||||
error:
|
||||
|
||||
@code{avrdude: serial_open(): can't set attributes for device "com1"},
|
||||
|
||||
Solution: This problem seems to appear with certain versions of Cygwin. Specifying
|
||||
@code{"/dev/com1"} instead of @code{"com1"} should help.
|
||||
|
||||
|
||||
@item
|
||||
Problem: I'm using linux and my AVR910 programmer is really slow.
|
||||
|
||||
Solution (short): @code{setserial @var{port} low_latency}
|
||||
|
||||
Solution (long):
|
||||
There are two problems here. First, the system may wait some time before it
|
||||
passes data from the serial port to the program. Under Linux the following
|
||||
command works around this (you may need root privileges for this).
|
||||
|
||||
@code{setserial @var{port} low_latency}
|
||||
|
||||
Secondly, the serial interface chip may delay the interrupt for some time.
|
||||
This behaviour can be changed by setting the FIFO-threshold to one. Under Linux this
|
||||
can only be done by changing the kernel source in @code{drivers/char/serial.c}.
|
||||
Search the file for @code{UART_FCR_TRIGGER_8} and replace it with @code{UART_FCR_TRIGGER_1}. Note that overall performance might suffer if there
|
||||
is high throughput on serial lines. Also note that you are modifying the kernel at
|
||||
your own risk.
|
||||
|
||||
|
||||
@item
|
||||
Problem: I'm not using linux and my AVR910 programmer is really slow.
|
||||
|
||||
Solutions: The reasons for this are the same as above.
|
||||
If you know how to work around this on your OS, please let us know.
|
||||
|
||||
@item
|
||||
Problem: I cannot modify the fuse bits on my AVR!
|
||||
|
||||
Solution: You probably forgot to specify the -u option, which allows you to modify fuse bits.
|
||||
This is done to prevent corrupt data from changing the fuse bits without you knowing about it, and
|
||||
currently also prevents the user from changing the fuse bits by accident. This patch was added in
|
||||
response to a number of occasions when an AVR had stopped responding because the fuse bits got changed
|
||||
by an error caused by the programmer. Programmer of course meaning both the physical device, and the
|
||||
person sitting at the keyboard.
|
||||
|
||||
@item
|
||||
Problem: AVRDUDE says my device is not supported when using the AVR109 boot loader
|
||||
|
||||
Solution: Currently, AVRDUDE uses the AVR910 device codes given in the
|
||||
@code{avrdude.conf} file, and matches them against the list of supported
|
||||
devices reported by the programmer. Unfortunately, there are no device
|
||||
codes at all for some of the newer AVR devices, and even worse, the
|
||||
device codes listed in @code{preprocessor.xls} of appnote AVR109 do not
|
||||
match those once specified in AVR910.
|
||||
|
||||
Use the -F option to force AVRDUDE to continue anyway.
|
||||
|
||||
@item
|
||||
Problem: Updating the flash ROM from terminal mode does not work with the
|
||||
JTAG ICE mkII.
|
||||
|
||||
Solution: None at this time. Currently, the JTAG ICE mkII code cannot
|
||||
write to the flash ROM one byte at a time.
|
||||
|
||||
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
|
||||
@bye
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -48,7 +48,6 @@ struct ihexrec {
|
||||
|
||||
extern char * progname;
|
||||
extern char progbuf[];
|
||||
extern int quell_progress;
|
||||
|
||||
int b2ihex(unsigned char * inbuf, int bufsize,
|
||||
int recsize, int startaddr,
|
||||
@@ -911,7 +910,7 @@ int fileio(int op, char * filename, FILEFMT format,
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
#if defined(__CYGWIN__)
|
||||
/* Open Raw Binary format in binary mode on Windows.*/
|
||||
if(format == FMT_RBIN)
|
||||
{
|
||||
@@ -971,10 +970,8 @@ int fileio(int op, char * filename, FILEFMT format,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (quell_progress < 2) {
|
||||
fprintf(stderr, "%s: %s file %s auto detected as %s\n",
|
||||
progname, fio.iodesc, fname, fmtstr(format));
|
||||
}
|
||||
fprintf(stderr, "%s: %s file %s auto detected as %s\n",
|
||||
progname, fio.iodesc, fname, fmtstr(format));
|
||||
}
|
||||
|
||||
if (format != FMT_IMM) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
|
||||
1821
avrdude/jtagmkII.c
1821
avrdude/jtagmkII.c
File diff suppressed because it is too large
Load Diff
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 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$ */
|
||||
|
||||
#ifndef jtagmkII_h
|
||||
#define jtagmkII_h
|
||||
|
||||
void jtagmkII_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,290 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2005 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
|
||||
/*
|
||||
* JTAG ICE mkII definitions
|
||||
* Taken from Appnote AVR067
|
||||
*/
|
||||
|
||||
/*
|
||||
* Communication with the JTAG ICE works in frames. The protocol
|
||||
* somewhat resembles the STK500v2 protocol, yet it is sufficiently
|
||||
* different to prevent a direct code reuse. :-(
|
||||
*
|
||||
* Frame format:
|
||||
*
|
||||
* +---------------------------------------------------------------+
|
||||
* | 0 | 1 . 2 | 3 . 4 . 5 . 6 | 7 | ... | N-1 . N |
|
||||
* | | | | | | |
|
||||
* | start | LSB MSB | LSB ....... MSB | token | msg | LSB MSB |
|
||||
* | 0x1B | sequence# | message size | 0x0E | | CRC16 |
|
||||
* +---------------------------------------------------------------+
|
||||
*
|
||||
* Each request message will be returned by a response with a matching
|
||||
* sequence #. Sequence # 0xffff is reserved for asynchronous event
|
||||
* notifications that will be sent by the ICE without a request
|
||||
* message (e.g. when the target hit a breakpoint).
|
||||
*
|
||||
* The message size excludes the framing overhead (10 bytes).
|
||||
*
|
||||
* The first byte of the message is always the request or response
|
||||
* code, which is roughly classified as:
|
||||
*
|
||||
* . Messages (commands) use 0x00 through 0x3f. (The documentation
|
||||
* claims that messages start at 0x01, but actually CMND_SIGN_OFF is
|
||||
* 0x00.)
|
||||
* . Internal commands use 0x40 through 0x7f (not documented).
|
||||
* . Success responses use 0x80 through 0x9f.
|
||||
* . Failure responses use 0xa0 through 0xbf.
|
||||
* . Events use 0xe0 through 0xff.
|
||||
*/
|
||||
#define MESSAGE_START 0x1b
|
||||
#define TOKEN 0x0e
|
||||
|
||||
/*
|
||||
* Max message size we are willing to accept. Prevents us from trying
|
||||
* to allocate too much VM in case we received a nonsensical packet
|
||||
* length. We have to allocate the buffer as soon as we've got the
|
||||
* length information (and thus have to trust that information by that
|
||||
* time at first), as the final CRC check can only be done once the
|
||||
* entire packet came it.
|
||||
*/
|
||||
#define MAX_MESSAGE 100000
|
||||
|
||||
/* ICE command codes */
|
||||
#define CMND_CHIP_ERASE 0x13
|
||||
#define CMND_CLEAR_EVENTS 0x22
|
||||
#define CMND_CLR_BREAK 0x1A
|
||||
#define CMND_ENTER_PROGMODE 0x14
|
||||
#define CMND_ERASEPAGE_SPM 0x0D
|
||||
#define CMND_FORCED_STOP 0x0A
|
||||
#define CMND_GET_BREAK 0x12
|
||||
#define CMND_GET_PARAMETER 0x03
|
||||
#define CMND_GET_SIGN_ON 0x01
|
||||
#define CMND_GET_SYNC 0x0f
|
||||
#define CMND_GO 0x08
|
||||
#define CMND_LEAVE_PROGMODE 0x15
|
||||
#define CMND_READ_MEMORY 0x05
|
||||
#define CMND_READ_PC 0x07
|
||||
#define CMND_RESET 0x0B
|
||||
#define CMND_RESTORE_TARGET 0x23
|
||||
#define CMND_RUN_TO_ADDR 0x1C
|
||||
#define CMND_SELFTEST 0x10
|
||||
#define CMND_SET_BREAK 0x11
|
||||
#define CMND_SET_DEVICE_DESCRIPTOR 0x0C
|
||||
#define CMND_SET_N_PARAMETERS 0x16
|
||||
#define CMND_SET_PARAMETER 0x02
|
||||
#define CMND_SIGN_OFF 0x00
|
||||
#define CMND_SINGLE_STEP 0x09
|
||||
#define CMND_SPI_CMD 0x1D
|
||||
#define CMND_WRITE_MEMORY 0x04
|
||||
#define CMND_WRITE_PC 0x06
|
||||
|
||||
/* ICE responses */
|
||||
#define RSP_DEBUGWIRE_SYNC_FAILED 0xAC
|
||||
#define RSP_FAILED 0xA0
|
||||
#define RSP_GET_BREAK 0x83
|
||||
#define RSP_ILLEGAL_BREAKPOINT 0xA8
|
||||
#define RSP_ILLEGAL_COMMAND 0xAA
|
||||
#define RSP_ILLEGAL_EMULATOR_MODE 0xA4
|
||||
#define RSP_ILLEGAL_JTAG_ID 0xA9
|
||||
#define RSP_ILLEGAL_MCU_STATE 0xA5
|
||||
#define RSP_ILLEGAL_MEMORY_TYPE 0xA2
|
||||
#define RSP_ILLEGAL_MEMORY_RANGE 0xA3
|
||||
#define RSP_ILLEGAL_PARAMETER 0xA1
|
||||
#define RSP_ILLEGAL_POWER_STATE 0xAD
|
||||
#define RSP_ILLEGAL_VALUE 0xA6
|
||||
#define RSP_MEMORY 0x82
|
||||
#define RSP_NO_TARGET_POWER 0xAB
|
||||
#define RSP_OK 0x80
|
||||
#define RSP_PARAMETER 0x81
|
||||
#define RSP_PC 0x84
|
||||
#define RSP_SELFTEST 0x85
|
||||
#define RSP_SET_N_PARAMETERS 0xA7
|
||||
#define RSP_SIGN_ON 0x86
|
||||
#define RSP_SPI_DATA 0x88
|
||||
|
||||
/* ICE events */
|
||||
#define EVT_BREAK 0xE0
|
||||
#define EVT_DEBUG 0xE6
|
||||
#define EVT_ERROR_PHY_FORCE_BREAK_TIMEOUT 0xE2
|
||||
#define EVT_ERROR_PHY_MAX_BIT_LENGTH_DIFF 0xED
|
||||
#define EVT_ERROR_PHY_OPT_RECEIVE_TIMEOUT 0xF9
|
||||
#define EVT_ERROR_PHY_OPT_RECEIVED_BREAK 0xFA
|
||||
#define EVT_ERROR_PHY_RECEIVED_BREAK 0xF8
|
||||
#define EVT_ERROR_PHY_RECEIVE_TIMEOUT 0xF7
|
||||
#define EVT_ERROR_PHY_RELEASE_BREAK_TIMEOUT 0xE3
|
||||
#define EVT_ERROR_PHY_SYNC_OUT_OF_RANGE 0xF5
|
||||
#define EVT_ERROR_PHY_SYNC_TIMEOUT 0xF0
|
||||
#define EVT_ERROR_PHY_SYNC_TIMEOUT_BAUD 0xF4
|
||||
#define EVT_ERROR_PHY_SYNC_WAIT_TIMEOUT 0xF6
|
||||
#define EVT_RESULT_PHY_NO_ACTIVITY 0xFB
|
||||
#define EVT_EXT_RESET 0xE7
|
||||
#define EVT_ICE_POWER_ERROR_STATE 0xEA
|
||||
#define EVT_ICE_POWER_OK 0xEB
|
||||
#define EVT_IDR_DIRTY 0xEC
|
||||
#define EVT_NONE 0xEF
|
||||
#define EVT_PDSB_BREAK 0xF2
|
||||
#define EVT_PDSMB_BREAK 0xF3
|
||||
#define EVT_PROGRAM_BREAK 0xF1
|
||||
#define EVT_RUN 0xE1
|
||||
#define EVT_TARGET_POWER_OFF 0xE5
|
||||
#define EVT_TARGET_POWER_ON 0xE4
|
||||
#define EVT_TARGET_SLEEP 0xE8
|
||||
#define EVT_TARGET_WAKEUP 0xE9
|
||||
|
||||
/* memory types for CMND_{READ,WRITE}_MEMORY */
|
||||
#define MTYPE_IO_SHADOW 0x30 /* cached IO registers? */
|
||||
#define MTYPE_SRAM 0x20 /* target's SRAM or [ext.] IO registers */
|
||||
#define MTYPE_EEPROM 0x22 /* EEPROM, what way? */
|
||||
#define MTYPE_EVENT 0x60 /* ICE event memory */
|
||||
#define MTYPE_SPM 0xA0 /* flash through LPM/SPM */
|
||||
#define MTYPE_FLASH_PAGE 0xB0 /* flash in programming mode */
|
||||
#define MTYPE_EEPROM_PAGE 0xB1 /* EEPROM in programming mode */
|
||||
#define MTYPE_FUSE_BITS 0xB2 /* fuse bits in programming mode */
|
||||
#define MTYPE_LOCK_BITS 0xB3 /* lock bits in programming mode */
|
||||
#define MTYPE_SIGN_JTAG 0xB4 /* signature in programming mode */
|
||||
#define MTYPE_OSCCAL_BYTE 0xB5 /* osccal cells in programming mode */
|
||||
#define MTYPE_CAN 0xB6 /* CAN mailbox */
|
||||
|
||||
/* (some) ICE parameters, for CMND_{GET,SET}_PARAMETER */
|
||||
#define PAR_HW_VERSION 0x01
|
||||
#define PAR_FW_VERSION 0x02
|
||||
#define PAR_EMULATOR_MODE 0x03
|
||||
# define EMULATOR_MODE_DEBUGWIRE 0x00
|
||||
# define EMULATOR_MODE_JTAG 0x01
|
||||
# define EMULATOR_MODE_UNKNOWN 0x02
|
||||
# define EMULATOR_MODE_SPI 0x03
|
||||
#define PAR_IREG 0x04
|
||||
#define PAR_BAUD_RATE 0x05
|
||||
# define PAR_BAUD_2400 0x01
|
||||
# define PAR_BAUD_4800 0x02
|
||||
# define PAR_BAUD_9600 0x03
|
||||
# define PAR_BAUD_19200 0x04 /* default */
|
||||
# define PAR_BAUD_38400 0x05
|
||||
# define PAR_BAUD_57600 0x06
|
||||
# define PAR_BAUD_115200 0x07
|
||||
# define PAR_BAUD_14400 0x08
|
||||
#define PAR_OCD_VTARGET 0x06
|
||||
#define PAR_OCD_JTAG_CLK 0x07
|
||||
#define PAR_OCD_BREAK_CAUSE 0x08
|
||||
#define PAR_TIMERS_RUNNING 0x09
|
||||
#define PAR_BREAK_ON_CHANGE_FLOW 0x0A
|
||||
#define PAR_BREAK_ADDR1 0x0B
|
||||
#define PAR_BREAK_ADDR2 0x0C
|
||||
#define PAR_COMBBREAKCTRL 0x0D
|
||||
#define PAR_JTAGID 0x0E
|
||||
#define PAR_UNITS_BEFORE 0x0F
|
||||
#define PAR_UNITS_AFTER 0x10
|
||||
#define PAR_BIT_BEFORE 0x11
|
||||
#define PAR_BIT_ATER 0x12
|
||||
#define PAR_EXTERNAL_RESET 0x13
|
||||
#define PAR_FLASH_PAGE_SIZE 0x14
|
||||
#define PAR_EEPROM_PAGE_SIZE 0x15
|
||||
#define PAR_UNUSED1 0x16
|
||||
#define PAR_PSB0 0x17
|
||||
#define PAR_PSB1 0x18
|
||||
#define PAR_PROTOCOL_DEBUG_EVENT 0x19
|
||||
#define PAR_MCU_STATE 0x1A
|
||||
# define STOPPED 0x00
|
||||
# define RUNNING 0x01
|
||||
# define PROGRAMMING 0x02
|
||||
#define PAR_DAISY_CHAIN_INFO 0x1B
|
||||
#define PAR_BOOT_ADDRESS 0x1C
|
||||
#define PAR_TARGET_SIGNATURE 0x1D
|
||||
#define PAR_DEBUGWIRE_BAUDRATE 0x1E
|
||||
#define PAR_PROGRAM_ENTRY_POINT 0x1F
|
||||
#define PAR_PACKET_PARSING_ERRORS 0x40
|
||||
#define PAR_VALID_PACKETS_RECEIVED 0x41
|
||||
#define PAR_INTERCOMMUNICATION_TX_FAILURES 0x42
|
||||
#define PAR_INTERCOMMUNICATION_RX_FAILURES 0x43
|
||||
#define PAR_CRC_ERRORS 0x44
|
||||
#define PAR_POWER_SOURCE 0x45
|
||||
# define POWER_EXTERNAL 0x00
|
||||
# define POWER_USB 0x01
|
||||
#define PAR_CAN_FLAG 0x22
|
||||
# define DONT_READ_CAN_MAILBOX 0x00
|
||||
# define READ_CAN_MAILBOX 0x01
|
||||
#define PAR_ENABLE_IDR_IN_RUN_MODE 0x23
|
||||
# define ACCESS_OSCCAL 0x00
|
||||
# define ACCESS_IDR 0x01
|
||||
#define PAR_ALLOW_PAGEPROGRAMMING_IN_SCANCHAIN 0x24
|
||||
# define PAGEPROG_NOT_ALLOWED 0x00
|
||||
# define PAGEPROG_ALLOWED 0x01
|
||||
|
||||
/*
|
||||
* In appnote AVR067, struct device_descriptor is written with
|
||||
* int/long field types. We cannot use them directly, as they were
|
||||
* neither properly aligned for portability, nor did they care for
|
||||
* endianess issues. We thus use arrays of unsigned chars, plus
|
||||
* conversion macros.
|
||||
*/
|
||||
struct device_descriptor
|
||||
{
|
||||
unsigned char ucReadIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */
|
||||
unsigned char ucReadIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */
|
||||
unsigned char ucWriteIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */
|
||||
unsigned char ucWriteIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */
|
||||
unsigned char ucReadExtIO[52]; /*LSB = IOloc 96, MSB = IOloc511 */
|
||||
unsigned char ucReadIOExtShadow[52]; /*LSB = IOloc 96, MSB = IOloc511 */
|
||||
unsigned char ucWriteExtIO[52]; /*LSB = IOloc 96, MSB = IOloc511 */
|
||||
unsigned char ucWriteIOExtShadow[52];/*LSB = IOloc 96, MSB = IOloc511 */
|
||||
unsigned char ucIDRAddress; /*IDR address */
|
||||
unsigned char ucSPMCRAddress; /*SPMCR Register address and dW BasePC */
|
||||
unsigned char ucRAMPZAddress; /*RAMPZ Register address in SRAM I/O */
|
||||
/*space */
|
||||
unsigned char uiFlashPageSize[2]; /*Device Flash Page Size, Size = */
|
||||
/*2 exp ucFlashPageSize */
|
||||
unsigned char ucEepromPageSize; /*Device Eeprom Page Size in bytes */
|
||||
unsigned char ulBootAddress[4]; /*Device Boot Loader Start Address */
|
||||
unsigned char uiUpperExtIOLoc[2]; /*Topmost (last) extended I/O */
|
||||
/*location, 0 if no external I/O */
|
||||
unsigned char ulFlashSize[4]; /*Device Flash Size */
|
||||
unsigned char ucEepromInst[20]; /*Instructions for W/R EEPROM */
|
||||
unsigned char ucFlashInst[3]; /*Instructions for W/R FLASH */
|
||||
unsigned char ucSPHaddr; /* stack pointer high */
|
||||
unsigned char ucSPLaddr; /* stack pointer low */
|
||||
/* new as of 16-02-2004 */
|
||||
unsigned char uiFlashpages[2]; /* number of pages in flash */
|
||||
unsigned char ucDWDRAddress; /* DWDR register address */
|
||||
unsigned char ucDWBasePC; /* base/mask value of the PC */
|
||||
/* new as of 30-04-2004 */
|
||||
unsigned char ucAllowFullPageBitstream; /* FALSE on ALL new */
|
||||
/*parts */
|
||||
unsigned char uiStartSmallestBootLoaderSection[2]; /* */
|
||||
/* new as of 18-10-2004 */
|
||||
unsigned char EnablePageProgramming; /* For JTAG parts only, */
|
||||
/* default TRUE */
|
||||
unsigned char ucCacheType; /* CacheType_Normal 0x00, */
|
||||
/* CacheType_CAN 0x01, */
|
||||
/* CacheType_HEIMDALL 0x02 */
|
||||
/* new as of 27-10-2004 */
|
||||
unsigned char uiSramStartAddr[2]; /* Start of SRAM */
|
||||
unsigned char ucResetType; /* Selects reset type. ResetNormal = 0x00 */
|
||||
/* ResetAT76CXXX = 0x01 */
|
||||
unsigned char ucPCMaskExtended; /* For parts with extended PC */
|
||||
unsigned char ucPCMaskHigh; /* PC high mask */
|
||||
unsigned char ucEindAddress; /* Selects reset type. [EIND address...] */
|
||||
/* new as of early 2005, firmware 4.x */
|
||||
unsigned char EECRAddress[2]; /* EECR memory-mapped IO address */
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -115,30 +115,22 @@ SIGN [+-]
|
||||
exit(1); }
|
||||
}
|
||||
|
||||
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
|
||||
avr910 { yylval=NULL; return K_AVR910; }
|
||||
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
|
||||
bank_size { yylval=NULL; return K_PAGE_SIZE; }
|
||||
banked { yylval=NULL; return K_PAGED; }
|
||||
baudrate { yylval=NULL; return K_BAUDRATE; }
|
||||
bs2 { yylval=NULL; return K_BS2; }
|
||||
buff { yylval=NULL; return K_BUFF; }
|
||||
butterfly { yylval=NULL; return K_BUTTERFLY; }
|
||||
chip_erase_delay { yylval=NULL; return K_CHIP_ERASE_DELAY; }
|
||||
desc { yylval=NULL; return K_DESC; }
|
||||
default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
|
||||
default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
|
||||
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
|
||||
devicecode { yylval=NULL; return K_DEVICECODE; }
|
||||
eecr { yylval=NULL; return K_EECR; }
|
||||
stk500_devcode { yylval=NULL; return K_STK500_DEVCODE; }
|
||||
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
|
||||
eeprom { yylval=NULL; return K_EEPROM; }
|
||||
enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; }
|
||||
errled { yylval=NULL; return K_ERRLED; }
|
||||
flash { yylval=NULL; return K_FLASH; }
|
||||
has_jtag { yylval=NULL; return K_HAS_JTAG; }
|
||||
id { yylval=NULL; return K_ID; }
|
||||
idr { yylval=NULL; return K_IDR; }
|
||||
jtagmkii { yylval=NULL; return K_JTAG_MKII; }
|
||||
max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; }
|
||||
memory { yylval=NULL; return K_MEMORY; }
|
||||
min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; }
|
||||
@@ -155,38 +147,18 @@ part { yylval=NULL; return K_PART; }
|
||||
pgmled { yylval=NULL; return K_PGMLED; }
|
||||
programmer { yylval=NULL; return K_PROGRAMMER; }
|
||||
pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; }
|
||||
rampz { yylval=NULL; return K_RAMPZ; }
|
||||
rdyled { yylval=NULL; return K_RDYLED; }
|
||||
readback_p1 { yylval=NULL; return K_READBACK_P1; }
|
||||
readback_p2 { yylval=NULL; return K_READBACK_P2; }
|
||||
retry_pulse { yylval=NULL; return K_RETRY_PULSE; }
|
||||
serbb { yylval=NULL; return K_SERBB; }
|
||||
serial { yylval=NULL; return K_SERIAL; }
|
||||
size { yylval=NULL; return K_SIZE; }
|
||||
spmcr { yylval=NULL; return K_SPMCR; }
|
||||
stk500 { yylval=NULL; return K_STK500; }
|
||||
stk500v2 { yylval=NULL; return K_STK500V2; }
|
||||
stk500_devcode { yylval=NULL; return K_STK500_DEVCODE; }
|
||||
avr910 { yylval=NULL; return K_AVR910; }
|
||||
type { yylval=NULL; return K_TYPE; }
|
||||
vcc { yylval=NULL; return K_VCC; }
|
||||
vfyled { yylval=NULL; return K_VFYLED; }
|
||||
|
||||
timeout { yylval=NULL; return K_TIMEOUT; }
|
||||
stabdelay { yylval=NULL; return K_STABDELAY; }
|
||||
cmdexedelay { yylval=NULL; return K_CMDEXEDELAY; }
|
||||
synchloops { yylval=NULL; return K_SYNCHLOOPS; }
|
||||
bytedelay { yylval=NULL; return K_BYTEDELAY; }
|
||||
pollvalue { yylval=NULL; return K_POLLVALUE; }
|
||||
pollindex { yylval=NULL; return K_POLLINDEX; }
|
||||
predelay { yylval=NULL; return K_PREDELAY; }
|
||||
postdelay { yylval=NULL; return K_POSTDELAY; }
|
||||
pollmethod { yylval=NULL; return K_POLLMETHOD; }
|
||||
mode { yylval=NULL; return K_MODE; }
|
||||
delay { yylval=NULL; return K_DELAY; }
|
||||
blocksize { yylval=NULL; return K_BLOCKSIZE; }
|
||||
readsize { yylval=NULL; return K_READSIZE; }
|
||||
|
||||
|
||||
|
||||
dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
|
||||
io { yylval=new_token(K_IO); return K_IO; }
|
||||
@@ -213,7 +185,6 @@ yes { yylval=new_token(K_YES); return K_YES; }
|
||||
"," { yylval = NULL; pyytext(); return TKN_COMMA; }
|
||||
"=" { yylval = NULL; pyytext(); return TKN_EQUAL; }
|
||||
";" { yylval = NULL; pyytext(); return TKN_SEMI; }
|
||||
"~" { yylval = NULL; pyytext(); return TKN_TILDE; }
|
||||
|
||||
"\n" { lineno++; }
|
||||
[ \r\t]+ /* ignore whitespace */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 1990-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
* 1998, 1999, 2000, 2001, 2002, 2003 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
|
||||
@@ -412,6 +413,11 @@ lcreat ( void * liststruct, int elements )
|
||||
{
|
||||
LIST * l;
|
||||
|
||||
if (LISTSZ != sizeof(LIST)) {
|
||||
printf ( "lcreat(): warning, LISTSZ[%d] != sizeof(LIST)[%d]\n",
|
||||
LISTSZ, sizeof(LIST) );
|
||||
}
|
||||
|
||||
if (liststruct == NULL) {
|
||||
/*--------------------------------------------------
|
||||
allocate memory for the list itself
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 1990-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
* 1998, 1999, 2000, 2001, 2002, 2003 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
|
||||
@@ -67,6 +68,9 @@ typedef void * LNODEID;
|
||||
#define LISTRMV(l,d) lrmv_d(l,d) /* remove from end of the list */
|
||||
|
||||
|
||||
#define LISTSZ 32 /* size of internal private LIST structure */
|
||||
|
||||
|
||||
/* .................... Function Prototypes .................... */
|
||||
|
||||
LISTID lcreat ( void * liststruct, int poolsize );
|
||||
|
||||
875
avrdude/main.c
875
avrdude/main.c
File diff suppressed because it is too large
Load Diff
400
avrdude/par.c
400
avrdude/par.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -37,8 +37,8 @@
|
||||
#include "avr.h"
|
||||
#include "pindefs.h"
|
||||
#include "pgm.h"
|
||||
#include "par.h"
|
||||
#include "ppi.h"
|
||||
#include "bitbang.h"
|
||||
|
||||
#define SLOW_TOGGLE 0
|
||||
|
||||
@@ -49,7 +49,7 @@ struct ppipins_t {
|
||||
int inverted;
|
||||
};
|
||||
|
||||
struct ppipins_t ppipins[] = {
|
||||
static struct ppipins_t pins[] = {
|
||||
{ 1, PPICTRL, 0x01, 1 },
|
||||
{ 2, PPIDATA, 0x01, 0 },
|
||||
{ 3, PPIDATA, 0x02, 0 },
|
||||
@@ -69,30 +69,70 @@ struct ppipins_t ppipins[] = {
|
||||
{ 17, PPICTRL, 0x08, 1 }
|
||||
};
|
||||
|
||||
#define NPINS (sizeof(ppipins)/sizeof(struct ppipins_t))
|
||||
#define NPINS (sizeof(pins)/sizeof(struct ppipins_t))
|
||||
|
||||
|
||||
extern char * progname;
|
||||
extern int do_cycles;
|
||||
extern int verbose;
|
||||
|
||||
int par_setpin(int fd, int pin, int value)
|
||||
{
|
||||
|
||||
pin &= PIN_MASK;
|
||||
static int par_setpin (int fd, int pin, int value);
|
||||
|
||||
static int par_getpin (int fd, int pin);
|
||||
|
||||
static int par_pulsepin (int fd, int pin);
|
||||
|
||||
|
||||
static int par_rdy_led (PROGRAMMER * pgm, int value);
|
||||
|
||||
static int par_err_led (PROGRAMMER * pgm, int value);
|
||||
|
||||
static int par_pgm_led (PROGRAMMER * pgm, int value);
|
||||
|
||||
static int par_vfy_led (PROGRAMMER * pgm, int value);
|
||||
|
||||
static int par_cmd (PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4]);
|
||||
|
||||
static int par_chip_erase (PROGRAMMER * pgm, AVRPART * p);
|
||||
|
||||
static int par_program_enable (PROGRAMMER * pgm, AVRPART * p);
|
||||
|
||||
static void par_powerup (PROGRAMMER * pgm);
|
||||
|
||||
static void par_powerdown (PROGRAMMER * pgm);
|
||||
|
||||
static int par_initialize (PROGRAMMER * pgm, AVRPART * p);
|
||||
|
||||
static int par_save (PROGRAMMER * pgm);
|
||||
|
||||
static void par_restore (PROGRAMMER * pgm);
|
||||
|
||||
static void par_disable (PROGRAMMER * pgm);
|
||||
|
||||
static void par_enable (PROGRAMMER * pgm);
|
||||
|
||||
static void par_open (PROGRAMMER * pgm, char * port);
|
||||
|
||||
static void par_close (PROGRAMMER * pgm);
|
||||
|
||||
|
||||
static int par_setpin(int fd, int pin, int value)
|
||||
{
|
||||
|
||||
if (pin < 1 || pin > 17)
|
||||
return -1;
|
||||
|
||||
pin--;
|
||||
|
||||
if (ppipins[pin].inverted)
|
||||
if (pins[pin].inverted)
|
||||
value = !value;
|
||||
|
||||
if (value)
|
||||
ppi_set(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
ppi_set(fd, pins[pin].reg, pins[pin].bit);
|
||||
else
|
||||
ppi_clr(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
ppi_clr(fd, pins[pin].reg, pins[pin].bit);
|
||||
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
@@ -102,30 +142,28 @@ int par_setpin(int fd, int pin, int value)
|
||||
}
|
||||
|
||||
|
||||
int par_getpin(int fd, int pin)
|
||||
static int par_getpin(int fd, int pin)
|
||||
{
|
||||
int value;
|
||||
|
||||
pin &= PIN_MASK;
|
||||
|
||||
if (pin < 1 || pin > 17)
|
||||
return -1;
|
||||
|
||||
pin--;
|
||||
|
||||
value = ppi_get(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
value = ppi_get(fd, pins[pin].reg, pins[pin].bit);
|
||||
|
||||
if (value)
|
||||
value = 1;
|
||||
|
||||
if (ppipins[pin].inverted)
|
||||
if (pins[pin].inverted)
|
||||
value = !value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
int par_highpulsepin(int fd, int pin)
|
||||
static int par_pulsepin(int fd, int pin)
|
||||
{
|
||||
|
||||
if (pin < 1 || pin > 17)
|
||||
@@ -133,11 +171,13 @@ int par_highpulsepin(int fd, int pin)
|
||||
|
||||
pin--;
|
||||
|
||||
ppi_set(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
ppi_toggle(fd, pins[pin].reg, pins[pin].bit);
|
||||
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
ppi_clr(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
|
||||
ppi_toggle(fd, pins[pin].reg, pins[pin].bit);
|
||||
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
@@ -148,17 +188,15 @@ int par_highpulsepin(int fd, int pin)
|
||||
|
||||
int par_getpinmask(int pin)
|
||||
{
|
||||
pin &= PIN_MASK;
|
||||
|
||||
if (pin < 1 || pin > 17)
|
||||
return -1;
|
||||
|
||||
return ppipins[pin-1].bit;
|
||||
return pins[pin-1].bit;
|
||||
}
|
||||
|
||||
|
||||
char vccpins_buf[64];
|
||||
char * vccpins_str(unsigned int pmask)
|
||||
static char vccpins_buf[64];
|
||||
static char * vccpins_str(unsigned int pmask)
|
||||
{
|
||||
unsigned int mask;
|
||||
int pin;
|
||||
@@ -180,10 +218,182 @@ char * vccpins_str(unsigned int pmask)
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* transmit and receive a byte of data to/from the AVR device
|
||||
*/
|
||||
static unsigned char par_txrx(PROGRAMMER * pgm, unsigned char byte)
|
||||
{
|
||||
int i;
|
||||
unsigned char r, b, rbyte;
|
||||
|
||||
rbyte = 0;
|
||||
for (i=0; i<8; i++) {
|
||||
b = (byte >> (7-i)) & 0x01;
|
||||
|
||||
/*
|
||||
* read the result bit (it is either valid from a previous clock
|
||||
* pulse or it is ignored in the current context)
|
||||
*/
|
||||
r = par_getpin(pgm->fd, pgm->pinno[PIN_AVR_MISO]);
|
||||
|
||||
/* set the data input line as desired */
|
||||
par_setpin(pgm->fd, pgm->pinno[PIN_AVR_MOSI], b);
|
||||
|
||||
/*
|
||||
* pulse the clock line, clocking in the MOSI data, and clocking out
|
||||
* the next result bit
|
||||
*/
|
||||
par_pulsepin(pgm->fd, pgm->pinno[PIN_AVR_SCK]);
|
||||
|
||||
rbyte = rbyte | (r << (7-i));
|
||||
}
|
||||
|
||||
return rbyte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int par_rdy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
par_setpin(pgm->fd, pgm->pinno[PIN_LED_RDY], !value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int par_err_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
par_setpin(pgm->fd, pgm->pinno[PIN_LED_ERR], !value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int par_pgm_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
par_setpin(pgm->fd, pgm->pinno[PIN_LED_PGM], !value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int par_vfy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
par_setpin(pgm->fd, pgm->pinno[PIN_LED_VFY], !value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* transmit an AVR device command and return the results; 'cmd' and
|
||||
* 'res' must point to at least a 4 byte data buffer
|
||||
*/
|
||||
static int par_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
res[i] = par_txrx(pgm, cmd[i]);
|
||||
}
|
||||
|
||||
if(verbose >= 2)
|
||||
{
|
||||
fprintf(stderr, "par_cmd(): [ ");
|
||||
for(i = 0; i < 4; i++)
|
||||
fprintf(stderr, "%02X ", cmd[i]);
|
||||
fprintf(stderr, "] [ ");
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
fprintf(stderr, "%02X ", res[i]);
|
||||
}
|
||||
fprintf(stderr, "]\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* issue the 'chip erase' command to the AVR device
|
||||
*/
|
||||
static int par_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
int cycles;
|
||||
int rc;
|
||||
|
||||
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
|
||||
fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
|
||||
p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = avr_get_cycle_count(pgm, p, &cycles);
|
||||
|
||||
/*
|
||||
* only print out the current cycle count if we aren't going to
|
||||
* display it below
|
||||
*/
|
||||
if (!do_cycles && ((rc >= 0) && (cycles != 0xffffffff))) {
|
||||
fprintf(stderr,
|
||||
"%s: current erase-rewrite cycle count is %d%s\n",
|
||||
progname, cycles,
|
||||
do_cycles ? "" : " (if being tracked)");
|
||||
}
|
||||
|
||||
pgm->pgm_led(pgm, ON);
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
|
||||
avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
usleep(p->chip_erase_delay);
|
||||
pgm->initialize(pgm, p);
|
||||
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
|
||||
if (do_cycles && (cycles != -1)) {
|
||||
if (cycles == 0x00ffff) {
|
||||
cycles = 0;
|
||||
}
|
||||
cycles++;
|
||||
fprintf(stderr, "%s: erase-rewrite cycle count is now %d\n",
|
||||
progname, cycles);
|
||||
avr_put_cycle_count(pgm, p, cycles);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* issue the 'program enable' command to the AVR device
|
||||
*/
|
||||
static int par_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
|
||||
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
|
||||
fprintf(stderr, "program enable instruction not defined for part \"%s\"\n",
|
||||
p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd);
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
|
||||
if (res[2] != cmd[1])
|
||||
return -2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* apply power to the AVR processor
|
||||
*/
|
||||
void par_powerup(PROGRAMMER * pgm)
|
||||
static void par_powerup(PROGRAMMER * pgm)
|
||||
{
|
||||
ppi_set(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_VCC]); /* power up */
|
||||
usleep(100000);
|
||||
@@ -193,17 +403,91 @@ void par_powerup(PROGRAMMER * pgm)
|
||||
/*
|
||||
* remove power from the AVR processor
|
||||
*/
|
||||
void par_powerdown(PROGRAMMER * pgm)
|
||||
static void par_powerdown(PROGRAMMER * pgm)
|
||||
{
|
||||
ppi_clr(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_VCC]); /* power down */
|
||||
}
|
||||
|
||||
void par_disable(PROGRAMMER * pgm)
|
||||
|
||||
/*
|
||||
* initialize the AVR device and prepare it to accept commands
|
||||
*/
|
||||
static int par_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
int rc;
|
||||
int tries;
|
||||
|
||||
pgm->powerup(pgm);
|
||||
usleep(20000);
|
||||
|
||||
par_setpin(pgm->fd, pgm->pinno[PIN_AVR_SCK], 0);
|
||||
par_setpin(pgm->fd, pgm->pinno[PIN_AVR_RESET], 0);
|
||||
usleep(20000);
|
||||
|
||||
par_pulsepin(pgm->fd, pgm->pinno[PIN_AVR_RESET]);
|
||||
|
||||
usleep(20000); /* 20 ms XXX should be a per-chip parameter */
|
||||
|
||||
/*
|
||||
* Enable programming mode. If we are programming an AT90S1200, we
|
||||
* can only issue the command and hope it worked. If we are using
|
||||
* one of the other chips, the chip will echo 0x53 when issuing the
|
||||
* third byte of the command. In this case, try up to 32 times in
|
||||
* order to possibly get back into sync with the chip if we are out
|
||||
* of sync.
|
||||
*/
|
||||
if (strcmp(p->desc, "AT90S1200")==0) {
|
||||
pgm->program_enable(pgm, p);
|
||||
}
|
||||
else {
|
||||
tries = 0;
|
||||
do {
|
||||
rc = pgm->program_enable(pgm, p);
|
||||
if ((rc == 0)||(rc == -1))
|
||||
break;
|
||||
par_pulsepin(pgm->fd, pgm->pinno[p->retry_pulse/*PIN_AVR_SCK*/]);
|
||||
tries++;
|
||||
} while (tries < 65);
|
||||
|
||||
/*
|
||||
* can't sync with the device, maybe it's not attached?
|
||||
*/
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: AVR device not responding\n", progname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int par_save(PROGRAMMER * pgm)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ppi_getall(pgm->fd, PPIDATA);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: error reading status of ppi data port\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pgm->ppidata = rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void par_restore(PROGRAMMER * pgm)
|
||||
{
|
||||
ppi_setall(pgm->fd, PPIDATA, pgm->ppidata);
|
||||
}
|
||||
|
||||
static void par_disable(PROGRAMMER * pgm)
|
||||
{
|
||||
ppi_set(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_BUFF]);
|
||||
}
|
||||
|
||||
void par_enable(PROGRAMMER * pgm)
|
||||
static void par_enable(PROGRAMMER * pgm)
|
||||
{
|
||||
/*
|
||||
* Prepare to start talking to the connected device - pull reset low
|
||||
@@ -225,10 +509,9 @@ void par_enable(PROGRAMMER * pgm)
|
||||
ppi_clr(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_BUFF]);
|
||||
}
|
||||
|
||||
int par_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
int rc;
|
||||
|
||||
static void par_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
pgm->fd = ppi_open(port);
|
||||
if (pgm->fd < 0) {
|
||||
fprintf(stderr, "%s: failed to open parallel port \"%s\"\n\n",
|
||||
@@ -237,51 +520,25 @@ int par_open(PROGRAMMER * pgm, char * port)
|
||||
}
|
||||
|
||||
ppi_claim(pgm);
|
||||
|
||||
/*
|
||||
* save pin values, so they can be restored when device is closed
|
||||
*/
|
||||
rc = ppi_getall(pgm->fd, PPIDATA);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: error reading status of ppi data port\n", progname);
|
||||
return -1;
|
||||
}
|
||||
pgm->ppidata = rc;
|
||||
|
||||
rc = ppi_getall(pgm->fd, PPICTRL);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: error reading status of ppi ctrl port\n", progname);
|
||||
return -1;
|
||||
}
|
||||
pgm->ppictrl = rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void par_close(PROGRAMMER * pgm)
|
||||
static void par_close(PROGRAMMER * pgm)
|
||||
{
|
||||
/*
|
||||
* Restore pin values before closing,
|
||||
* but ensure that buffers are turned off.
|
||||
*/
|
||||
pgm->ppidata |= pgm->pinno[PPI_AVR_BUFF];
|
||||
ppi_setall(pgm->fd, PPIDATA, pgm->ppidata);
|
||||
ppi_setall(pgm->fd, PPICTRL, pgm->ppictrl);
|
||||
|
||||
ppi_release(pgm);
|
||||
|
||||
ppi_close(pgm->fd);
|
||||
pgm->fd = -1;
|
||||
}
|
||||
|
||||
void par_display(PROGRAMMER * pgm, char * p)
|
||||
|
||||
static void par_display(PROGRAMMER * pgm, char * p)
|
||||
{
|
||||
char vccpins[64];
|
||||
char buffpins[64];
|
||||
|
||||
if (pgm->pinno[PPI_AVR_VCC]) {
|
||||
snprintf(vccpins, sizeof(vccpins), " = pins %s",
|
||||
snprintf(vccpins, sizeof(vccpins), " = pins %s",
|
||||
vccpins_str(pgm->pinno[PPI_AVR_VCC]));
|
||||
}
|
||||
else {
|
||||
@@ -325,22 +582,23 @@ void par_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
strcpy(pgm->type, "PPI");
|
||||
|
||||
pgm->rdy_led = bitbang_rdy_led;
|
||||
pgm->err_led = bitbang_err_led;
|
||||
pgm->pgm_led = bitbang_pgm_led;
|
||||
pgm->vfy_led = bitbang_vfy_led;
|
||||
pgm->initialize = bitbang_initialize;
|
||||
pgm->rdy_led = par_rdy_led;
|
||||
pgm->err_led = par_err_led;
|
||||
pgm->pgm_led = par_pgm_led;
|
||||
pgm->vfy_led = par_vfy_led;
|
||||
pgm->initialize = par_initialize;
|
||||
pgm->display = par_display;
|
||||
pgm->save = par_save;
|
||||
pgm->restore = par_restore;
|
||||
pgm->enable = par_enable;
|
||||
pgm->disable = par_disable;
|
||||
pgm->powerup = par_powerup;
|
||||
pgm->powerdown = par_powerdown;
|
||||
pgm->program_enable = bitbang_program_enable;
|
||||
pgm->chip_erase = bitbang_chip_erase;
|
||||
pgm->cmd = bitbang_cmd;
|
||||
pgm->program_enable = par_program_enable;
|
||||
pgm->chip_erase = par_chip_erase;
|
||||
pgm->cmd = par_cmd;
|
||||
pgm->open = par_open;
|
||||
pgm->close = par_close;
|
||||
|
||||
/* this is a parallel port bitbang device */
|
||||
pgm->flag = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -22,12 +22,11 @@
|
||||
#ifndef __par_h__
|
||||
#define __par_h__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
void par_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
int par_getpinmask(int pin);
|
||||
int par_setpin(int fd, int pin, int value);
|
||||
int par_getpin(int fd, int pin);
|
||||
int par_highpulsepin(int fd, int pin);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2002, 2003 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
|
||||
@@ -29,35 +29,13 @@
|
||||
|
||||
extern char * progname;
|
||||
|
||||
static int pgm_default_2 (struct programmer_t *, AVRPART *);
|
||||
static void pgm_default_4 (struct programmer_t *);
|
||||
static int pgm_default_5 (struct programmer_t *, unsigned char cmd[4],
|
||||
int pgm_default_1 (struct programmer_t *, int);
|
||||
int pgm_default_2 (struct programmer_t *, AVRPART *);
|
||||
int pgm_default_3 (struct programmer_t *);
|
||||
void pgm_default_4 (struct programmer_t *);
|
||||
int pgm_default_5 (struct programmer_t *, unsigned char cmd[4],
|
||||
unsigned char res[4]);
|
||||
static void pgm_default_6 (struct programmer_t *, char *);
|
||||
|
||||
|
||||
static int pgm_default_open (struct programmer_t *pgm, char * name)
|
||||
{
|
||||
fprintf (stderr, "\n%s: Fatal error: Programmer does not support open()",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int pgm_default_led (struct programmer_t * pgm, int value)
|
||||
{
|
||||
/*
|
||||
* If programmer has no LEDs, just do nothing.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void pgm_default_powerup_powerdown (struct programmer_t * pgm)
|
||||
{
|
||||
/*
|
||||
* If programmer does not support powerup/down, just do nothing.
|
||||
*/
|
||||
}
|
||||
void pgm_default_6 (struct programmer_t *, char *);
|
||||
|
||||
|
||||
PROGRAMMER * pgm_new(void)
|
||||
@@ -79,7 +57,6 @@ PROGRAMMER * pgm_new(void)
|
||||
pgm->type[0] = 0;
|
||||
pgm->config_file[0] = 0;
|
||||
pgm->lineno = 0;
|
||||
pgm->baudrate = 0;
|
||||
|
||||
for (i=0; i<N_PINS; i++)
|
||||
pgm->pinno[i] = 0;
|
||||
@@ -88,28 +65,24 @@ PROGRAMMER * pgm_new(void)
|
||||
* mandatory functions - these are called without checking to see
|
||||
* whether they are assigned or not
|
||||
*/
|
||||
pgm->rdy_led = pgm_default_1;
|
||||
pgm->err_led = pgm_default_1;
|
||||
pgm->pgm_led = pgm_default_1;
|
||||
pgm->vfy_led = pgm_default_1;
|
||||
pgm->initialize = pgm_default_2;
|
||||
pgm->display = pgm_default_6;
|
||||
pgm->save = pgm_default_3;
|
||||
pgm->restore = pgm_default_4;
|
||||
pgm->enable = pgm_default_4;
|
||||
pgm->disable = pgm_default_4;
|
||||
pgm->powerup = pgm_default_powerup_powerdown;
|
||||
pgm->powerdown = pgm_default_powerup_powerdown;
|
||||
pgm->powerup = pgm_default_4;
|
||||
pgm->powerdown = pgm_default_4;
|
||||
pgm->program_enable = pgm_default_2;
|
||||
pgm->chip_erase = pgm_default_2;
|
||||
pgm->cmd = pgm_default_5;
|
||||
pgm->open = pgm_default_open;
|
||||
pgm->open = pgm_default_6;
|
||||
pgm->close = pgm_default_4;
|
||||
|
||||
/*
|
||||
* predefined functions - these functions have a valid default
|
||||
* implementation. Hence, they don't need to be defined in
|
||||
* the programmer.
|
||||
*/
|
||||
pgm->rdy_led = pgm_default_led;
|
||||
pgm->err_led = pgm_default_led;
|
||||
pgm->pgm_led = pgm_default_led;
|
||||
pgm->vfy_led = pgm_default_led;
|
||||
|
||||
/*
|
||||
* optional functions - these are checked to make sure they are
|
||||
* assigned before they are called
|
||||
@@ -128,31 +101,43 @@ PROGRAMMER * pgm_new(void)
|
||||
}
|
||||
|
||||
|
||||
static void pgm_default(void)
|
||||
void pgm_default(void)
|
||||
{
|
||||
fprintf(stderr, "%s: programmer operation not supported\n", progname);
|
||||
}
|
||||
|
||||
|
||||
static int pgm_default_2 (struct programmer_t * pgm, AVRPART * p)
|
||||
int pgm_default_1 (struct programmer_t * pgm, int value)
|
||||
{
|
||||
pgm_default();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void pgm_default_4 (struct programmer_t * pgm)
|
||||
int pgm_default_2 (struct programmer_t * pgm, AVRPART * p)
|
||||
{
|
||||
pgm_default();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pgm_default_3 (struct programmer_t * pgm)
|
||||
{
|
||||
pgm_default();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pgm_default_4 (struct programmer_t * pgm)
|
||||
{
|
||||
pgm_default();
|
||||
}
|
||||
|
||||
static int pgm_default_5 (struct programmer_t * pgm, unsigned char cmd[4],
|
||||
int pgm_default_5 (struct programmer_t * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
pgm_default();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void pgm_default_6 (struct programmer_t * pgm, char * p)
|
||||
void pgm_default_6 (struct programmer_t * pgm, char * p)
|
||||
{
|
||||
pgm_default();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2002, 2003 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
|
||||
@@ -35,9 +35,6 @@
|
||||
#define PGM_DESCLEN 80
|
||||
#define PGM_PORTLEN PATH_MAX
|
||||
#define PGM_TYPELEN 32
|
||||
|
||||
extern LISTID programmers;
|
||||
|
||||
typedef struct programmer_t {
|
||||
LISTID id;
|
||||
char desc[PGM_DESCLEN];
|
||||
@@ -45,9 +42,6 @@ typedef struct programmer_t {
|
||||
char port[PGM_PORTLEN];
|
||||
unsigned int pinno[N_PINS];
|
||||
int ppidata;
|
||||
int ppictrl;
|
||||
int baudrate;
|
||||
double bitclock; /* JTAG ICE clock period in microseconds */
|
||||
int fd;
|
||||
int page_size; /* page size if the programmer supports paged write/load */
|
||||
int (*rdy_led) (struct programmer_t * pgm, int value);
|
||||
@@ -56,6 +50,8 @@ typedef struct programmer_t {
|
||||
int (*vfy_led) (struct programmer_t * pgm, int value);
|
||||
int (*initialize) (struct programmer_t * pgm, AVRPART * p);
|
||||
void (*display) (struct programmer_t * pgm, char * p);
|
||||
int (*save) (struct programmer_t * pgm);
|
||||
void (*restore) (struct programmer_t * pgm);
|
||||
void (*enable) (struct programmer_t * pgm);
|
||||
void (*disable) (struct programmer_t * pgm);
|
||||
void (*powerup) (struct programmer_t * pgm);
|
||||
@@ -64,7 +60,7 @@ typedef struct programmer_t {
|
||||
int (*chip_erase) (struct programmer_t * pgm, AVRPART * p);
|
||||
int (*cmd) (struct programmer_t * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4]);
|
||||
int (*open) (struct programmer_t * pgm, char * port);
|
||||
void (*open) (struct programmer_t * pgm, char * port);
|
||||
void (*close) (struct programmer_t * pgm);
|
||||
int (*paged_write) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes);
|
||||
@@ -80,41 +76,11 @@ typedef struct programmer_t {
|
||||
int (*set_vtarget) (struct programmer_t * pgm, double v);
|
||||
int (*set_varef) (struct programmer_t * pgm, double v);
|
||||
int (*set_fosc) (struct programmer_t * pgm, double v);
|
||||
int (*set_sck_period) (struct programmer_t * pgm, double v);
|
||||
char config_file[PATH_MAX]; /* config file where defined */
|
||||
int lineno; /* config file line number */
|
||||
char flag; /* for private use of the programmer */
|
||||
} PROGRAMMER;
|
||||
|
||||
|
||||
PROGRAMMER * pgm_new(void);
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* usleep replacements */
|
||||
/* sleep Windows in ms, Unix usleep in us
|
||||
#define usleep(us) Sleep((us)<20000?20:us/1000)
|
||||
#define usleep(us) Sleep(us/1000)
|
||||
#define ANTIWARP 3
|
||||
#define usleep(us) Sleep(us/1000*ANTIWARP)
|
||||
*/
|
||||
void usleep(unsigned long us);
|
||||
|
||||
void gettimeofday(struct timeval*, void*z);
|
||||
|
||||
#define rindex strrchr
|
||||
|
||||
#endif /* __win32native_h */
|
||||
|
||||
|
||||
#if !defined(ppi_claim)
|
||||
# define ppi_claim(pgm)
|
||||
#endif
|
||||
|
||||
#if !defined(ppi_release)
|
||||
# define ppi_release(pgm)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -35,8 +35,6 @@ enum {
|
||||
PIN_LED_VFY,
|
||||
N_PINS
|
||||
};
|
||||
#define PIN_INVERSE 0x80 /* flag for inverted pin in serbb */
|
||||
#define PIN_MASK 0x7f
|
||||
|
||||
#define LED_ON(fd,pin) ppi_setpin(fd,pin,0)
|
||||
#define LED_OFF(fd,pin) ppi_setpin(fd,pin,1)
|
||||
|
||||
181
avrdude/ppi.c
181
avrdude/ppi.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -43,33 +43,24 @@
|
||||
|
||||
extern char * progname;
|
||||
|
||||
enum {
|
||||
PPI_READ,
|
||||
PPI_WRITE,
|
||||
PPI_SHADOWREAD
|
||||
};
|
||||
|
||||
int ppi_shadow_access(int fd, int reg, unsigned char *v, unsigned char action)
|
||||
/*
|
||||
* set 'get' and 'set' appropriately for subsequent passage to ioctl()
|
||||
* to get/set the specified PPI registers.
|
||||
*/
|
||||
static int ppi_getops(int reg, unsigned long * get, unsigned long * set)
|
||||
{
|
||||
static unsigned char shadow[3];
|
||||
int shadow_num;
|
||||
unsigned long set, get;
|
||||
|
||||
switch (reg) {
|
||||
case PPIDATA:
|
||||
set = PPISDATA;
|
||||
get = PPIGDATA;
|
||||
shadow_num = 0;
|
||||
*set = PPISDATA;
|
||||
*get = PPIGDATA;
|
||||
break;
|
||||
case PPICTRL:
|
||||
set = PPISCTRL;
|
||||
get = PPIGCTRL;
|
||||
shadow_num = 1;
|
||||
*set = PPISCTRL;
|
||||
*get = PPIGCTRL;
|
||||
break;
|
||||
case PPISTATUS:
|
||||
set = PPISSTATUS;
|
||||
get = PPIGSTATUS;
|
||||
shadow_num = 2;
|
||||
*set = PPISSTATUS;
|
||||
*get = PPIGSTATUS;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: avr_set(): invalid register=%d\n",
|
||||
@@ -78,37 +69,27 @@ int ppi_shadow_access(int fd, int reg, unsigned char *v, unsigned char action)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case PPI_SHADOWREAD:
|
||||
*v = shadow[shadow_num];
|
||||
break;
|
||||
case PPI_READ:
|
||||
ioctl(fd, get, v);
|
||||
shadow[shadow_num]=*v;
|
||||
break;
|
||||
case PPI_WRITE:
|
||||
shadow[shadow_num]=*v;
|
||||
ioctl(fd, set, v);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_set(int fd, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
unsigned long get, set;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD);
|
||||
v |= bit;
|
||||
rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE);
|
||||
|
||||
rc = ppi_getops(reg, &get, &set);
|
||||
if (rc)
|
||||
return -1;
|
||||
|
||||
ioctl(fd, get, &v);
|
||||
v |= bit;
|
||||
ioctl(fd, set, &v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -119,15 +100,17 @@ int ppi_set(int fd, int reg, int bit)
|
||||
int ppi_clr(int fd, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
unsigned long get, set;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD);
|
||||
v &= ~bit;
|
||||
rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE);
|
||||
|
||||
rc = ppi_getops(reg, &get, &set);
|
||||
if (rc)
|
||||
return -1;
|
||||
|
||||
ioctl(fd, get, &v);
|
||||
v &= ~bit;
|
||||
ioctl(fd, set, &v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -138,14 +121,16 @@ int ppi_clr(int fd, int reg, int bit)
|
||||
int ppi_get(int fd, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
unsigned long get, set;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_READ);
|
||||
v &= bit;
|
||||
|
||||
rc = ppi_getops(reg, &get, &set);
|
||||
if (rc)
|
||||
return -1;
|
||||
|
||||
ioctl(fd, get, &v);
|
||||
v &= bit;
|
||||
|
||||
return v; /* v == bit */
|
||||
}
|
||||
|
||||
@@ -155,15 +140,17 @@ int ppi_get(int fd, int reg, int bit)
|
||||
int ppi_toggle(int fd, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
unsigned long get, set;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD);
|
||||
v ^= bit;
|
||||
rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE);
|
||||
|
||||
rc = ppi_getops(reg, &get, &set);
|
||||
if (rc)
|
||||
return -1;
|
||||
|
||||
ioctl(fd, get, &v);
|
||||
v ^= bit;
|
||||
ioctl(fd, set, &v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -174,14 +161,16 @@ int ppi_toggle(int fd, int reg, int bit)
|
||||
int ppi_getall(int fd, int reg)
|
||||
{
|
||||
unsigned char v;
|
||||
unsigned long get, set;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_READ);
|
||||
|
||||
rc = ppi_getops(reg, &get, &set);
|
||||
if (rc)
|
||||
return -1;
|
||||
|
||||
return v; /* v == bit */
|
||||
ioctl(fd, get, &v);
|
||||
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -190,14 +179,16 @@ int ppi_getall(int fd, int reg)
|
||||
int ppi_setall(int fd, int reg, int val)
|
||||
{
|
||||
unsigned char v;
|
||||
unsigned long get, set;
|
||||
int rc;
|
||||
|
||||
v = val;
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_WRITE);
|
||||
|
||||
rc = ppi_getops(reg, &get, &set);
|
||||
if (rc)
|
||||
return -1;
|
||||
|
||||
v = val;
|
||||
ioctl(fd, set, &v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -205,7 +196,6 @@ int ppi_setall(int fd, int reg, int val)
|
||||
int ppi_open(char * port)
|
||||
{
|
||||
int fd;
|
||||
unsigned char v;
|
||||
|
||||
fd = open(port, O_RDWR);
|
||||
if (fd < 0) {
|
||||
@@ -214,14 +204,6 @@ int ppi_open(char * port)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize shadow registers
|
||||
*/
|
||||
|
||||
ppi_shadow_access (fd, PPIDATA, &v, PPI_READ);
|
||||
ppi_shadow_access (fd, PPICTRL, &v, PPI_READ);
|
||||
ppi_shadow_access (fd, PPISTATUS, &v, PPI_READ);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -232,75 +214,4 @@ void ppi_close(int fd)
|
||||
}
|
||||
|
||||
|
||||
#elif defined(__POWERPC__) && defined(__APPLE__)
|
||||
|
||||
int ppi_shadow_access(int fd, int reg, unsigned char *v, unsigned char action)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* set the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_set(int fd, int reg, int bit)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* clear the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_clr(int fd, int reg, int bit)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_get(int fd, int reg, int bit)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* toggle the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_toggle(int fd, int reg, int bit)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get all bits of the specified register.
|
||||
*/
|
||||
int ppi_getall(int fd, int reg)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* set all bits of the specified register to val.
|
||||
*/
|
||||
int ppi_setall(int fd, int reg, int val)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int ppi_open(char * port)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void ppi_close(int fd)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -22,6 +22,8 @@
|
||||
#ifndef __ppi_h__
|
||||
#define __ppi_h__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/*
|
||||
* PPI registers
|
||||
*/
|
||||
@@ -32,6 +34,13 @@ enum {
|
||||
};
|
||||
|
||||
|
||||
#if !defined(ppi_claim)
|
||||
# define ppi_claim(pgm)
|
||||
#endif
|
||||
|
||||
#if !defined(ppi_release)
|
||||
# define ppi_release(pgm)
|
||||
#endif
|
||||
|
||||
int ppi_get (int fd, int reg, int bit);
|
||||
|
||||
|
||||
134
avrdude/ppiwin.c
134
avrdude/ppiwin.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003, 2004 Eric B. Weddington <ericw@evcohs.com>
|
||||
* Copyright (C) 2003 Eric B. Weddington <eric@ecentral.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
|
||||
@@ -17,7 +17,6 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
This is the parallel port interface for Windows built using Cygwin.
|
||||
@@ -31,7 +30,7 @@ reg = register as defined in an enum in ppi.h. This must be converted
|
||||
|
||||
|
||||
|
||||
#if defined (WIN32NATIVE)
|
||||
#if defined(__CYGWIN__)
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -41,9 +40,11 @@ reg = register as defined in an enum in ppi.h. This must be converted
|
||||
#include <unistd.h>
|
||||
#include <windows.h>
|
||||
#include <sys/time.h>
|
||||
#include <windows.h>
|
||||
#include <w32api/windows.h>
|
||||
#include "ppi.h"
|
||||
|
||||
|
||||
|
||||
extern char *progname;
|
||||
|
||||
|
||||
@@ -316,73 +317,80 @@ static void outb(unsigned char value, unsigned short port)
|
||||
return;
|
||||
}
|
||||
|
||||
void gettimeofday(struct timeval*tv, void*z){
|
||||
// i've found only ms resolution, avrdude expects us
|
||||
/* These two functions usecPerfDelay and usleep are based on code from the
|
||||
* uisp project and are a replacement for the cygwin usleep library
|
||||
* function which seems to not delay for the correct time
|
||||
*/
|
||||
|
||||
SYSTEMTIME st;
|
||||
GetSystemTime(&st);
|
||||
|
||||
tv->tv_sec=(long)(st.wSecond+st.wMinute*60+st.wHour*3600);
|
||||
tv->tv_usec=(long)(st.wMilliseconds*1000);
|
||||
}
|
||||
|
||||
// #define W32USLEEPDBG
|
||||
|
||||
#ifdef W32USLEEPDBG
|
||||
|
||||
# define DEBUG_QueryPerformanceCounter(arg) QueryPerformanceCounter(arg)
|
||||
# define DEBUG_DisplayTimingInfo(start, stop, freq, us, has_highperf) \
|
||||
do { \
|
||||
unsigned long dt; \
|
||||
dt = (unsigned long)((stop.QuadPart - start.QuadPart) * 1000 * 1000 \
|
||||
/ freq.QuadPart); \
|
||||
fprintf(stderr, \
|
||||
"hpt:%i usleep usec:%lu sleep msec:%lu timed usec:%lu\n", \
|
||||
has_highperf, us, ((us + 999) / 1000), dt); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
# define DEBUG_QueryPerformanceCounter(arg)
|
||||
# define DEBUG_DisplayTimingInfo(start, stop, freq, us, has_highperf)
|
||||
|
||||
#endif
|
||||
|
||||
void usleep(unsigned long us)
|
||||
BOOL usecPerfDelay(long t)
|
||||
{
|
||||
int has_highperf;
|
||||
LARGE_INTEGER freq,start,stop,loopend;
|
||||
static BOOL perf_counter_checked = FALSE;
|
||||
static BOOL use_perf_counter = FALSE;
|
||||
static LARGE_INTEGER freq ;
|
||||
|
||||
// workaround: although usleep is very precise if using
|
||||
// high-performance-timers there are sometimes problems with
|
||||
// verify - increasing the delay helps sometimes but not
|
||||
// realiably. There must be some other problem. Maybe just
|
||||
// with my test-hardware maybe in the code-base.
|
||||
//// us=(unsigned long) (us*1.5);
|
||||
if (! perf_counter_checked) {
|
||||
if (QueryPerformanceFrequency(&freq)){
|
||||
use_perf_counter = TRUE;
|
||||
}
|
||||
perf_counter_checked = TRUE;
|
||||
}
|
||||
|
||||
has_highperf=QueryPerformanceFrequency(&freq);
|
||||
if (! use_perf_counter)
|
||||
return FALSE;
|
||||
|
||||
//has_highperf=0; // debug
|
||||
else {
|
||||
LARGE_INTEGER now;
|
||||
LARGE_INTEGER finish;
|
||||
QueryPerformanceCounter(&now);
|
||||
finish.QuadPart = now.QuadPart + (t * freq.QuadPart) / 1000000;
|
||||
do {
|
||||
QueryPerformanceCounter(&now);
|
||||
} while (now.QuadPart < finish.QuadPart);
|
||||
|
||||
if (has_highperf) {
|
||||
QueryPerformanceCounter(&start);
|
||||
loopend.QuadPart=start.QuadPart+freq.QuadPart*us/(1000*1000);
|
||||
do {
|
||||
QueryPerformanceCounter(&stop);
|
||||
} while (stop.QuadPart<=loopend.QuadPart);
|
||||
}
|
||||
else {
|
||||
DEBUG_QueryPerformanceCounter(&start);
|
||||
|
||||
Sleep(1);
|
||||
Sleep( (DWORD)((us+999)/1000) );
|
||||
|
||||
DEBUG_QueryPerformanceCounter(&stop);
|
||||
}
|
||||
|
||||
DEBUG_DisplayTimingInfo(start, stop, freq, us, has_highperf);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
WARNING WARNING This function replaces the standard usleep() library function
|
||||
because it doesn't appear to delay for the correct time.
|
||||
*/
|
||||
|
||||
#ifndef MIN_SLEEP_USEC
|
||||
#define MIN_SLEEP_USEC 20000
|
||||
#endif
|
||||
|
||||
unsigned usleep( unsigned int uSeconds )
|
||||
{
|
||||
struct timeval t1, t2;
|
||||
struct timespec nanoDelay ;
|
||||
|
||||
if (usecPerfDelay(uSeconds))
|
||||
return(0);
|
||||
|
||||
gettimeofday(&t1, NULL);
|
||||
|
||||
if( uSeconds > MIN_SLEEP_USEC )
|
||||
{
|
||||
nanoDelay.tv_sec = uSeconds / 1000000UL;
|
||||
nanoDelay.tv_nsec = (uSeconds / 1000000UL) * 1000 ;
|
||||
nanosleep( &nanoDelay, NULL ) ;
|
||||
}
|
||||
|
||||
/* loop for the remaining time */
|
||||
t2.tv_sec = uSeconds / 1000000UL;
|
||||
t2.tv_usec = uSeconds % 1000000UL;
|
||||
|
||||
timeradd(&t1, &t2, &t1);
|
||||
|
||||
do {
|
||||
gettimeofday(&t2, NULL);
|
||||
} while (timercmp(&t2, &t1, <));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* avrdude is Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
*
|
||||
* This file: Copyright (C) 2005 Colin O'Flynn <coflynn@newae.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
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ac_cfg.h"
|
||||
#include "avr.h"
|
||||
#include "pgm.h"
|
||||
#include "safemode.h"
|
||||
|
||||
/* This value from ac_cfg.h */
|
||||
char * progname = PACKAGE_NAME;
|
||||
|
||||
/*
|
||||
* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or
|
||||
* "efuse") and verifies it. Will try up to tries amount of times
|
||||
* before giving up
|
||||
*/
|
||||
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm,
|
||||
AVRPART * p, int tries, int verbose)
|
||||
{
|
||||
AVRMEM * m;
|
||||
unsigned char fuseread;
|
||||
int returnvalue = -1;
|
||||
|
||||
m = avr_locate_mem(p, fusename);
|
||||
if (m == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Keep trying to write then read back the fuse values */
|
||||
while (tries > 0) {
|
||||
avr_write_byte(pgm, p, m, 0, fuse);
|
||||
avr_read_byte(pgm, p, m, 0, &fuseread);
|
||||
|
||||
/* Report information to user if needed */
|
||||
if (verbose > 0) {
|
||||
fprintf(stderr,
|
||||
"%s: safemode: Wrote %s to %x, read as %x. %d attempts left\n",
|
||||
progname, fusename, fuse, fuseread, tries-1);
|
||||
}
|
||||
|
||||
/* If fuse wrote OK, no need to keep going */
|
||||
if (fuse == fuseread) {
|
||||
tries = 0;
|
||||
returnvalue = 0;
|
||||
}
|
||||
tries--;
|
||||
}
|
||||
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads the fuses three times, checking that all readings are the
|
||||
* same. This will ensure that the before values aren't in error!
|
||||
*/
|
||||
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse,
|
||||
unsigned char * efuse, unsigned char * fuse,
|
||||
PROGRAMMER * pgm, AVRPART * p, int verbose)
|
||||
{
|
||||
|
||||
unsigned char value;
|
||||
unsigned char fusegood = 0;
|
||||
unsigned char safemode_lfuse;
|
||||
unsigned char safemode_hfuse;
|
||||
unsigned char safemode_efuse;
|
||||
unsigned char safemode_fuse;
|
||||
AVRMEM * m;
|
||||
|
||||
safemode_lfuse = *lfuse;
|
||||
safemode_hfuse = *hfuse;
|
||||
safemode_efuse = *efuse;
|
||||
safemode_fuse = *fuse;
|
||||
|
||||
|
||||
/* Read fuse three times */
|
||||
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||
to generate a verify error */
|
||||
m = avr_locate_mem(p, "fuse");
|
||||
if (m != NULL) {
|
||||
fusegood = 0; /* By default fuse is a failure */
|
||||
avr_read_byte(pgm, p, m, 0, &safemode_fuse);
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (value == safemode_fuse) {
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (value == safemode_fuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fusegood == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: safemode: Verify error - unable to read fuse properly. "
|
||||
"Programmer may not be reliable.\n", progname);
|
||||
return -1;
|
||||
}
|
||||
else if ((fusegood == 1) && (verbose > 0)) {
|
||||
printf("%s: safemode: fuse reads as %X\n", progname, safemode_fuse);
|
||||
}
|
||||
|
||||
|
||||
/* Read lfuse three times */
|
||||
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||
to generate a verify error */
|
||||
m = avr_locate_mem(p, "lfuse");
|
||||
if (m != NULL) {
|
||||
fusegood = 0; /* By default fuse is a failure */
|
||||
avr_read_byte(pgm, p, m, 0, &safemode_lfuse);
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (value == safemode_lfuse) {
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (value == safemode_lfuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fusegood == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: safemode: Verify error - unable to read lfuse properly. "
|
||||
"Programmer may not be reliable.\n", progname);
|
||||
return -1;
|
||||
}
|
||||
else if ((fusegood == 1) && (verbose > 0)) {
|
||||
printf("%s: safemode: lfuse reads as %X\n", progname, safemode_lfuse);
|
||||
}
|
||||
|
||||
/* Read hfuse three times */
|
||||
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||
to generate a verify error */
|
||||
m = avr_locate_mem(p, "hfuse");
|
||||
if (m != NULL) {
|
||||
fusegood = 0; /* By default fuse is a failure */
|
||||
avr_read_byte(pgm, p, m, 0, &safemode_hfuse);
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (value == safemode_hfuse) {
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (value == safemode_hfuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fusegood == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: safemode: Verify error - unable to read hfuse properly. "
|
||||
"Programmer may not be reliable.\n", progname);
|
||||
return -2;
|
||||
}
|
||||
else if ((fusegood == 1) && (verbose > 0)){
|
||||
printf("%s: safemode: hfuse reads as %X\n", progname, safemode_hfuse);
|
||||
}
|
||||
|
||||
/* Read efuse three times */
|
||||
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||
to generate a verify error */
|
||||
m = avr_locate_mem(p, "efuse");
|
||||
if (m != NULL) {
|
||||
fusegood = 0; /* By default fuse is a failure */
|
||||
avr_read_byte(pgm, p, m, 0, &safemode_efuse);
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (value == safemode_efuse) {
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (value == safemode_efuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fusegood == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: safemode: Verify error - unable to read efuse properly. "
|
||||
"Programmer may not be reliable.\n", progname);
|
||||
return -3;
|
||||
}
|
||||
else if ((fusegood == 1) && (verbose > 0)) {
|
||||
printf("%s: safemode: efuse reads as %X\n", progname, safemode_efuse);
|
||||
}
|
||||
|
||||
*lfuse = safemode_lfuse;
|
||||
*hfuse = safemode_hfuse;
|
||||
*efuse = safemode_efuse;
|
||||
*fuse = safemode_fuse;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine will store the current values pointed to by lfuse,
|
||||
* hfuse, and efuse into an internal buffer in this routine when save
|
||||
* is set to 1. When save is 0 (or not 1 really) it will copy the
|
||||
* values from the internal buffer into the locations pointed to be
|
||||
* lfuse, hfuse, and efuse. This allows you to change the fuse bits if
|
||||
* needed from another routine (ie: have it so if user requests fuse
|
||||
* bits are changed, the requested value is now verified
|
||||
*/
|
||||
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse,
|
||||
unsigned char * efuse, unsigned char * fuse)
|
||||
{
|
||||
static unsigned char safemode_lfuse = 0xff;
|
||||
static unsigned char safemode_hfuse = 0xff;
|
||||
static unsigned char safemode_efuse = 0xff;
|
||||
static unsigned char safemode_fuse = 0xff;
|
||||
|
||||
switch (save) {
|
||||
|
||||
/* Save the fuses as safemode setting */
|
||||
case 1:
|
||||
safemode_lfuse = *lfuse;
|
||||
safemode_hfuse = *hfuse;
|
||||
safemode_efuse = *efuse;
|
||||
safemode_fuse = *fuse;
|
||||
|
||||
break;
|
||||
/* Read back the fuses */
|
||||
default:
|
||||
*lfuse = safemode_lfuse;
|
||||
*hfuse = safemode_hfuse;
|
||||
*efuse = safemode_efuse;
|
||||
*fuse = safemode_fuse;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* avrdude is Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
*
|
||||
* This file: Copyright (C) 2005 Colin O'Flynn <coflynn@newae.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
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __safemode_h__
|
||||
#define __safemode_h__
|
||||
|
||||
/* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or "efuse") and verifies it. Will try up to tries
|
||||
amount of times before giving up */
|
||||
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries, int verbose);
|
||||
|
||||
/* Reads the fuses three times, checking that all readings are the same. This will ensure that the before values aren't in error! */
|
||||
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse, PROGRAMMER * pgm, AVRPART * p, int verbose);
|
||||
|
||||
/* This routine will store the current values pointed to by lfuse, hfuse, and efuse into an internal buffer in this routine
|
||||
when save is set to 1. When save is 0 (or not 1 really) it will copy the values from the internal buffer into the locations
|
||||
pointed to be lfuse, hfuse, and efuse. This allows you to change the fuse bits if needed from another routine (ie: have it so
|
||||
if user requests fuse bits are changed, the requested value is now verified */
|
||||
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse);
|
||||
|
||||
#endif //__safemode_h
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003 Theodore A. Roth <troth@openavr.org>
|
||||
*
|
||||
* 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
|
||||
@@ -23,9 +23,6 @@
|
||||
* Posix serial interface for avrdude.
|
||||
*/
|
||||
|
||||
#if !defined(WIN32NATIVE)
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -38,13 +35,9 @@
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
extern char *progname;
|
||||
extern int verbose;
|
||||
|
||||
long serial_recv_timeout = 5000; /* ms */
|
||||
|
||||
struct baud_mapping {
|
||||
long baud;
|
||||
speed_t speed;
|
||||
@@ -80,7 +73,7 @@ static speed_t serial_baud_lookup(long baud)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int ser_setspeed(int fd, long baud)
|
||||
static int serial_setattr(int fd, long baud)
|
||||
{
|
||||
int rc;
|
||||
struct termios termios;
|
||||
@@ -94,7 +87,7 @@ static int ser_setspeed(int fd, long baud)
|
||||
*/
|
||||
rc = tcgetattr(fd, &termios);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_setspeed(): tcgetattr() failed, %s",
|
||||
fprintf(stderr, "%s: serial_setattr(): tcgetattr() failed, %s",
|
||||
progname, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
@@ -112,24 +105,16 @@ static int ser_setspeed(int fd, long baud)
|
||||
|
||||
rc = tcsetattr(fd, TCSANOW, &termios);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_setspeed(): tcsetattr() failed, %s",
|
||||
fprintf(stderr, "%s: serial_setattr(): tcsetattr() failed, %s",
|
||||
progname, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* set non blocking mode
|
||||
*/
|
||||
rc = fcntl(fd, F_GETFL, 0);
|
||||
fcntl(fd, F_SETFL, rc | O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ser_open(char * port, long baud)
|
||||
int serial_open(char * port, int baud)
|
||||
{
|
||||
int rc;
|
||||
int fd;
|
||||
@@ -139,7 +124,7 @@ static int ser_open(char * port, long baud)
|
||||
*/
|
||||
fd = open(port, O_RDWR | O_NOCTTY /*| O_NONBLOCK*/);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "%s: ser_open(): can't open device \"%s\": %s\n",
|
||||
fprintf(stderr, "%s: serial_open(): can't open device \"%s\": %s\n",
|
||||
progname, port, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
@@ -147,10 +132,10 @@ static int ser_open(char * port, long baud)
|
||||
/*
|
||||
* set serial line attributes
|
||||
*/
|
||||
rc = ser_setspeed(fd, baud);
|
||||
rc = serial_setattr(fd, baud);
|
||||
if (rc) {
|
||||
fprintf(stderr,
|
||||
"%s: ser_open(): can't set attributes for device \"%s\"\n",
|
||||
"%s: serial_open(): can't set attributes for device \"%s\"\n",
|
||||
progname, port);
|
||||
exit(1);
|
||||
}
|
||||
@@ -159,7 +144,7 @@ static int ser_open(char * port, long baud)
|
||||
}
|
||||
|
||||
|
||||
static void ser_close(int fd)
|
||||
void serial_close(int fd)
|
||||
{
|
||||
/* FIXME: Should really restore the terminal to original state here. */
|
||||
|
||||
@@ -167,13 +152,14 @@ static void ser_close(int fd)
|
||||
}
|
||||
|
||||
|
||||
static int ser_send(int fd, unsigned char * buf, size_t buflen)
|
||||
int serial_send(int fd, char * buf, size_t buflen)
|
||||
{
|
||||
struct timeval timeout, to2;
|
||||
struct timeval timeout;
|
||||
fd_set wfds;
|
||||
int nfds;
|
||||
int rc;
|
||||
unsigned char * p = buf;
|
||||
|
||||
char * p = buf;
|
||||
size_t len = buflen;
|
||||
|
||||
if (!len)
|
||||
@@ -202,94 +188,88 @@ static int ser_send(int fd, unsigned char * buf, size_t buflen)
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 500000;
|
||||
to2 = timeout;
|
||||
|
||||
while (len) {
|
||||
reselect:
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(fd, &wfds);
|
||||
|
||||
nfds = select(fd+1, NULL, &wfds, NULL, &to2);
|
||||
reselect:
|
||||
nfds = select(fd+1, NULL, &wfds, NULL, &timeout);
|
||||
if (nfds == 0) {
|
||||
if (verbose >= 1)
|
||||
fprintf(stderr,
|
||||
"%s: ser_send(): programmer is not responding\n",
|
||||
progname);
|
||||
fprintf(stderr,
|
||||
"%s: serial_send(): programmer is not responding\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
else if (nfds == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
if (errno == EINTR) {
|
||||
goto reselect;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s: ser_send(): select(): %s\n",
|
||||
fprintf(stderr, "%s: serial_send(): select(): %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
rc = write(fd, p, (len > 1024) ? 1024 : len);
|
||||
rc = write(fd, p, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_send(): write error: %s\n",
|
||||
fprintf(stderr, "%s: serial_send(): write error: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
p += rc;
|
||||
len -= rc;
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ser_recv(int fd, unsigned char * buf, size_t buflen)
|
||||
int serial_recv(int fd, char * buf, size_t buflen)
|
||||
{
|
||||
struct timeval timeout, to2;
|
||||
struct timeval timeout;
|
||||
fd_set rfds;
|
||||
int nfds;
|
||||
int rc;
|
||||
unsigned char * p = buf;
|
||||
|
||||
char * p = buf;
|
||||
size_t len = 0;
|
||||
|
||||
timeout.tv_sec = serial_recv_timeout / 1000L;
|
||||
timeout.tv_usec = (serial_recv_timeout % 1000L) * 1000;
|
||||
to2 = timeout;
|
||||
timeout.tv_sec = 5;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
while (len < buflen) {
|
||||
reselect:
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
|
||||
nfds = select(fd+1, &rfds, NULL, NULL, &to2);
|
||||
reselect:
|
||||
nfds = select(fd+1, &rfds, NULL, NULL, &timeout);
|
||||
if (nfds == 0) {
|
||||
if (verbose > 1)
|
||||
fprintf(stderr,
|
||||
"%s: ser_recv(): programmer is not responding\n",
|
||||
progname);
|
||||
return -1;
|
||||
fprintf(stderr,
|
||||
"%s: serial_recv(): programmer is not responding\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
else if (nfds == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
fprintf(stderr,
|
||||
"%s: ser_recv(): programmer is not responding,reselecting\n",
|
||||
progname);
|
||||
if (errno == EINTR) {
|
||||
goto reselect;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s: ser_recv(): select(): %s\n",
|
||||
fprintf(stderr, "%s: serial_recv(): select(): %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
rc = read(fd, p, (buflen - len > 1024) ? 1024 : buflen - len);
|
||||
rc = read(fd, p, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_recv(): read error: %s\n",
|
||||
fprintf(stderr, "%s: serial_recv(): read error: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
p += rc;
|
||||
len += rc;
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
|
||||
p = buf;
|
||||
@@ -318,7 +298,7 @@ static int ser_recv(int fd, unsigned char * buf, size_t buflen)
|
||||
}
|
||||
|
||||
|
||||
static int ser_drain(int fd, int display)
|
||||
int serial_drain(int fd, int display)
|
||||
{
|
||||
struct timeval timeout;
|
||||
fd_set rfds;
|
||||
@@ -351,7 +331,7 @@ static int ser_drain(int fd, int display)
|
||||
goto reselect;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s: ser_drain(): select(): %s\n",
|
||||
fprintf(stderr, "%s: serial_drain(): select(): %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
@@ -359,7 +339,7 @@ static int ser_drain(int fd, int display)
|
||||
|
||||
rc = read(fd, &buf, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_drain(): read error: %s\n",
|
||||
fprintf(stderr, "%s: serial_drain(): read error: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
@@ -370,17 +350,3 @@ static int ser_drain(int fd, int display)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct serial_device serial_serdev =
|
||||
{
|
||||
.open = ser_open,
|
||||
.setspeed = ser_setspeed,
|
||||
.close = ser_close,
|
||||
.send = ser_send,
|
||||
.recv = ser_recv,
|
||||
.drain = ser_drain,
|
||||
};
|
||||
|
||||
struct serial_device *serdev = &serial_serdev;
|
||||
|
||||
#endif /* WIN32NATIVE */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003, 2004 Martin J. Thomas <mthomas@rhrk.uni-kl.de>
|
||||
* Copyright (C) 2003 Theodore A. Roth <troth@openavr.org>
|
||||
*
|
||||
* 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
|
||||
@@ -23,333 +23,38 @@
|
||||
* Native Win32 serial interface for avrdude.
|
||||
*/
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h> /* for isprint */
|
||||
#include "serial.h"
|
||||
|
||||
extern char *progname;
|
||||
extern int verbose;
|
||||
|
||||
long serial_recv_timeout = 5000; /* ms */
|
||||
#if 0
|
||||
|
||||
#define W32SERBUFSIZE 1024
|
||||
|
||||
struct baud_mapping {
|
||||
long baud;
|
||||
DWORD speed;
|
||||
};
|
||||
|
||||
/* HANDLE hComPort=INVALID_HANDLE_VALUE; */
|
||||
|
||||
static struct baud_mapping baud_lookup_table [] = {
|
||||
{ 1200, CBR_1200 },
|
||||
{ 2400, CBR_2400 },
|
||||
{ 4800, CBR_4800 },
|
||||
{ 9600, CBR_9600 },
|
||||
{ 19200, CBR_19200 },
|
||||
{ 38400, CBR_38400 },
|
||||
{ 57600, CBR_57600 },
|
||||
{ 115200, CBR_115200 },
|
||||
{ 0, 0 } /* Terminator. */
|
||||
};
|
||||
|
||||
static DWORD serial_baud_lookup(long baud)
|
||||
int serial_open(char * port, long baud)
|
||||
{
|
||||
struct baud_mapping *map = baud_lookup_table;
|
||||
|
||||
while (map->baud) {
|
||||
if (map->baud == baud)
|
||||
return map->speed;
|
||||
map++;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: serial_baud_lookup(): unknown baud rate: %ld",
|
||||
progname, baud);
|
||||
exit(1);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms
|
||||
void serial_close(int fd)
|
||||
{
|
||||
COMMTIMEOUTS ctmo;
|
||||
ZeroMemory (&ctmo, sizeof(COMMTIMEOUTS));
|
||||
ctmo.ReadIntervalTimeout = timeout;
|
||||
ctmo.ReadTotalTimeoutMultiplier = timeout;
|
||||
ctmo.ReadTotalTimeoutConstant = timeout;
|
||||
|
||||
return SetCommTimeouts(hComPort, &ctmo);
|
||||
}
|
||||
|
||||
static int ser_setspeed(int fd, long baud)
|
||||
{
|
||||
DCB dcb;
|
||||
HANDLE hComPort = (HANDLE)fd;
|
||||
|
||||
ZeroMemory (&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
dcb.BaudRate = serial_baud_lookup (baud);
|
||||
dcb.fBinary = 1;
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
|
||||
if (!SetCommState(hComPort, &dcb))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ser_open(char * port, long baud)
|
||||
int serial_send(int fd, char * buf, size_t buflen)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
HANDLE hComPort=INVALID_HANDLE_VALUE;
|
||||
|
||||
/* if (hComPort!=INVALID_HANDLE_VALUE)
|
||||
fprintf(stderr, "%s: ser_open(): \"%s\" is already open\n",
|
||||
progname, port);
|
||||
*/
|
||||
|
||||
hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
fprintf(stderr, "%s: ser_open(): can't open device \"%s\": %s\n",
|
||||
progname, port, (char*)lpMsgBuf);
|
||||
LocalFree( lpMsgBuf );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE))
|
||||
{
|
||||
CloseHandle(hComPort);
|
||||
fprintf(stderr, "%s: ser_open(): can't set buffers for \"%s\"\n",
|
||||
progname, port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (ser_setspeed((int)hComPort, baud) != 0)
|
||||
{
|
||||
CloseHandle(hComPort);
|
||||
fprintf(stderr, "%s: ser_open(): can't set com-state for \"%s\"\n",
|
||||
progname, port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!serial_w32SetTimeOut(hComPort,0))
|
||||
{
|
||||
CloseHandle(hComPort);
|
||||
fprintf(stderr, "%s: ser_open(): can't set initial timeout for \"%s\"\n",
|
||||
progname, port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (int)hComPort;
|
||||
}
|
||||
|
||||
|
||||
static void ser_close(int fd)
|
||||
{
|
||||
HANDLE hComPort=(HANDLE)fd;
|
||||
if (hComPort != INVALID_HANDLE_VALUE)
|
||||
CloseHandle (hComPort);
|
||||
|
||||
hComPort = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static int ser_send(int fd, char * buf, size_t buflen)
|
||||
{
|
||||
size_t len = buflen;
|
||||
unsigned char c='\0';
|
||||
DWORD written;
|
||||
|
||||
HANDLE hComPort=(HANDLE)fd;
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "%s: ser_send(): port not open\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (verbose > 3)
|
||||
{
|
||||
fprintf(stderr, "%s: Send: ", progname);
|
||||
|
||||
while (buflen) {
|
||||
c = *buf;
|
||||
if (isprint(c)) {
|
||||
fprintf(stderr, "%c ", c);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, ". ");
|
||||
}
|
||||
fprintf(stderr, "[%02x] ", c);
|
||||
buf++;
|
||||
buflen--;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
serial_w32SetTimeOut(hComPort,500);
|
||||
|
||||
if (!WriteFile (hComPort, buf, buflen, &written, NULL)) {
|
||||
fprintf(stderr, "%s: ser_send(): write error: %s\n",
|
||||
progname, "sorry no info avail"); // TODO
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (written != buflen) {
|
||||
fprintf(stderr, "%s: ser_send(): size/send mismatch\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ser_recv(int fd, char * buf, size_t buflen)
|
||||
{
|
||||
unsigned char c;
|
||||
char * p = buf;
|
||||
size_t len = 0;
|
||||
DWORD read;
|
||||
|
||||
HANDLE hComPort=(HANDLE)fd;
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "%s: ser_read(): port not open\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
serial_w32SetTimeOut(hComPort, serial_recv_timeout);
|
||||
|
||||
if (!ReadFile(hComPort, buf, buflen, &read, NULL)) {
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL );
|
||||
fprintf(stderr, "%s: ser_recv(): read error: %s\n",
|
||||
progname, (char*)lpMsgBuf);
|
||||
LocalFree( lpMsgBuf );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p = buf;
|
||||
|
||||
if (verbose > 3)
|
||||
{
|
||||
fprintf(stderr, "%s: Recv: ", progname);
|
||||
|
||||
while (len) {
|
||||
c = *p;
|
||||
if (isprint(c)) {
|
||||
fprintf(stderr, "%c ", c);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, ". ");
|
||||
}
|
||||
fprintf(stderr, "[%02x] ", c);
|
||||
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ser_drain(int fd, int display)
|
||||
int serial_recv(int fd, char * buf, size_t buflen)
|
||||
{
|
||||
// int rc;
|
||||
unsigned char buf[10];
|
||||
BOOL readres;
|
||||
DWORD read;
|
||||
|
||||
HANDLE hComPort=(HANDLE)fd;
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "%s: ser_drain(): port not open\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
serial_w32SetTimeOut(hComPort,250);
|
||||
|
||||
if (display) {
|
||||
fprintf(stderr, "drain>");
|
||||
}
|
||||
|
||||
while (1) {
|
||||
readres=ReadFile(hComPort, buf, 1, &read, NULL);
|
||||
if (!readres) {
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL );
|
||||
fprintf(stderr, "%s: ser_drain(): read error: %s\n",
|
||||
progname, (char*)lpMsgBuf);
|
||||
LocalFree( lpMsgBuf );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (read) { // data avail
|
||||
if (display) fprintf(stderr, "%02x ", buf[0]);
|
||||
}
|
||||
else { // no more data
|
||||
if (display) fprintf(stderr, "<drain\n");
|
||||
break;
|
||||
}
|
||||
} // while
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct serial_device serial_serdev =
|
||||
|
||||
int serial_drain(int fd, int display)
|
||||
{
|
||||
.open = ser_open,
|
||||
.setspeed = ser_setspeed,
|
||||
.close = ser_close,
|
||||
.send = ser_send,
|
||||
.recv = ser_recv,
|
||||
.drain = ser_drain,
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct serial_device *serdev = &serial_serdev;
|
||||
|
||||
#endif /* WIN32NATIVE */
|
||||
#endif
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.org>
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
#ifndef serbb_h
|
||||
#define serbb_h
|
||||
|
||||
void serbb_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
int serbb_setpin(int fd, int pin, int value);
|
||||
int serbb_getpin(int fd, int pin);
|
||||
int serbb_highpulsepin(int fd, int pin);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.org>
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
/*
|
||||
* Posix serial bitbanging interface for avrdude.
|
||||
*/
|
||||
|
||||
#if !defined(WIN32NATIVE)
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "avr.h"
|
||||
#include "pindefs.h"
|
||||
#include "pgm.h"
|
||||
#include "bitbang.h"
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
extern char *progname;
|
||||
struct termios oldmode;
|
||||
|
||||
/*
|
||||
serial port/pin mapping
|
||||
|
||||
1 cd <-
|
||||
2 rxd <-
|
||||
3 txd ->
|
||||
4 dtr ->
|
||||
5 dsr <-
|
||||
6 rts ->
|
||||
7 cts <-
|
||||
*/
|
||||
|
||||
int serregbits[] =
|
||||
{ TIOCM_CD, 0, 0, TIOCM_DTR, TIOCM_DSR, TIOCM_RTS, TIOCM_CTS };
|
||||
|
||||
#ifdef DEBUG
|
||||
char *serpins[7] =
|
||||
{ "CD", "RXD", "TXD ~RESET", "DTR MOSI", "DSR", "RTS SCK", "CTS MISO" };
|
||||
#endif
|
||||
|
||||
void serbb_setpin(int fd, int pin, int value)
|
||||
{
|
||||
unsigned int ctl;
|
||||
|
||||
if (pin & PIN_INVERSE)
|
||||
{
|
||||
value = !value;
|
||||
pin &= PIN_MASK;
|
||||
}
|
||||
|
||||
if ( pin < 1 || pin > 7 )
|
||||
return;
|
||||
|
||||
pin--;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("%s to %d\n",serpins[pin],value);
|
||||
#endif
|
||||
|
||||
switch ( pin )
|
||||
{
|
||||
case 2: /* txd */
|
||||
ioctl(fd, value ? TIOCSBRK : TIOCCBRK, 0);
|
||||
return;
|
||||
|
||||
case 3: /* dtr, rts */
|
||||
case 5: ioctl(fd, TIOCMGET, &ctl);
|
||||
if ( value )
|
||||
ctl |= serregbits[pin];
|
||||
else
|
||||
ctl &= ~(serregbits[pin]);
|
||||
ioctl(fd, TIOCMSET, &ctl);
|
||||
return;
|
||||
|
||||
default: /* impossible */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int serbb_getpin(int fd, int pin)
|
||||
{
|
||||
unsigned int ctl;
|
||||
unsigned char invert;
|
||||
|
||||
if (pin & PIN_INVERSE)
|
||||
{
|
||||
invert = 1;
|
||||
pin &= PIN_MASK;
|
||||
} else
|
||||
invert = 0;
|
||||
|
||||
if ( pin < 1 || pin > 7 )
|
||||
return(-1);
|
||||
|
||||
pin --;
|
||||
|
||||
switch ( pin )
|
||||
{
|
||||
case 1: /* rxd, currently not implemented, FIXME */
|
||||
return(-1);
|
||||
|
||||
case 0: /* cd, dsr, dtr, rts, cts */
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6: ioctl(fd, TIOCMGET, &ctl);
|
||||
if ( !invert )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("%s is %d\n",serpins[pin],(ctl & serregbits[pin]) ? 1 : 0 );
|
||||
#endif
|
||||
return ( (ctl & serregbits[pin]) ? 1 : 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("%s is %d (~)\n",serpins[pin],(ctl & serregbits[pin]) ? 0 : 1 );
|
||||
#endif
|
||||
return (( ctl & serregbits[pin]) ? 0 : 1 );
|
||||
}
|
||||
|
||||
default: /* impossible */
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int serbb_highpulsepin(int fd, int pin)
|
||||
{
|
||||
if (pin < 1 || pin > 7)
|
||||
return -1;
|
||||
|
||||
serbb_setpin(fd, pin, 1);
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
serbb_setpin(fd, pin, 0);
|
||||
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void serbb_display(PROGRAMMER *pgm, char *p)
|
||||
{
|
||||
/* MAYBE */
|
||||
}
|
||||
|
||||
void serbb_enable(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_disable(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_powerup(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_powerdown(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
int serbb_open(PROGRAMMER *pgm, char *port)
|
||||
{
|
||||
struct termios mode;
|
||||
int flags;
|
||||
|
||||
/* adapted from uisp code */
|
||||
|
||||
pgm->fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
|
||||
if ( pgm->fd > 0 )
|
||||
{
|
||||
tcgetattr(pgm->fd, &mode);
|
||||
oldmode = mode;
|
||||
|
||||
cfmakeraw(&mode);
|
||||
mode.c_iflag &= ~(INPCK | IXOFF | IXON);
|
||||
mode.c_cflag &= ~(HUPCL | CSTOPB | CRTSCTS);
|
||||
mode.c_cflag |= (CLOCAL | CREAD);
|
||||
mode.c_cc [VMIN] = 1;
|
||||
mode.c_cc [VTIME] = 0;
|
||||
|
||||
tcsetattr(pgm->fd, TCSANOW, &mode);
|
||||
|
||||
/* Clear O_NONBLOCK flag. */
|
||||
flags = fcntl(pgm->fd, F_GETFL, 0);
|
||||
if (flags == -1)
|
||||
{
|
||||
fprintf(stderr, "%s: Can not get flags\n", progname);
|
||||
return(-1);
|
||||
}
|
||||
flags &= ~O_NONBLOCK;
|
||||
if (fcntl(pgm->fd, F_SETFL, flags) == -1)
|
||||
{
|
||||
fprintf(stderr, "%s: Can not clear nonblock flag\n", progname);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void serbb_close(PROGRAMMER *pgm)
|
||||
{
|
||||
tcsetattr(pgm->fd, TCSADRAIN, &oldmode);
|
||||
return;
|
||||
}
|
||||
|
||||
void serbb_initpgm(PROGRAMMER *pgm)
|
||||
{
|
||||
strcpy(pgm->type, "SERBB");
|
||||
|
||||
pgm->rdy_led = bitbang_rdy_led;
|
||||
pgm->err_led = bitbang_err_led;
|
||||
pgm->pgm_led = bitbang_pgm_led;
|
||||
pgm->vfy_led = bitbang_vfy_led;
|
||||
pgm->initialize = bitbang_initialize;
|
||||
pgm->display = serbb_display;
|
||||
pgm->enable = serbb_enable;
|
||||
pgm->disable = serbb_disable;
|
||||
pgm->powerup = serbb_powerup;
|
||||
pgm->powerdown = serbb_powerdown;
|
||||
pgm->program_enable = bitbang_program_enable;
|
||||
pgm->chip_erase = bitbang_chip_erase;
|
||||
pgm->cmd = bitbang_cmd;
|
||||
pgm->open = serbb_open;
|
||||
pgm->close = serbb_close;
|
||||
|
||||
/* this is a serial port bitbang device */
|
||||
pgm->flag = 1;
|
||||
}
|
||||
|
||||
#endif /* WIN32NATIVE */
|
||||
@@ -1,372 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003, 2004 Martin J. Thomas <mthomas@rhrk.uni-kl.de>
|
||||
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.org>
|
||||
* Copyright (C) 2005 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
/*
|
||||
* Win32 serial bitbanging interface for avrdude.
|
||||
*/
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "avr.h"
|
||||
#include "pindefs.h"
|
||||
#include "pgm.h"
|
||||
#include "bitbang.h"
|
||||
|
||||
extern char *progname;
|
||||
extern int verbose;
|
||||
|
||||
/* cached status lines */
|
||||
static int dtr, rts, txd;
|
||||
|
||||
#define W32SERBUFSIZE 1024
|
||||
|
||||
/*
|
||||
serial port/pin mapping
|
||||
|
||||
1 cd <-
|
||||
2 rxd <-
|
||||
3 txd ->
|
||||
4 dtr ->
|
||||
5 dsr <-
|
||||
6 rts ->
|
||||
7 cts <-
|
||||
|
||||
Negative pin # means negated value.
|
||||
*/
|
||||
|
||||
void serbb_setpin(int fd, int pin, int value)
|
||||
{
|
||||
HANDLE hComPort = (HANDLE)fd;
|
||||
LPVOID lpMsgBuf;
|
||||
DWORD dwFunc;
|
||||
const char *name;
|
||||
|
||||
if (pin & PIN_INVERSE)
|
||||
{
|
||||
value = !value;
|
||||
pin &= PIN_MASK;
|
||||
}
|
||||
|
||||
if (pin < 1 || pin > 7)
|
||||
return;
|
||||
|
||||
pin--;
|
||||
|
||||
switch (pin)
|
||||
{
|
||||
case 2: /* txd */
|
||||
dwFunc = value? SETBREAK: CLRBREAK;
|
||||
name = value? "SETBREAK": "CLRBREAK";
|
||||
txd = value;
|
||||
break;
|
||||
|
||||
case 3: /* dtr */
|
||||
dwFunc = value? SETDTR: CLRDTR;
|
||||
name = value? "SETDTR": "CLRDTR";
|
||||
dtr = value;
|
||||
break;
|
||||
|
||||
case 5: /* rts */
|
||||
dwFunc = value? SETRTS: CLRRTS;
|
||||
name = value? "SETRTS": "CLRRTS";
|
||||
break;
|
||||
|
||||
default:
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
"%s: serbb_setpin(): unknown pin %d\n",
|
||||
progname, pin + 1);
|
||||
return;
|
||||
}
|
||||
if (verbose > 4)
|
||||
fprintf(stderr,
|
||||
"%s: serbb_setpin(): EscapeCommFunction(%s)\n",
|
||||
progname, name);
|
||||
if (!EscapeCommFunction(hComPort, dwFunc))
|
||||
{
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
fprintf(stderr,
|
||||
"%s: serbb_setpin(): SetCommState() failed: %s\n",
|
||||
progname, (char *)lpMsgBuf);
|
||||
CloseHandle(hComPort);
|
||||
LocalFree(lpMsgBuf);
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int serbb_getpin(int fd, int pin)
|
||||
{
|
||||
HANDLE hComPort = (HANDLE)fd;
|
||||
LPVOID lpMsgBuf;
|
||||
int invert, rv;
|
||||
const char *name;
|
||||
DWORD modemstate;
|
||||
|
||||
if (pin & PIN_INVERSE)
|
||||
{
|
||||
invert = 1;
|
||||
pin &= PIN_MASK;
|
||||
} else
|
||||
invert = 0;
|
||||
|
||||
if (pin < 1 || pin > 7)
|
||||
return -1;
|
||||
|
||||
pin --;
|
||||
|
||||
if (pin == 0 /* cd */ || pin == 4 /* dsr */ || pin == 6 /* cts */)
|
||||
{
|
||||
if (!GetCommModemStatus(hComPort, &modemstate))
|
||||
{
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
fprintf(stderr,
|
||||
"%s: serbb_setpin(): GetCommModemStatus() failed: %s\n",
|
||||
progname, (char *)lpMsgBuf);
|
||||
CloseHandle(hComPort);
|
||||
LocalFree(lpMsgBuf);
|
||||
exit(1);
|
||||
}
|
||||
if (verbose > 4)
|
||||
fprintf(stderr,
|
||||
"%s: serbb_getpin(): GetCommState() => 0x%lx\n",
|
||||
progname, modemstate);
|
||||
switch (pin)
|
||||
{
|
||||
case 0:
|
||||
modemstate &= MS_RLSD_ON;
|
||||
break;
|
||||
case 4:
|
||||
modemstate &= MS_DSR_ON;
|
||||
break;
|
||||
case 6:
|
||||
modemstate &= MS_CTS_ON;
|
||||
break;
|
||||
}
|
||||
rv = modemstate != 0;
|
||||
if (invert)
|
||||
rv = !rv;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
switch (pin)
|
||||
{
|
||||
case 2: /* txd */
|
||||
rv = txd;
|
||||
name = "TXD";
|
||||
break;
|
||||
case 3: /* dtr */
|
||||
rv = dtr;
|
||||
name = "DTR";
|
||||
break;
|
||||
case 5: /* rts */
|
||||
rv = rts;
|
||||
name = "RTS";
|
||||
break;
|
||||
default:
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
"%s: serbb_getpin(): unknown pin %d\n",
|
||||
progname, pin + 1);
|
||||
return -1;
|
||||
}
|
||||
if (verbose > 4)
|
||||
fprintf(stderr,
|
||||
"%s: serbb_getpin(): return cached state for %s\n",
|
||||
progname, name);
|
||||
if (invert)
|
||||
rv = !rv;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int serbb_highpulsepin(int fd, int pin)
|
||||
{
|
||||
if (pin < 1 || pin > 7)
|
||||
return -1;
|
||||
|
||||
serbb_setpin(fd, pin, 1);
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
serbb_setpin(fd, pin, 0);
|
||||
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void serbb_display(PROGRAMMER *pgm, char *p)
|
||||
{
|
||||
/* MAYBE */
|
||||
}
|
||||
|
||||
void serbb_enable(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_disable(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_powerup(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_powerdown(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
int serbb_open(PROGRAMMER *pgm, char *port)
|
||||
{
|
||||
DCB dcb;
|
||||
LPVOID lpMsgBuf;
|
||||
HANDLE hComPort = INVALID_HANDLE_VALUE;
|
||||
|
||||
hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
fprintf(stderr, "%s: ser_open(): can't open device \"%s\": %s\n",
|
||||
progname, port, (char*)lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE))
|
||||
{
|
||||
CloseHandle(hComPort);
|
||||
fprintf(stderr, "%s: ser_open(): can't set buffers for \"%s\"\n",
|
||||
progname, port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ZeroMemory(&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
dcb.BaudRate = CBR_9600;
|
||||
dcb.fBinary = 1;
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
|
||||
if (!SetCommState(hComPort, &dcb))
|
||||
{
|
||||
CloseHandle(hComPort);
|
||||
fprintf(stderr, "%s: ser_open(): can't set com-state for \"%s\"\n",
|
||||
progname, port);
|
||||
return -1;
|
||||
}
|
||||
if (verbose > 2)
|
||||
fprintf(stderr,
|
||||
"%s: ser_open(): opened comm port \"%s\", handle 0x%x\n",
|
||||
progname, port, (int)hComPort);
|
||||
|
||||
pgm->fd = (int)hComPort;
|
||||
|
||||
dtr = rts = txd = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serbb_close(PROGRAMMER *pgm)
|
||||
{
|
||||
HANDLE hComPort=(HANDLE)pgm->fd;
|
||||
if (hComPort != INVALID_HANDLE_VALUE)
|
||||
CloseHandle (hComPort);
|
||||
if (verbose > 2)
|
||||
fprintf(stderr,
|
||||
"%s: ser_close(): closed comm port handle 0x%x\n",
|
||||
progname, (int)hComPort);
|
||||
|
||||
hComPort = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
void serbb_initpgm(PROGRAMMER *pgm)
|
||||
{
|
||||
strcpy(pgm->type, "SERBB");
|
||||
|
||||
pgm->rdy_led = bitbang_rdy_led;
|
||||
pgm->err_led = bitbang_err_led;
|
||||
pgm->pgm_led = bitbang_pgm_led;
|
||||
pgm->vfy_led = bitbang_vfy_led;
|
||||
pgm->initialize = bitbang_initialize;
|
||||
pgm->display = serbb_display;
|
||||
pgm->enable = serbb_enable;
|
||||
pgm->disable = serbb_disable;
|
||||
pgm->powerup = serbb_powerup;
|
||||
pgm->powerdown = serbb_powerdown;
|
||||
pgm->program_enable = bitbang_program_enable;
|
||||
pgm->chip_erase = bitbang_chip_erase;
|
||||
pgm->cmd = bitbang_cmd;
|
||||
pgm->open = serbb_open;
|
||||
pgm->close = serbb_close;
|
||||
|
||||
/* this is a serial port bitbang device */
|
||||
pgm->flag = 1;
|
||||
}
|
||||
|
||||
#endif /* WIN32NATIVE */
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003 Theodore A. Roth <troth@openavr.org>
|
||||
*
|
||||
* 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
|
||||
@@ -30,27 +30,13 @@
|
||||
#ifndef __serial_h__
|
||||
#define __serial_h__
|
||||
|
||||
extern long serial_recv_timeout;
|
||||
#include "config.h"
|
||||
|
||||
struct serial_device
|
||||
{
|
||||
int (*open)(char * port, long baud);
|
||||
int (*setspeed)(int fd, long baud);
|
||||
void (*close)(int fd);
|
||||
extern int serial_open(char * port, long baud);
|
||||
extern void serial_close(int fd);
|
||||
|
||||
int (*send)(int fd, unsigned char * buf, size_t buflen);
|
||||
int (*recv)(int fd, unsigned char * buf, size_t buflen);
|
||||
int (*drain)(int fd, int display);
|
||||
};
|
||||
|
||||
extern struct serial_device *serdev;
|
||||
extern struct serial_device serial_serdev, usb_serdev;
|
||||
|
||||
#define serial_open (serdev->open)
|
||||
#define serial_setspeed (serdev->setspeed)
|
||||
#define serial_close (serdev->close)
|
||||
#define serial_send (serdev->send)
|
||||
#define serial_recv (serdev->recv)
|
||||
#define serial_drain (serdev->drain)
|
||||
extern int serial_send(int fd, char * buf, size_t buflen);
|
||||
extern int serial_recv(int fd, char * buf, size_t buflen);
|
||||
extern int serial_drain(int fd, int display);
|
||||
|
||||
#endif /* __serial_h__ */
|
||||
|
||||
231
avrdude/stk500.c
231
avrdude/stk500.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2002, 2003 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
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "stk500_private.h"
|
||||
#include "serial.h"
|
||||
|
||||
#define STK500_XTAL 7372800U
|
||||
|
||||
extern int verbose;
|
||||
extern char * progname;
|
||||
@@ -51,28 +50,16 @@ extern int do_cycles;
|
||||
static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value);
|
||||
static int stk500_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value);
|
||||
static void stk500_print_parms1(PROGRAMMER * pgm, char * p);
|
||||
static int stk500_is_page_empty(unsigned int address, int page_size,
|
||||
const unsigned char *buf);
|
||||
|
||||
|
||||
static int stk500_send(PROGRAMMER * pgm, unsigned char * buf, size_t len)
|
||||
static int stk500_send(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
{
|
||||
return serial_send(pgm->fd, buf, len);
|
||||
}
|
||||
|
||||
|
||||
static int stk500_recv(PROGRAMMER * pgm, unsigned char * buf, size_t len)
|
||||
static int stk500_recv(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = serial_recv(pgm->fd, buf, len);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500_recv(): programmer is not responding\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
return serial_recv(pgm->fd, buf, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,11 +100,32 @@ static int stk500_getsync(PROGRAMMER * pgm)
|
||||
}
|
||||
|
||||
|
||||
static int stk500_rdy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stk500_err_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stk500_pgm_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stk500_vfy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* transmit an AVR device command and return the results; 'cmd' and
|
||||
* 'res' must point to at least a 4 byte data buffer
|
||||
*/
|
||||
static int stk500_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
static int stk500_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
unsigned char buf[32];
|
||||
@@ -160,6 +168,8 @@ static int stk500_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
int cycles;
|
||||
int rc;
|
||||
|
||||
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
|
||||
fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
|
||||
@@ -167,6 +177,19 @@ static int stk500_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = avr_get_cycle_count(pgm, p, &cycles);
|
||||
|
||||
/*
|
||||
* only print out the current cycle count if we aren't going to
|
||||
* display it below
|
||||
*/
|
||||
if (!do_cycles && ((rc >= 0) && (cycles != 0xffffffff))) {
|
||||
fprintf(stderr,
|
||||
"%s: current erase-rewrite cycle count is %d%s\n",
|
||||
progname, cycles,
|
||||
do_cycles ? "" : " (if being tracked)");
|
||||
}
|
||||
|
||||
pgm->pgm_led(pgm, ON);
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
@@ -178,6 +201,16 @@ static int stk500_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
|
||||
if (do_cycles && (cycles != -1)) {
|
||||
if (cycles == 0x00ffff) {
|
||||
cycles = 0;
|
||||
}
|
||||
cycles++;
|
||||
fprintf(stderr, "%s: erase-rewrite cycle count is now %d\n",
|
||||
progname, cycles);
|
||||
avr_put_cycle_count(pgm, p, cycles);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -241,8 +274,25 @@ static int stk500_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* apply power to the AVR processor
|
||||
*/
|
||||
static void stk500_powerup(PROGRAMMER * pgm)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int stk500_set_extended_parms(PROGRAMMER * pgm, int n,
|
||||
|
||||
/*
|
||||
* remove power from the AVR processor
|
||||
*/
|
||||
static void stk500_powerdown(PROGRAMMER * pgm)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int stk500_set_extended_parms(PROGRAMMER * pgm, int n,
|
||||
unsigned char * cmd)
|
||||
{
|
||||
unsigned char buf[16];
|
||||
@@ -494,6 +544,16 @@ static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
}
|
||||
|
||||
|
||||
static int stk500_save(PROGRAMMER * pgm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stk500_restore(PROGRAMMER * pgm)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void stk500_disable(PROGRAMMER * pgm)
|
||||
{
|
||||
unsigned char buf[16];
|
||||
@@ -547,13 +607,10 @@ static void stk500_enable(PROGRAMMER * pgm)
|
||||
}
|
||||
|
||||
|
||||
static int stk500_open(PROGRAMMER * pgm, char * port)
|
||||
static void stk500_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
strcpy(pgm->port, port);
|
||||
if (pgm->baudrate)
|
||||
pgm->fd = serial_open(port, pgm->baudrate);
|
||||
else
|
||||
pgm->fd = serial_open(port, 115200);
|
||||
pgm->fd = serial_open(port, 115200);
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
@@ -563,8 +620,6 @@ static int stk500_open(PROGRAMMER * pgm, char * port)
|
||||
stk500_getsync(pgm);
|
||||
|
||||
stk500_drain(pgm, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -629,10 +684,9 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int memtype;
|
||||
unsigned int addr;
|
||||
int a_div;
|
||||
int block_size;
|
||||
int i;
|
||||
int tries;
|
||||
unsigned int n;
|
||||
int flash;
|
||||
|
||||
if (page_size == 0) {
|
||||
page_size = 128;
|
||||
@@ -640,11 +694,9 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
memtype = 'F';
|
||||
flash = 1;
|
||||
}
|
||||
else if (strcmp(m->desc, "eeprom") == 0) {
|
||||
memtype = 'E';
|
||||
flash = 0;
|
||||
}
|
||||
else {
|
||||
return -2;
|
||||
@@ -679,32 +731,19 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
|
||||
for (addr = 0; addr < n; addr += page_size) {
|
||||
report_progress (addr, n_bytes, NULL);
|
||||
|
||||
if (addr + page_size > n_bytes) {
|
||||
block_size = n_bytes % page_size;
|
||||
}
|
||||
else {
|
||||
block_size = page_size;
|
||||
}
|
||||
|
||||
/* Only skip on empty page if programming flash. */
|
||||
if (flash) {
|
||||
if (stk500_is_page_empty(addr, block_size, m->buf)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
tries = 0;
|
||||
retry:
|
||||
tries++;
|
||||
stk500_loadaddr(pgm, addr/a_div);
|
||||
buf[0] = Cmnd_STK_PROG_PAGE;
|
||||
buf[1] = (block_size >> 8) & 0xff;
|
||||
buf[2] = block_size & 0xff;
|
||||
buf[1] = (page_size >> 8) & 0xff;
|
||||
buf[2] = page_size & 0xff;
|
||||
buf[3] = memtype;
|
||||
stk500_send(pgm, buf, 4);
|
||||
|
||||
stk500_send(pgm, &m->buf[addr], block_size);
|
||||
|
||||
for (i=0; i<page_size; i++) {
|
||||
buf[0] = m->buf[addr + i];
|
||||
stk500_send(pgm, buf, 1);
|
||||
}
|
||||
buf[0] = Sync_CRC_EOP;
|
||||
stk500_send(pgm, buf, 1);
|
||||
|
||||
@@ -736,23 +775,9 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
}
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
return n;
|
||||
}
|
||||
|
||||
static int stk500_is_page_empty(unsigned int address, int page_size,
|
||||
const unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < page_size; i++) {
|
||||
if(buf[address + i] != 0xFF) {
|
||||
/* Page is not empty. */
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Page is empty. */
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
@@ -763,7 +788,6 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int a_div;
|
||||
int tries;
|
||||
unsigned int n;
|
||||
int block_size;
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
memtype = 'F';
|
||||
@@ -795,21 +819,13 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
|
||||
for (addr = 0; addr < n; addr += page_size) {
|
||||
report_progress (addr, n_bytes, NULL);
|
||||
|
||||
if (addr + page_size > n_bytes) {
|
||||
block_size = n_bytes % page_size;
|
||||
}
|
||||
else {
|
||||
block_size = page_size;
|
||||
}
|
||||
|
||||
tries = 0;
|
||||
retry:
|
||||
tries++;
|
||||
stk500_loadaddr(pgm, addr/a_div);
|
||||
buf[0] = Cmnd_STK_READ_PAGE;
|
||||
buf[1] = (block_size >> 8) & 0xff;
|
||||
buf[2] = block_size & 0xff;
|
||||
buf[1] = (page_size >> 8) & 0xff;
|
||||
buf[2] = page_size & 0xff;
|
||||
buf[3] = memtype;
|
||||
buf[4] = Sync_CRC_EOP;
|
||||
stk500_send(pgm, buf, 5);
|
||||
@@ -832,7 +848,7 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
return -4;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, &m->buf[addr], block_size);
|
||||
stk500_recv(pgm, &m->buf[addr], page_size);
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (buf[0] != Resp_STK_OK) {
|
||||
@@ -844,7 +860,7 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
}
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@@ -899,6 +915,7 @@ static int stk500_set_varef(PROGRAMMER * pgm, double v)
|
||||
|
||||
static int stk500_set_fosc(PROGRAMMER * pgm, double v)
|
||||
{
|
||||
#define fbase 7372800U
|
||||
unsigned prescale, cmatch, fosc;
|
||||
static unsigned ps[] = {
|
||||
1, 8, 32, 64, 128, 256, 1024
|
||||
@@ -907,7 +924,7 @@ static int stk500_set_fosc(PROGRAMMER * pgm, double v)
|
||||
|
||||
prescale = cmatch = 0;
|
||||
if (v > 0.0) {
|
||||
if (v > STK500_XTAL / 2) {
|
||||
if (v > fbase / 2) {
|
||||
const char *unit;
|
||||
if (v > 1e6) {
|
||||
v /= 1e6;
|
||||
@@ -919,22 +936,22 @@ static int stk500_set_fosc(PROGRAMMER * pgm, double v)
|
||||
unit = "Hz";
|
||||
fprintf(stderr,
|
||||
"%s: stk500_set_fosc(): f = %.3f %s too high, using %.3f MHz\n",
|
||||
progname, v, unit, STK500_XTAL / 2e6);
|
||||
fosc = STK500_XTAL / 2;
|
||||
progname, v, unit, fbase / 2e6);
|
||||
fosc = fbase / 2;
|
||||
} else
|
||||
fosc = (unsigned)v;
|
||||
|
||||
for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) {
|
||||
if (fosc >= STK500_XTAL / (256 * ps[idx] * 2)) {
|
||||
if (fosc >= fbase / (256 * ps[idx] * 2)) {
|
||||
/* this prescaler value can handle our frequency */
|
||||
prescale = idx + 1;
|
||||
cmatch = (unsigned)(STK500_XTAL / (2 * fosc * ps[idx])) - 1;
|
||||
cmatch = (unsigned)(fbase / (2 * v * ps[idx]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == sizeof(ps) / sizeof(ps[0])) {
|
||||
fprintf(stderr, "%s: stk500_set_fosc(): f = %u Hz too low, %u Hz min\n",
|
||||
progname, fosc, STK500_XTAL / (256 * 1024 * 2));
|
||||
progname, fosc, fbase / (256 * 1024 * 2));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -947,38 +964,6 @@ static int stk500_set_fosc(PROGRAMMER * pgm, double v)
|
||||
}
|
||||
|
||||
|
||||
/* This code assumes that each count of the SCK duration parameter
|
||||
represents 8/f, where f is the clock frequency of the STK500 master
|
||||
processors (not the target). This number comes from Atmel
|
||||
application note AVR061. It appears that the STK500 bit bangs SCK.
|
||||
For small duration values, the actual SCK width is larger than
|
||||
expected. As the duration value increases, the SCK width error
|
||||
diminishes. */
|
||||
static int stk500_set_sck_period(PROGRAMMER * pgm, double v)
|
||||
{
|
||||
int dur;
|
||||
double min, max;
|
||||
|
||||
min = 8.0 / STK500_XTAL;
|
||||
max = 255 * min;
|
||||
dur = v / min + 0.5;
|
||||
|
||||
if (v < min) {
|
||||
dur = 1;
|
||||
fprintf(stderr,
|
||||
"%s: stk500_set_sck_period(): p = %.1f us too small, using %.1f us\n",
|
||||
progname, v / 1e-6, dur * min / 1e-6);
|
||||
} else if (v > max) {
|
||||
dur = 255;
|
||||
fprintf(stderr,
|
||||
"%s: stk500_set_sck_period(): p = %.1f us too large, using %.1f us\n",
|
||||
progname, v / 1e-6, dur * min / 1e-6);
|
||||
}
|
||||
|
||||
return stk500_setparm(pgm, Parm_STK_SCK_DURATION, dur);
|
||||
}
|
||||
|
||||
|
||||
static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value)
|
||||
{
|
||||
unsigned char buf[16];
|
||||
@@ -1122,13 +1107,12 @@ static void stk500_display(PROGRAMMER * pgm, char * p)
|
||||
|
||||
static void stk500_print_parms1(PROGRAMMER * pgm, char * p)
|
||||
{
|
||||
unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
|
||||
unsigned vtarget, vadjust, osc_pscale, osc_cmatch;
|
||||
|
||||
stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget);
|
||||
stk500_getparm(pgm, Parm_STK_VADJUST, &vadjust);
|
||||
stk500_getparm(pgm, Parm_STK_OSC_PSCALE, &osc_pscale);
|
||||
stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch);
|
||||
stk500_getparm(pgm, Parm_STK_SCK_DURATION, &sck_duration);
|
||||
|
||||
fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
||||
fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0);
|
||||
@@ -1137,7 +1121,7 @@ static void stk500_print_parms1(PROGRAMMER * pgm, char * p)
|
||||
fprintf(stderr, "Off\n");
|
||||
else {
|
||||
int prescale = 1;
|
||||
double f = STK500_XTAL / 2;
|
||||
double f = 3.6864e6;
|
||||
const char *unit;
|
||||
|
||||
switch (osc_pscale) {
|
||||
@@ -1160,8 +1144,6 @@ static void stk500_print_parms1(PROGRAMMER * pgm, char * p)
|
||||
unit = "Hz";
|
||||
fprintf(stderr, "%.3f %s\n", f, unit);
|
||||
}
|
||||
fprintf(stderr, "%sSCK period : %.1f us\n", p,
|
||||
sck_duration * 8.0e6 / STK500_XTAL + 0.05);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1180,10 +1162,18 @@ void stk500_initpgm(PROGRAMMER * pgm)
|
||||
/*
|
||||
* mandatory functions
|
||||
*/
|
||||
pgm->rdy_led = stk500_rdy_led;
|
||||
pgm->err_led = stk500_err_led;
|
||||
pgm->pgm_led = stk500_pgm_led;
|
||||
pgm->vfy_led = stk500_vfy_led;
|
||||
pgm->initialize = stk500_initialize;
|
||||
pgm->display = stk500_display;
|
||||
pgm->save = stk500_save;
|
||||
pgm->restore = stk500_restore;
|
||||
pgm->enable = stk500_enable;
|
||||
pgm->disable = stk500_disable;
|
||||
pgm->powerup = stk500_powerup;
|
||||
pgm->powerdown = stk500_powerdown;
|
||||
pgm->program_enable = stk500_program_enable;
|
||||
pgm->chip_erase = stk500_chip_erase;
|
||||
pgm->cmd = stk500_cmd;
|
||||
@@ -1199,6 +1189,5 @@ void stk500_initpgm(PROGRAMMER * pgm)
|
||||
pgm->set_vtarget = stk500_set_vtarget;
|
||||
pgm->set_varef = stk500_set_varef;
|
||||
pgm->set_fosc = stk500_set_fosc;
|
||||
pgm->set_sck_period = stk500_set_sck_period;
|
||||
pgm->page_size = 256;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2002, 2003 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
|
||||
@@ -22,6 +22,8 @@
|
||||
#ifndef __stk500_h__
|
||||
#define __stk500_h__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
void stk500_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,982 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2005 Erik Walthinsen
|
||||
* Copyright (C) 2002-2004 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$ */
|
||||
/* Based on Id: stk500.c,v 1.46 2004/12/22 01:52:45 bdean Exp */
|
||||
|
||||
/*
|
||||
* avrdude interface for Atmel STK500V2 programmer
|
||||
*
|
||||
* Note: most commands use the "universal command" feature of the
|
||||
* programmer in a "pass through" mode, exceptions are "program
|
||||
* enable", "paged read", and "paged write".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "avr.h"
|
||||
#include "pgm.h"
|
||||
#include "stk500_private.h" // temp until all code converted
|
||||
#include "stk500v2_private.h"
|
||||
#include "serial.h"
|
||||
|
||||
#define STK500V2_XTAL 7372800U
|
||||
|
||||
#if 0
|
||||
#define DEBUG(format,args...) fprintf(stderr, format, ## args)
|
||||
#else
|
||||
#define DEBUG(format,args...)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define DEBUGRECV(format,args...) fprintf(stderr, format, ## args)
|
||||
#else
|
||||
#define DEBUGRECV(format,args...)
|
||||
#endif
|
||||
|
||||
|
||||
extern int verbose;
|
||||
extern char * progname;
|
||||
extern int do_cycles;
|
||||
|
||||
static unsigned char command_sequence = 1;
|
||||
|
||||
|
||||
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value);
|
||||
static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value);
|
||||
static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p);
|
||||
static int stk500v2_is_page_empty(unsigned int address, int page_size,
|
||||
const unsigned char *buf);
|
||||
|
||||
|
||||
static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||
{
|
||||
unsigned char buf[275 + 6]; // max MESSAGE_BODY of 275 bytes, 6 bytes overhead
|
||||
int i;
|
||||
|
||||
buf[0] = MESSAGE_START;
|
||||
buf[1] = command_sequence;
|
||||
buf[2] = len / 256;
|
||||
buf[3] = len % 256;
|
||||
buf[4] = TOKEN;
|
||||
memcpy(buf+5, data, len);
|
||||
|
||||
// calculate the XOR checksum
|
||||
buf[5+len] = 0;
|
||||
for (i=0;i<5+len;i++)
|
||||
buf[5+len] ^= buf[i];
|
||||
|
||||
DEBUG("STK500V2: stk500v2_send(");
|
||||
for (i=0;i<len+6;i++) DEBUG("0x%02x ",buf[i]);
|
||||
DEBUG(", %d)\n",len+6);
|
||||
|
||||
if (serial_send(pgm->fd, buf, len+6) != 0) {
|
||||
fprintf(stderr,"%s: stk500_send(): failed to send command to serial port\n",progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_drain(PROGRAMMER * pgm, int display)
|
||||
{
|
||||
return serial_drain(pgm->fd, display);
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) {
|
||||
enum states { sINIT, sSTART, sSEQNUM, sSIZE1, sSIZE2, sTOKEN, sDATA, sCSUM, sDONE } state = sSTART;
|
||||
int msglen = 0;
|
||||
int curlen = 0;
|
||||
int timeout = 0;
|
||||
unsigned char c, checksum = 0;
|
||||
|
||||
long timeoutval = 5; // seconds
|
||||
struct timeval tv;
|
||||
double tstart, tnow;
|
||||
|
||||
DEBUG("STK500V2: stk500v2_recv(): ");
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
tstart = tv.tv_sec;
|
||||
|
||||
while ( (state != sDONE ) && (!timeout) ) {
|
||||
if (serial_recv(pgm->fd, &c, 1) < 0)
|
||||
goto timedout;
|
||||
DEBUG("0x%02x ",c);
|
||||
checksum ^= c;
|
||||
|
||||
switch (state) {
|
||||
case sSTART:
|
||||
DEBUGRECV("hoping for start token...");
|
||||
if (c == MESSAGE_START) {
|
||||
DEBUGRECV("got it\n");
|
||||
checksum = MESSAGE_START;
|
||||
state = sSEQNUM;
|
||||
} else
|
||||
DEBUGRECV("sorry\n");
|
||||
break;
|
||||
case sSEQNUM:
|
||||
DEBUGRECV("hoping for sequence...\n");
|
||||
if (c == command_sequence) {
|
||||
DEBUGRECV("got it, incrementing\n");
|
||||
state = sSIZE1;
|
||||
command_sequence++;
|
||||
} else {
|
||||
DEBUGRECV("sorry\n");
|
||||
state = sSTART;
|
||||
}
|
||||
break;
|
||||
case sSIZE1:
|
||||
DEBUGRECV("hoping for size LSB\n");
|
||||
msglen = c*256;
|
||||
state = sSIZE2;
|
||||
break;
|
||||
case sSIZE2:
|
||||
DEBUGRECV("hoping for size MSB...");
|
||||
msglen += c;
|
||||
DEBUG(" msg is %d bytes\n",msglen);
|
||||
state = sTOKEN;
|
||||
break;
|
||||
case sTOKEN:
|
||||
if (c == TOKEN) state = sDATA;
|
||||
else state = sSTART;
|
||||
break;
|
||||
case sDATA:
|
||||
if (curlen < maxsize) {
|
||||
msg[curlen] = c;
|
||||
} else {
|
||||
fprintf(stderr, "%s: stk500v2_recv(): buffer too small, received %d byte into %zd byte buffer\n",
|
||||
progname,curlen,maxsize);
|
||||
return -2;
|
||||
}
|
||||
if ((curlen == 0) && (msg[0] == ANSWER_CKSUM_ERROR)) {
|
||||
fprintf(stderr, "%s: stk500v2_recv(): previous packet sent with wrong checksum\n",
|
||||
progname);
|
||||
return -3;
|
||||
}
|
||||
curlen++;
|
||||
if (curlen == msglen) state = sCSUM;
|
||||
break;
|
||||
case sCSUM:
|
||||
if (checksum == 0) {
|
||||
state = sDONE;
|
||||
} else {
|
||||
state = sSTART;
|
||||
fprintf(stderr, "%s: stk500v2_recv(): checksum error\n",
|
||||
progname);
|
||||
return -4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: stk500v2_recv(): unknown state\n",
|
||||
progname);
|
||||
return -5;
|
||||
} /* switch */
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
tnow = tv.tv_sec;
|
||||
if (tnow-tstart > timeoutval) { // wuff - signed/unsigned/overflow
|
||||
timedout:
|
||||
fprintf(stderr, "%s: stk500_2_ReceiveMessage(): timeout\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} /* while */
|
||||
DEBUG("\n");
|
||||
|
||||
return msglen+6;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int stk500v2_getsync(PROGRAMMER * pgm) {
|
||||
int tries = 0;
|
||||
unsigned char buf[1], resp[32];
|
||||
int status;
|
||||
|
||||
DEBUG("STK500V2: stk500v2_getsync()\n");
|
||||
|
||||
retry:
|
||||
tries++;
|
||||
|
||||
// send the sync command and see if we can get there
|
||||
buf[0] = CMD_SIGN_ON;
|
||||
stk500v2_send(pgm, buf, 1);
|
||||
|
||||
// try to get the response back and see where we got
|
||||
status = stk500v2_recv(pgm, resp, sizeof(resp));
|
||||
|
||||
// if we got bytes returned, check to see what came back
|
||||
if (status > 0) {
|
||||
if ((resp[0] == CMD_SIGN_ON) && (resp[1] == STATUS_CMD_OK)) {
|
||||
// success!
|
||||
return 0;
|
||||
} else {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500v2_getsync(): can't communicate with device: resp=0x%02x\n",
|
||||
progname, resp[0]);
|
||||
return -6;
|
||||
} else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
// or if we got a timeout
|
||||
} else if (status == -1) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr,"%s: stk500v2_getsync(): timeout communicating with programmer\n",
|
||||
progname);
|
||||
return -1;
|
||||
} else
|
||||
goto retry;
|
||||
|
||||
// or any other error
|
||||
} else {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr,"%s: stk500v2_getsync(): error communicating with programmer: (%d)\n",
|
||||
progname,status);
|
||||
} else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stk500v2_command(PROGRAMMER * pgm, unsigned char * buf, size_t len, size_t maxlen) {
|
||||
int i;
|
||||
int tries = 0;
|
||||
int status;
|
||||
|
||||
DEBUG("STK500V2: stk500v2_command(");
|
||||
for (i=0;i<len;i++) DEBUG("0x%02hhx ",buf[i]);
|
||||
DEBUG(", %d)\n",len);
|
||||
|
||||
retry:
|
||||
tries++;
|
||||
|
||||
// send the command to the programmer
|
||||
stk500v2_send(pgm,buf,len);
|
||||
|
||||
// attempt to read the status back
|
||||
status = stk500v2_recv(pgm,buf,maxlen);
|
||||
|
||||
// if we got a successful readback, return
|
||||
if (status > 0) {
|
||||
DEBUG(" = %d\n",status);
|
||||
return status;
|
||||
}
|
||||
|
||||
// otherwise try to sync up again
|
||||
status = stk500v2_getsync(pgm);
|
||||
if (status != 0) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr,"%s: stk500v2_command(): failed miserably to execute command 0x%02x\n",
|
||||
progname,buf[0]);
|
||||
return -1;
|
||||
} else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
DEBUG(" = 0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
unsigned char buf[8];
|
||||
int result;
|
||||
|
||||
DEBUG("STK500V2: stk500v2_cmd(%02x,%02x,%02x,%02x)\n",cmd[0],cmd[1],cmd[2],cmd[3]);
|
||||
|
||||
buf[0] = CMD_SPI_MULTI;
|
||||
buf[1] = 4;
|
||||
buf[2] = 4;
|
||||
buf[3] = 0;
|
||||
buf[4] = cmd[0];
|
||||
buf[5] = cmd[1];
|
||||
buf[6] = cmd[2];
|
||||
buf[7] = cmd[3];
|
||||
|
||||
result = stk500v2_command(pgm, buf, 8, sizeof(buf));
|
||||
if (buf[1] != STATUS_CMD_OK) {
|
||||
fprintf(stderr, "%s: stk500v2_cmd(): failed to send command\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res[0] = buf[2];
|
||||
res[1] = buf[3];
|
||||
res[2] = buf[4];
|
||||
res[3] = buf[5];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* issue the 'chip erase' command to the AVR device
|
||||
*/
|
||||
static int stk500v2_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
int result;
|
||||
unsigned char buf[16];
|
||||
|
||||
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
|
||||
fprintf(stderr, "%s: stk500v2_chip_erase: chip erase instruction not defined for part \"%s\"\n",
|
||||
progname, p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pgm->pgm_led(pgm, ON);
|
||||
|
||||
buf[0] = CMD_CHIP_ERASE_ISP;
|
||||
buf[1] = p->chip_erase_delay / 1000;
|
||||
buf[2] = 0; // use delay (?)
|
||||
avr_set_bits(p->op[AVR_OP_CHIP_ERASE], buf+3);
|
||||
result = stk500v2_command(pgm, buf, 7, sizeof(buf));
|
||||
usleep(p->chip_erase_delay);
|
||||
pgm->initialize(pgm, p);
|
||||
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* issue the 'program enable' command to the AVR device
|
||||
*/
|
||||
static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char buf[16];
|
||||
|
||||
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
|
||||
fprintf(stderr, "%s: stk500v2_program_enable(): program enable instruction not defined for part \"%s\"\n",
|
||||
progname, p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[0] = CMD_ENTER_PROGMODE_ISP;
|
||||
buf[1] = p->timeout;
|
||||
buf[2] = p->stabdelay;
|
||||
buf[3] = p->cmdexedelay;
|
||||
buf[4] = p->synchloops;
|
||||
buf[5] = p->bytedelay;
|
||||
buf[6] = p->pollvalue;
|
||||
buf[7] = p->pollindex;
|
||||
avr_set_bits(p->op[AVR_OP_PGM_ENABLE], buf+8);
|
||||
|
||||
return stk500v2_command(pgm, buf, 12, sizeof(buf));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* initialize the AVR device and prepare it to accept commands
|
||||
*/
|
||||
static int stk500v2_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
return pgm->program_enable(pgm, p);
|
||||
}
|
||||
|
||||
|
||||
static void stk500v2_disable(PROGRAMMER * pgm)
|
||||
{
|
||||
unsigned char buf[16];
|
||||
int result;
|
||||
|
||||
buf[0] = CMD_LEAVE_PROGMODE_ISP;
|
||||
buf[1] = 1; // preDelay;
|
||||
buf[2] = 1; // postDelay;
|
||||
|
||||
result = stk500v2_command(pgm, buf, 3, sizeof(buf));
|
||||
|
||||
if (buf[1] != STATUS_CMD_OK) {
|
||||
fprintf(stderr, "%s: stk500v2_disable(): failed to leave programming mode, got 0x%02x\n",
|
||||
progname,buf[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void stk500v2_enable(PROGRAMMER * pgm)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
DEBUG("STK500V2: stk500v2_open()\n");
|
||||
|
||||
strcpy(pgm->port, port);
|
||||
if (pgm->baudrate)
|
||||
pgm->fd = serial_open(port, pgm->baudrate);
|
||||
else
|
||||
pgm->fd = serial_open(port, 115200);
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
stk500v2_drain(pgm, 0);
|
||||
|
||||
stk500v2_getsync(pgm);
|
||||
|
||||
stk500v2_drain(pgm, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void stk500v2_close(PROGRAMMER * pgm)
|
||||
{
|
||||
DEBUG("STK500V2: stk500v2_close()\n");
|
||||
|
||||
serial_close(pgm->fd);
|
||||
pgm->fd = -1;
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_loadaddr(PROGRAMMER * pgm, unsigned int addr)
|
||||
{
|
||||
unsigned char buf[16];
|
||||
int result;
|
||||
|
||||
DEBUG("STK500V2: stk500v2_loadaddr(%d)\n",addr);
|
||||
|
||||
buf[0] = CMD_LOAD_ADDRESS;
|
||||
buf[1] = (addr >> 24) & 0xff;
|
||||
buf[2] = (addr >> 16) & 0xff;
|
||||
buf[3] = (addr >> 8) & 0xff;
|
||||
buf[4] = addr & 0xff;
|
||||
|
||||
result = stk500v2_command(pgm, buf, 5, sizeof(buf));
|
||||
|
||||
if (buf[1] != STATUS_CMD_OK) {
|
||||
fprintf(stderr, "%s: stk500v2_loadaddr(): failed to set load address, got 0x%02x\n",
|
||||
progname,buf[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
int addr, block_size, last_addr;
|
||||
int a_div=1;
|
||||
unsigned char commandbuf[10];
|
||||
unsigned char buf[266];
|
||||
unsigned char cmds[4];
|
||||
int result;
|
||||
OPCODE * rop, * wop;
|
||||
|
||||
DEBUG("STK500V2: stk500v2_paged_write(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
|
||||
|
||||
if (page_size == 0) page_size = 256;
|
||||
|
||||
// determine which command is to be used
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
a_div=2;
|
||||
commandbuf[0] = CMD_PROGRAM_FLASH_ISP;
|
||||
} else if (strcmp(m->desc, "eeprom") == 0) {
|
||||
commandbuf[0] = CMD_PROGRAM_EEPROM_ISP;
|
||||
}
|
||||
commandbuf[4] = m->delay;
|
||||
|
||||
if (a_div == 1) {
|
||||
wop = m->op[AVR_OP_WRITE];
|
||||
rop = m->op[AVR_OP_READ];
|
||||
}
|
||||
else {
|
||||
wop = m->op[AVR_OP_WRITE_LO];
|
||||
rop = m->op[AVR_OP_READ_LO];
|
||||
}
|
||||
|
||||
// if the memory is paged, load the appropriate commands into the buffer
|
||||
if (m->mode & 0x01) {
|
||||
commandbuf[3] = m->mode | 0x80; // yes, write the page to flash
|
||||
|
||||
if (m->op[AVR_OP_LOADPAGE_LO] == NULL) {
|
||||
fprintf(stderr, "%s: stk500v2_paged_write: loadpage instruction not defined for part \"%s\"\n",
|
||||
progname, p->desc);
|
||||
return -1;
|
||||
}
|
||||
avr_set_bits(m->op[AVR_OP_LOADPAGE_LO], cmds);
|
||||
commandbuf[5] = cmds[0];
|
||||
|
||||
if (m->op[AVR_OP_WRITEPAGE] == NULL) {
|
||||
fprintf(stderr, "%s: stk500v2_paged_write: write page instruction not defined for part \"%s\"\n",
|
||||
progname, p->desc);
|
||||
return -1;
|
||||
}
|
||||
avr_set_bits(m->op[AVR_OP_WRITEPAGE], cmds);
|
||||
commandbuf[6] = cmds[0];
|
||||
|
||||
// otherwise, we need to load different commands in
|
||||
}
|
||||
else {
|
||||
commandbuf[3] = m->mode | 0x80; // yes, write the words to flash
|
||||
|
||||
if (wop == NULL) {
|
||||
fprintf(stderr, "%s: stk500v2_paged_write: write instruction not defined for part \"%s\"\n",
|
||||
progname, p->desc);
|
||||
return -1;
|
||||
}
|
||||
avr_set_bits(wop, cmds);
|
||||
commandbuf[5] = cmds[0];
|
||||
commandbuf[6] = 0;
|
||||
}
|
||||
|
||||
// the read command is common to both methods
|
||||
if (rop == NULL) {
|
||||
fprintf(stderr, "%s: stk500v2_paged_write: read instruction not defined for part \"%s\"\n",
|
||||
progname, p->desc);
|
||||
return -1;
|
||||
}
|
||||
avr_set_bits(rop, cmds);
|
||||
commandbuf[7] = cmds[0];
|
||||
|
||||
commandbuf[8] = m->readback[0];
|
||||
commandbuf[9] = m->readback[1];
|
||||
|
||||
last_addr=-1;
|
||||
|
||||
for (addr=0; addr < n_bytes; addr += page_size) {
|
||||
report_progress(addr,n_bytes,NULL);
|
||||
|
||||
if ((n_bytes-addr) < page_size)
|
||||
block_size = n_bytes - addr;
|
||||
else
|
||||
block_size = page_size;
|
||||
|
||||
DEBUG("block_size at addr %d is %d\n",addr,block_size);
|
||||
|
||||
if(commandbuf[0] == CMD_PROGRAM_FLASH_ISP){
|
||||
if (stk500v2_is_page_empty(addr, block_size, m->buf)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buf,commandbuf,sizeof(commandbuf));
|
||||
|
||||
buf[1] = block_size >> 8;
|
||||
buf[2] = block_size & 0xff;
|
||||
|
||||
if((last_addr==-1)||(last_addr+block_size != addr)){
|
||||
stk500v2_loadaddr(pgm, addr/a_div);
|
||||
}
|
||||
last_addr=addr;
|
||||
|
||||
memcpy(buf+10,m->buf+addr, block_size);
|
||||
|
||||
result = stk500v2_command(pgm,buf,block_size+10, sizeof(buf));
|
||||
if (buf[1] != STATUS_CMD_OK) {
|
||||
fprintf(stderr,"%s: stk500v2_paged_write: write command failed with %d\n",
|
||||
progname,buf[1]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
static int stk500v2_is_page_empty(unsigned int address, int page_size,
|
||||
const unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < page_size; i++) {
|
||||
if(buf[address + i] != 0xFF) {
|
||||
/* Page is not empty. */
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Page is empty. */
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int stk500v2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
int addr, block_size;
|
||||
unsigned char commandbuf[4];
|
||||
unsigned char buf[275]; // max buffer size for stk500v2 at this point
|
||||
unsigned char cmds[4];
|
||||
int result;
|
||||
OPCODE * rop;
|
||||
|
||||
DEBUG("STK500V2: stk500v2_paged_load(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
|
||||
|
||||
page_size = m->readsize;
|
||||
|
||||
rop = m->op[AVR_OP_READ];
|
||||
|
||||
// determine which command is to be used
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
commandbuf[0] = CMD_READ_FLASH_ISP;
|
||||
rop = m->op[AVR_OP_READ_LO];
|
||||
}
|
||||
else if (strcmp(m->desc, "eeprom") == 0) {
|
||||
commandbuf[0] = CMD_READ_EEPROM_ISP;
|
||||
}
|
||||
|
||||
// the read command is common to both methods
|
||||
if (rop == NULL) {
|
||||
fprintf(stderr, "%s: stk500v2_paged_load: read instruction not defined for part \"%s\"\n",
|
||||
progname, p->desc);
|
||||
return -1;
|
||||
}
|
||||
avr_set_bits(rop, cmds);
|
||||
commandbuf[3] = cmds[0];
|
||||
|
||||
stk500v2_loadaddr(pgm, 0);
|
||||
|
||||
for (addr=0; addr < n_bytes; addr += page_size) {
|
||||
report_progress(addr, n_bytes,NULL);
|
||||
|
||||
if ((n_bytes-addr) < page_size)
|
||||
block_size = n_bytes - addr;
|
||||
else
|
||||
block_size = page_size;
|
||||
DEBUG("block_size at addr %d is %d\n",addr,block_size);
|
||||
|
||||
memcpy(buf,commandbuf,sizeof(commandbuf));
|
||||
|
||||
buf[1] = block_size >> 8;
|
||||
buf[2] = block_size & 0xff;
|
||||
|
||||
result = stk500v2_command(pgm,buf,4,sizeof(buf));
|
||||
if (buf[1] != STATUS_CMD_OK) {
|
||||
fprintf(stderr,"%s: stk500v2_paged_load: read command failed with %d\n",
|
||||
progname,buf[1]);
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
for (i=0;i<page_size;i++) {
|
||||
fprintf(stderr,"%02X",buf[2+i]);
|
||||
if (i%16 == 15) fprintf(stderr,"\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(&m->buf[addr], &buf[2], block_size);
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_set_vtarget(PROGRAMMER * pgm, double v)
|
||||
{
|
||||
unsigned char uaref, utarg;
|
||||
|
||||
utarg = (unsigned)((v + 0.049) * 10);
|
||||
|
||||
if (stk500v2_getparm(pgm, PARAM_VADJUST, &uaref) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500v2_set_vtarget(): cannot obtain V[aref]\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uaref > utarg) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500v2_set_vtarget(): reducing V[aref] from %.1f to %.1f\n",
|
||||
progname, uaref / 10.0, v);
|
||||
if (stk500v2_setparm(pgm, PARAM_VADJUST, utarg)
|
||||
!= 0)
|
||||
return -1;
|
||||
}
|
||||
return stk500v2_setparm(pgm, PARAM_VTARGET, utarg);
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_set_varef(PROGRAMMER * pgm, double v)
|
||||
{
|
||||
unsigned char uaref, utarg;
|
||||
|
||||
uaref = (unsigned)((v + 0.049) * 10);
|
||||
|
||||
if (stk500v2_getparm(pgm, PARAM_VTARGET, &utarg) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500v2_set_varef(): cannot obtain V[target]\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uaref > utarg) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500v2_set_varef(): V[aref] must not be greater than "
|
||||
"V[target] = %.1f\n",
|
||||
progname, utarg / 10.0);
|
||||
return -1;
|
||||
}
|
||||
return stk500v2_setparm(pgm, PARAM_VADJUST, uaref);
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_set_fosc(PROGRAMMER * pgm, double v)
|
||||
{
|
||||
int fosc;
|
||||
unsigned char prescale, cmatch;
|
||||
static unsigned ps[] = {
|
||||
1, 8, 32, 64, 128, 256, 1024
|
||||
};
|
||||
int idx, rc;
|
||||
|
||||
prescale = cmatch = 0;
|
||||
if (v > 0.0) {
|
||||
if (v > STK500V2_XTAL / 2) {
|
||||
const char *unit;
|
||||
if (v > 1e6) {
|
||||
v /= 1e6;
|
||||
unit = "MHz";
|
||||
} else if (v > 1e3) {
|
||||
v /= 1e3;
|
||||
unit = "kHz";
|
||||
} else
|
||||
unit = "Hz";
|
||||
fprintf(stderr,
|
||||
"%s: stk500v2_set_fosc(): f = %.3f %s too high, using %.3f MHz\n",
|
||||
progname, v, unit, STK500V2_XTAL / 2e6);
|
||||
fosc = STK500V2_XTAL / 2;
|
||||
} else
|
||||
fosc = (unsigned)v;
|
||||
|
||||
for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) {
|
||||
if (fosc >= STK500V2_XTAL / (256 * ps[idx] * 2)) {
|
||||
/* this prescaler value can handle our frequency */
|
||||
prescale = idx + 1;
|
||||
cmatch = (unsigned)(STK500V2_XTAL / (2 * fosc * ps[idx])) - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == sizeof(ps) / sizeof(ps[0])) {
|
||||
fprintf(stderr, "%s: stk500v2_set_fosc(): f = %u Hz too low, %u Hz min\n",
|
||||
progname, fosc, STK500V2_XTAL / (256 * 1024 * 2));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rc = stk500v2_setparm(pgm, PARAM_OSC_PSCALE, prescale)) != 0
|
||||
|| (rc = stk500v2_setparm(pgm, PARAM_OSC_CMATCH, cmatch)) != 0)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* This code assumes that each count of the SCK duration parameter
|
||||
represents 8/f, where f is the clock frequency of the STK500V2 master
|
||||
processors (not the target). This number comes from Atmel
|
||||
application note AVR061. It appears that the STK500V2 bit bangs SCK.
|
||||
For small duration values, the actual SCK width is larger than
|
||||
expected. As the duration value increases, the SCK width error
|
||||
diminishes. */
|
||||
static int stk500v2_set_sck_period(PROGRAMMER * pgm, double v)
|
||||
{
|
||||
unsigned char dur;
|
||||
double min, max;
|
||||
|
||||
min = 8.0 / STK500V2_XTAL;
|
||||
max = 255 * min;
|
||||
dur = v / min + 0.5;
|
||||
|
||||
if (v < min) {
|
||||
dur = 1;
|
||||
fprintf(stderr,
|
||||
"%s: stk500v2_set_sck_period(): p = %.1f us too small, using %.1f us\n",
|
||||
progname, v / 1e-6, dur * min / 1e-6);
|
||||
} else if (v > max) {
|
||||
dur = 255;
|
||||
fprintf(stderr,
|
||||
"%s: stk500v2_set_sck_period(): p = %.1f us too large, using %.1f us\n",
|
||||
progname, v / 1e-6, dur * min / 1e-6);
|
||||
}
|
||||
|
||||
return stk500v2_setparm(pgm, PARAM_SCK_DURATION, dur);
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
|
||||
buf[0] = CMD_GET_PARAMETER;
|
||||
buf[1] = parm;
|
||||
|
||||
if (stk500v2_command(pgm, buf, 2, sizeof(buf)) < 0) {
|
||||
fprintf(stderr,"%s: stk500v2_getparm(): failed to get parameter 0x%02x\n",
|
||||
progname, parm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*value = buf[2];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
|
||||
buf[0] = CMD_SET_PARAMETER;
|
||||
buf[1] = parm;
|
||||
buf[2] = value;
|
||||
|
||||
if (stk500v2_command(pgm, buf, 3, sizeof(buf)) < 0) {
|
||||
fprintf(stderr, "\n%s: stk500v2_setparm(): failed to set parameter 0x%02x\n",
|
||||
progname, parm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void stk500v2_display(PROGRAMMER * pgm, char * p)
|
||||
{
|
||||
unsigned char maj, min, hdw, topcard;
|
||||
const char *topcard_name;
|
||||
|
||||
stk500v2_getparm(pgm, PARAM_HW_VER, &hdw);
|
||||
stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
|
||||
stk500v2_getparm(pgm, PARAM_SW_MINOR, &min);
|
||||
stk500v2_getparm(pgm, PARAM_TOPCARD_DETECT, &topcard);
|
||||
|
||||
fprintf(stderr, "%sHardware Version: %d\n", p, hdw);
|
||||
fprintf(stderr, "%sFirmware Version: %d.%d\n", p, maj, min);
|
||||
|
||||
if (1) { // should check to see if it's a stk500 first
|
||||
switch (topcard) {
|
||||
case 0xAA: topcard_name = "STK501"; break;
|
||||
case 0x55: topcard_name = "STK502"; break;
|
||||
case 0xFA: topcard_name = "STK503"; break;
|
||||
case 0xEE: topcard_name = "STK504"; break;
|
||||
case 0xE4: topcard_name = "STK505"; break;
|
||||
case 0xDD: topcard_name = "STK520"; break;
|
||||
default: topcard_name = "Unknown"; break;
|
||||
}
|
||||
fprintf(stderr, "%sTopcard : %s\n", p, topcard_name);
|
||||
}
|
||||
stk500v2_print_parms1(pgm, p);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p)
|
||||
{
|
||||
unsigned char vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
|
||||
|
||||
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
|
||||
stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust);
|
||||
stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
|
||||
stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
|
||||
stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
|
||||
|
||||
fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
||||
fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0);
|
||||
fprintf(stderr, "%sOscillator : ", p);
|
||||
if (osc_pscale == 0)
|
||||
fprintf(stderr, "Off\n");
|
||||
else {
|
||||
int prescale = 1;
|
||||
double f = STK500V2_XTAL / 2;
|
||||
const char *unit;
|
||||
|
||||
switch (osc_pscale) {
|
||||
case 2: prescale = 8; break;
|
||||
case 3: prescale = 32; break;
|
||||
case 4: prescale = 64; break;
|
||||
case 5: prescale = 128; break;
|
||||
case 6: prescale = 256; break;
|
||||
case 7: prescale = 1024; break;
|
||||
}
|
||||
f /= prescale;
|
||||
f /= (osc_cmatch + 1);
|
||||
if (f > 1e6) {
|
||||
f /= 1e6;
|
||||
unit = "MHz";
|
||||
} else if (f > 1e3) {
|
||||
f /= 1000;
|
||||
unit = "kHz";
|
||||
} else
|
||||
unit = "Hz";
|
||||
fprintf(stderr, "%.3f %s\n", f, unit);
|
||||
}
|
||||
fprintf(stderr, "%sSCK period : %.1f us\n", p,
|
||||
sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void stk500v2_print_parms(PROGRAMMER * pgm)
|
||||
{
|
||||
stk500v2_print_parms1(pgm, "");
|
||||
}
|
||||
|
||||
|
||||
void stk500v2_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
strcpy(pgm->type, "STK500V2");
|
||||
|
||||
/*
|
||||
* mandatory functions
|
||||
*/
|
||||
pgm->initialize = stk500v2_initialize;
|
||||
pgm->display = stk500v2_display;
|
||||
pgm->enable = stk500v2_enable;
|
||||
pgm->disable = stk500v2_disable;
|
||||
pgm->program_enable = stk500v2_program_enable;
|
||||
pgm->chip_erase = stk500v2_chip_erase;
|
||||
pgm->cmd = stk500v2_cmd;
|
||||
pgm->open = stk500v2_open;
|
||||
pgm->close = stk500v2_close;
|
||||
|
||||
/*
|
||||
* optional functions
|
||||
*/
|
||||
pgm->paged_write = stk500v2_paged_write;
|
||||
pgm->paged_load = stk500v2_paged_load;
|
||||
pgm->print_parms = stk500v2_print_parms;
|
||||
pgm->set_vtarget = stk500v2_set_vtarget;
|
||||
pgm->set_varef = stk500v2_set_varef;
|
||||
pgm->set_fosc = stk500v2_set_fosc;
|
||||
pgm->set_sck_period = stk500v2_set_sck_period;
|
||||
pgm->page_size = 256;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-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$ */
|
||||
|
||||
#ifndef stk500v2_h__
|
||||
#define stk500v2_h__
|
||||
|
||||
void stk500v2_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
//**** ATMEL AVR - A P P L I C A T I O N N O T E ************************
|
||||
//*
|
||||
//* Title: AVR068 - STK500 Communication Protocol
|
||||
//* Filename: command.h
|
||||
//* Version: 1.0
|
||||
//* Last updated: 10.01.2005
|
||||
//*
|
||||
//* Support E-mail: avr@atmel.com
|
||||
//*
|
||||
//**************************************************************************
|
||||
|
||||
// *****************[ STK message constants ]***************************
|
||||
|
||||
#define MESSAGE_START 0x1B //= ESC = 27 decimal
|
||||
#define TOKEN 0x0E
|
||||
|
||||
// *****************[ STK general command constants ]**************************
|
||||
|
||||
#define CMD_SIGN_ON 0x01
|
||||
#define CMD_SET_PARAMETER 0x02
|
||||
#define CMD_GET_PARAMETER 0x03
|
||||
#define CMD_SET_DEVICE_PARAMETERS 0x04
|
||||
#define CMD_OSCCAL 0x05
|
||||
#define CMD_LOAD_ADDRESS 0x06
|
||||
#define CMD_FIRMWARE_UPGRADE 0x07
|
||||
|
||||
|
||||
// *****************[ STK ISP command constants ]******************************
|
||||
|
||||
#define CMD_ENTER_PROGMODE_ISP 0x10
|
||||
#define CMD_LEAVE_PROGMODE_ISP 0x11
|
||||
#define CMD_CHIP_ERASE_ISP 0x12
|
||||
#define CMD_PROGRAM_FLASH_ISP 0x13
|
||||
#define CMD_READ_FLASH_ISP 0x14
|
||||
#define CMD_PROGRAM_EEPROM_ISP 0x15
|
||||
#define CMD_READ_EEPROM_ISP 0x16
|
||||
#define CMD_PROGRAM_FUSE_ISP 0x17
|
||||
#define CMD_READ_FUSE_ISP 0x18
|
||||
#define CMD_PROGRAM_LOCK_ISP 0x19
|
||||
#define CMD_READ_LOCK_ISP 0x1A
|
||||
#define CMD_READ_SIGNATURE_ISP 0x1B
|
||||
#define CMD_READ_OSCCAL_ISP 0x1C
|
||||
#define CMD_SPI_MULTI 0x1D
|
||||
|
||||
// *****************[ STK PP command constants ]*******************************
|
||||
|
||||
#define CMD_ENTER_PROGMODE_PP 0x20
|
||||
#define CMD_LEAVE_PROGMODE_PP 0x21
|
||||
#define CMD_CHIP_ERASE_PP 0x22
|
||||
#define CMD_PROGRAM_FLASH_PP 0x23
|
||||
#define CMD_READ_FLASH_PP 0x24
|
||||
#define CMD_PROGRAM_EEPROM_PP 0x25
|
||||
#define CMD_READ_EEPROM_PP 0x26
|
||||
#define CMD_PROGRAM_FUSE_PP 0x27
|
||||
#define CMD_READ_FUSE_PP 0x28
|
||||
#define CMD_PROGRAM_LOCK_PP 0x29
|
||||
#define CMD_READ_LOCK_PP 0x2A
|
||||
#define CMD_READ_SIGNATURE_PP 0x2B
|
||||
#define CMD_READ_OSCCAL_PP 0x2C
|
||||
|
||||
#define CMD_SET_CONTROL_STACK 0x2D
|
||||
|
||||
// *****************[ STK HVSP command constants ]*****************************
|
||||
|
||||
#define CMD_ENTER_PROGMODE_HVSP 0x30
|
||||
#define CMD_LEAVE_PROGMODE_HVSP 0x31
|
||||
#define CMD_CHIP_ERASE_HVSP 0x32
|
||||
#define CMD_PROGRAM_FLASH_HVSP 0x33
|
||||
#define CMD_READ_FLASH_HVSP 0x34
|
||||
#define CMD_PROGRAM_EEPROM_HVSP 0x35
|
||||
#define CMD_READ_EEPROM_HVSP 0x36
|
||||
#define CMD_PROGRAM_FUSE_HVSP 0x37
|
||||
#define CMD_READ_FUSE_HVSP 0x38
|
||||
#define CMD_PROGRAM_LOCK_HVSP 0x39
|
||||
#define CMD_READ_LOCK_HVSP 0x3A
|
||||
#define CMD_READ_SIGNATURE_HVSP 0x3B
|
||||
#define CMD_READ_OSCCAL_HVSP 0x3C
|
||||
|
||||
// *****************[ STK test command constants ]***************************
|
||||
|
||||
#define CMD_ENTER_TESTMODE 0x60
|
||||
#define CMD_LEAVE_TESTMODE 0x61
|
||||
#define CMD_CHIP_WRITE 0x62
|
||||
#define CMD_PROGRAM_FLASH_PARTIAL 0x63
|
||||
#define CMD_PROGRAM_EEPROM_PARTIAL 0x64
|
||||
#define CMD_PROGRAM_SIGNATURE_ROW 0x65
|
||||
#define CMD_READ_FLASH_MARGIN 0x66
|
||||
#define CMD_READ_EEPROM_MARGIN 0x67
|
||||
#define CMD_READ_SIGNATURE_ROW_MARGIN 0x68
|
||||
#define CMD_PROGRAM_TEST_FUSE 0x69
|
||||
#define CMD_READ_TEST_FUSE 0x6A
|
||||
#define CMD_PROGRAM_HIDDEN_FUSE_LOW 0x6B
|
||||
#define CMD_READ_HIDDEN_FUSE_LOW 0x6C
|
||||
#define CMD_PROGRAM_HIDDEN_FUSE_HIGH 0x6D
|
||||
#define CMD_READ_HIDDEN_FUSE_HIGH 0x6E
|
||||
#define CMD_PROGRAM_HIDDEN_FUSE_EXT 0x6F
|
||||
#define CMD_READ_HIDDEN_FUSE_EXT 0x70
|
||||
|
||||
// *****************[ STK status constants ]***************************
|
||||
|
||||
// Success
|
||||
#define STATUS_CMD_OK 0x00
|
||||
|
||||
// Warnings
|
||||
#define STATUS_CMD_TOUT 0x80
|
||||
#define STATUS_RDY_BSY_TOUT 0x81
|
||||
#define STATUS_SET_PARAM_MISSING 0x82
|
||||
|
||||
// Errors
|
||||
#define STATUS_CMD_FAILED 0xC0
|
||||
#define STATUS_CKSUM_ERROR 0xC1
|
||||
#define STATUS_CMD_UNKNOWN 0xC9
|
||||
|
||||
// *****************[ STK parameter constants ]***************************
|
||||
#define PARAM_BUILD_NUMBER_LOW 0x80
|
||||
#define PARAM_BUILD_NUMBER_HIGH 0x81
|
||||
#define PARAM_HW_VER 0x90
|
||||
#define PARAM_SW_MAJOR 0x91
|
||||
#define PARAM_SW_MINOR 0x92
|
||||
#define PARAM_VTARGET 0x94
|
||||
#define PARAM_VADJUST 0x95
|
||||
#define PARAM_OSC_PSCALE 0x96
|
||||
#define PARAM_OSC_CMATCH 0x97
|
||||
#define PARAM_SCK_DURATION 0x98
|
||||
#define PARAM_TOPCARD_DETECT 0x9A
|
||||
#define PARAM_STATUS 0x9C
|
||||
#define PARAM_DATA 0x9D
|
||||
#define PARAM_RESET_POLARITY 0x9E
|
||||
#define PARAM_CONTROLLER_INIT 0x9F
|
||||
|
||||
// *****************[ STK answer constants ]***************************
|
||||
|
||||
#define ANSWER_CKSUM_ERROR 0xB0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -21,18 +21,14 @@
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(HAVE_LIBREADLINE)
|
||||
#if !defined(WIN32NATIVE)
|
||||
# include <readline/readline.h>
|
||||
# include <readline/history.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "avr.h"
|
||||
#include "config.h"
|
||||
@@ -78,8 +74,6 @@ int cmd_varef (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
|
||||
|
||||
int cmd_fosc (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
|
||||
|
||||
int cmd_sck (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
|
||||
|
||||
|
||||
struct command cmd[] = {
|
||||
{ "dump", cmd_dump, "dump memory : %s <memtype> <addr> <N-Bytes>" },
|
||||
@@ -93,7 +87,6 @@ struct command cmd[] = {
|
||||
{ "vtarg", cmd_vtarg, "set <V[target]> (STK500 only)" },
|
||||
{ "varef", cmd_varef, "set <V[aref]> (STK500 only)" },
|
||||
{ "fosc", cmd_fosc, "set <oscillator frequency> (STK500 only)" },
|
||||
{ "sck", cmd_sck, "set <SCK period> (STK500 only)" },
|
||||
{ "help", cmd_help, "help" },
|
||||
{ "?", cmd_help, "help" },
|
||||
{ "quit", cmd_quit, "quit" }
|
||||
@@ -600,38 +593,6 @@ int cmd_fosc(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
|
||||
}
|
||||
|
||||
|
||||
int cmd_sck(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
|
||||
{
|
||||
int rc;
|
||||
double v;
|
||||
char *endp;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: sck <value>\n");
|
||||
return -1;
|
||||
}
|
||||
v = strtod(argv[1], &endp);
|
||||
if (endp == argv[1]) {
|
||||
fprintf(stderr, "%s (sck): can't parse period \"%s\"\n",
|
||||
progname, argv[1]);
|
||||
return -1;
|
||||
}
|
||||
v *= 1e-6; /* Convert from microseconds to seconds. */
|
||||
if (pgm->set_sck_period == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s (sck): the %s programmer cannot set SCK period\n",
|
||||
progname, pgm->type);
|
||||
return -2;
|
||||
}
|
||||
if ((rc = pgm->set_sck_period(pgm, v)) != 0) {
|
||||
fprintf(stderr, "%s (sck): failed to set SCK period (rc = %d)\n",
|
||||
progname, rc);
|
||||
return -3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_varef(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
|
||||
{
|
||||
int rc;
|
||||
@@ -791,7 +752,7 @@ int do_cmd(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
|
||||
|
||||
char * terminal_get_input(const char *prompt)
|
||||
{
|
||||
#if defined(HAVE_LIBREADLINE) && !defined(WIN32NATIVE)
|
||||
#if defined(HAVE_LIBREADLINE)
|
||||
char *input;
|
||||
input = readline(prompt);
|
||||
if ((input != NULL) && (strlen(input) >= 1))
|
||||
@@ -804,7 +765,7 @@ char * terminal_get_input(const char *prompt)
|
||||
if (fgets(input, sizeof(input), stdin))
|
||||
{
|
||||
/* FIXME: readline strips the '\n', should this too? */
|
||||
return strdup(input);
|
||||
strdup(input);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 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
|
||||
@@ -26,6 +26,5 @@
|
||||
#include "pgm.h"
|
||||
|
||||
int terminal_mode(PROGRAMMER * pgm, struct avrpart * p);
|
||||
char * terminal_get_input(const char *prompt);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2005 Joerg Wunsch
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
/*
|
||||
* USB interface via libusb for avrdude.
|
||||
*/
|
||||
|
||||
#include "ac_cfg.h"
|
||||
#if defined(HAVE_LIBUSB)
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <usb.h>
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
extern char *progname;
|
||||
extern int verbose;
|
||||
|
||||
#define USB_VENDOR_ATMEL 1003
|
||||
#define USB_DEVICE_JTAGICEMKII 0x2103
|
||||
/*
|
||||
* Should we query the endpoint number and max transfer size from USB?
|
||||
* After all, the JTAG ICE mkII docs document these values.
|
||||
*/
|
||||
#define JTAGICE_BULK_EP 2
|
||||
#define JTAGICE_MAX_XFER 64
|
||||
|
||||
static char usbbuf[JTAGICE_MAX_XFER];
|
||||
static int buflen = -1, bufptr;
|
||||
|
||||
static int usbdev_open(char * port, long baud)
|
||||
{
|
||||
char string[256];
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *udev;
|
||||
char *serno, *cp2;
|
||||
size_t x;
|
||||
|
||||
/*
|
||||
* The syntax for usb devices is defined as:
|
||||
*
|
||||
* -P usb[:serialnumber]
|
||||
*
|
||||
* See if we've got a serial number passed here. The serial number
|
||||
* might contain colons which we remove below, and we compare it
|
||||
* right-to-left, so only the least significant nibbles need to be
|
||||
* specified.
|
||||
*/
|
||||
if ((serno = strchr(port, ':')) != NULL)
|
||||
{
|
||||
/* first, drop all colons there if any */
|
||||
cp2 = ++serno;
|
||||
|
||||
while ((cp2 = strchr(cp2, ':')) != NULL)
|
||||
{
|
||||
x = strlen(cp2) - 1;
|
||||
memmove(cp2, cp2 + 1, x);
|
||||
cp2[x] = '\0';
|
||||
}
|
||||
|
||||
if (strlen(serno) > 12)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): invalid serial number \"%s\"\n",
|
||||
progname, serno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
usb_init();
|
||||
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
for (bus = usb_busses; bus; bus = bus->next)
|
||||
{
|
||||
for (dev = bus->devices; dev; dev = dev->next)
|
||||
{
|
||||
udev = usb_open(dev);
|
||||
if (udev)
|
||||
{
|
||||
if (dev->descriptor.idVendor == USB_VENDOR_ATMEL &&
|
||||
dev->descriptor.idProduct == USB_DEVICE_JTAGICEMKII)
|
||||
{
|
||||
/* yeah, we found something */
|
||||
if (usb_get_string_simple(udev,
|
||||
dev->descriptor.iSerialNumber,
|
||||
string, sizeof(string)) < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usb_open(): cannot read serial number \"%s\"\n",
|
||||
progname, usb_strerror());
|
||||
/*
|
||||
* On some systems, libusb appears to have
|
||||
* problems sending control messages. Catch the
|
||||
* benign case where the user did not request a
|
||||
* particular serial number, so we could
|
||||
* continue anyway.
|
||||
*/
|
||||
if (serno != NULL)
|
||||
exit(1); /* no chance */
|
||||
else
|
||||
strcpy(string, "[unknown]");
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
"%s: usb_open(): Found JTAG ICE, serno: %s\n",
|
||||
progname, string);
|
||||
if (serno != NULL)
|
||||
{
|
||||
/*
|
||||
* See if the serial number requested by the
|
||||
* user matches what we found, matching
|
||||
* right-to-left.
|
||||
*/
|
||||
x = strlen(string) - strlen(serno);
|
||||
if (strcasecmp(string + x, serno) != 0)
|
||||
{
|
||||
if (verbose > 2)
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): serial number doesn't match\n",
|
||||
progname);
|
||||
usb_close(udev);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)udev;
|
||||
}
|
||||
usb_close(udev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: usbdev_open(): did not find any%s USB device \"%s\"\n",
|
||||
progname, serno? " (matching)": "", port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int usbdev_setspeed(int fd, long baud)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usbdev_close(int fd)
|
||||
{
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd;
|
||||
|
||||
usb_close(udev);
|
||||
}
|
||||
|
||||
|
||||
static int usbdev_send(int fd, unsigned char *bp, size_t mlen)
|
||||
{
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd;
|
||||
|
||||
return usb_bulk_write(udev, JTAGICE_BULK_EP, (char *)bp, mlen, 5000) != mlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* As calls to usb_bulk_read() result in exactly one USB request, we
|
||||
* have to buffer the read results ourselves, so the single-char read
|
||||
* requests performed by the upper layers will be handled. In order
|
||||
* to do this, we maintain a private buffer of what we've got so far,
|
||||
* and transparently issue another USB read request if the buffer is
|
||||
* empty and more data are requested.
|
||||
*/
|
||||
static int
|
||||
usb_fill_buf(usb_dev_handle *udev)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = usb_bulk_read(udev, JTAGICE_BULK_EP, usbbuf, JTAGICE_MAX_XFER, 5000);
|
||||
if (rv < 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
fprintf(stderr, "%s: usb_fill_buf(): usb_bulk_read() error %s\n",
|
||||
progname, usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
buflen = rv;
|
||||
bufptr = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbdev_recv(int fd, unsigned char *buf, size_t nbytes)
|
||||
{
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd;
|
||||
int i, amnt;
|
||||
unsigned char * p = buf;
|
||||
|
||||
for (i = 0; nbytes > 0;)
|
||||
{
|
||||
if (buflen <= bufptr)
|
||||
{
|
||||
if (usb_fill_buf(udev) < 0)
|
||||
return -1;
|
||||
}
|
||||
amnt = buflen - bufptr > nbytes? nbytes: buflen - bufptr;
|
||||
memcpy(buf + i, usbbuf + bufptr, amnt);
|
||||
bufptr += amnt;
|
||||
nbytes -= amnt;
|
||||
i += amnt;
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
{
|
||||
fprintf(stderr, "%s: Recv: ", progname);
|
||||
|
||||
while (i) {
|
||||
unsigned char c = *p;
|
||||
if (isprint(c)) {
|
||||
fprintf(stderr, "%c ", c);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, ". ");
|
||||
}
|
||||
fprintf(stderr, "[%02x] ", c);
|
||||
|
||||
p++;
|
||||
i--;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int usbdev_drain(int fd, int display)
|
||||
{
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd;
|
||||
int rv;
|
||||
|
||||
do {
|
||||
rv = usb_bulk_read(udev, JTAGICE_BULK_EP, usbbuf, JTAGICE_MAX_XFER, 100);
|
||||
if (rv > 0 && verbose >= 4)
|
||||
fprintf(stderr, "%s: usbdev_drain(): flushed %d characters\n",
|
||||
progname, rv);
|
||||
} while (rv > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct serial_device usb_serdev =
|
||||
{
|
||||
.open = usbdev_open,
|
||||
.setspeed = usbdev_setspeed,
|
||||
.close = usbdev_close,
|
||||
.send = usbdev_send,
|
||||
.recv = usbdev_recv,
|
||||
.drain = usbdev_drain,
|
||||
};
|
||||
|
||||
#endif /* HAVE_LIBUSB */
|
||||
@@ -37,7 +37,7 @@ EXTRA_DIST = \
|
||||
|
||||
bin_PROGRAMS = loaddrv
|
||||
|
||||
loaddrv_LDFLAGS = -mno-cygwin
|
||||
loaddrv_CFLAGS = -mno-cygwin
|
||||
|
||||
loaddrv_SOURCES = \
|
||||
loaddrv.c \
|
||||
|
||||
Reference in New Issue
Block a user