mirror of
https://github.com/mariusgreuel/avrdude.git
synced 2025-12-17 02:54:17 +00:00
Compare commits
177 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbed2e283a | ||
|
|
b2c5030890 | ||
|
|
1652c1b781 | ||
|
|
22fe8cd1e1 | ||
|
|
9749ffcd75 | ||
|
|
ac95d249d6 | ||
|
|
f239ffa1d1 | ||
|
|
ef04ad29bf | ||
|
|
a1afb8ea4a | ||
|
|
631f057984 | ||
|
|
dfe36d084b | ||
|
|
7abd4c5bb2 | ||
|
|
f25cf95909 | ||
|
|
10eb9c7f5c | ||
|
|
08f272851c | ||
|
|
35a87b9b6f | ||
|
|
ab86a7d09b | ||
|
|
fa205ce214 | ||
|
|
7d1d5424d2 | ||
|
|
a473be7683 | ||
|
|
84e401d795 | ||
|
|
17ac6b9989 | ||
|
|
4108e10380 | ||
|
|
71cd3f3dd1 | ||
|
|
47bc86120d | ||
|
|
22879832f1 | ||
|
|
a4fa4ea9fc | ||
|
|
074b7a0868 | ||
|
|
1da689ac37 | ||
|
|
c02384d670 | ||
|
|
45d7a727cd | ||
|
|
d11d70ea6c | ||
|
|
885333687c | ||
|
|
197dc966e9 | ||
|
|
25e7980b28 | ||
|
|
38c5d278aa | ||
|
|
f2d7a52f51 | ||
|
|
79ce8f34bf | ||
|
|
2ccc76a66d | ||
|
|
6b8fa85a0b | ||
|
|
8c215d1da5 | ||
|
|
860aea6e04 | ||
|
|
0353e3ade9 | ||
|
|
f39e957354 | ||
|
|
b8d0a34c44 | ||
|
|
0734c16f98 | ||
|
|
73f657ac41 | ||
|
|
2e86c833ce | ||
|
|
f3dfeb6ecf | ||
|
|
8e5f9c7e1b | ||
|
|
af4f648cf5 | ||
|
|
4f9cd863b8 | ||
|
|
84ed521326 | ||
|
|
c788c75014 | ||
|
|
c4e4fa62c3 | ||
|
|
16c7a11538 | ||
|
|
ac7bf0624c | ||
|
|
6e45624477 | ||
|
|
4bc635da8c | ||
|
|
3318df48ed | ||
|
|
f615f8cbad | ||
|
|
3b69ebd4e9 | ||
|
|
9a2971fb35 | ||
|
|
66fa9f0689 | ||
|
|
1abf521ee3 | ||
|
|
8962bec663 | ||
|
|
d973ae28e3 | ||
|
|
4074a28682 | ||
|
|
cba56a46fe | ||
|
|
82a9e3cd60 | ||
|
|
74f8cf9dd5 | ||
|
|
1c121a456a | ||
|
|
c71e4d3674 | ||
|
|
54b633cace | ||
|
|
6eeab88fd4 | ||
|
|
fc87fe433a | ||
|
|
5dbc32c73e | ||
|
|
fa5465b63f | ||
|
|
6460235802 | ||
|
|
4b97ebc9ad | ||
|
|
00791df09d | ||
|
|
9473243b2c | ||
|
|
8a833f921e | ||
|
|
ca1ed48a5e | ||
|
|
d54f7a4fdb | ||
|
|
879dd88de5 | ||
|
|
291c0515b9 | ||
|
|
fc2bb33bb6 | ||
|
|
1ac704aa18 | ||
|
|
7c00e9ce8d | ||
|
|
1066d7cbb2 | ||
|
|
656a37122e | ||
|
|
c4770ee293 | ||
|
|
13ae062376 | ||
|
|
fafd64f35d | ||
|
|
3f6708683a | ||
|
|
be32054156 | ||
|
|
8e64e0b3ca | ||
|
|
de999a4df4 | ||
|
|
1c27d0b72c | ||
|
|
72b22aa078 | ||
|
|
cf07755f50 | ||
|
|
2ff1624077 | ||
|
|
9243abcf3b | ||
|
|
9a055d4128 | ||
|
|
29daef32db | ||
|
|
e860b3091f | ||
|
|
75bf98f073 | ||
|
|
3745f482d9 | ||
|
|
f638a4caab | ||
|
|
4cf622cbf9 | ||
|
|
688e194b10 | ||
|
|
bb60925d96 | ||
|
|
e663123831 | ||
|
|
6ed65069bf | ||
|
|
e2e97bca93 | ||
|
|
c8c576ff35 | ||
|
|
c814037d98 | ||
|
|
4d5a479c86 | ||
|
|
2d146130a6 | ||
|
|
a8a9ed2ca1 | ||
|
|
285ae1ab31 | ||
|
|
a8e190bd30 | ||
|
|
f76b51b554 | ||
|
|
51770e1a4b | ||
|
|
a71e6218b8 | ||
|
|
7f81f23269 | ||
|
|
ed1637d25c | ||
|
|
56ef0aafe8 | ||
|
|
4d4b87df15 | ||
|
|
e20799eefe | ||
|
|
06a5af36ba | ||
|
|
cee67f5f4b | ||
|
|
bbe2807089 | ||
|
|
b17ff40a09 | ||
|
|
db16162922 | ||
|
|
cb4000d7d3 | ||
|
|
d7bddada25 | ||
|
|
df364f59c3 | ||
|
|
cd07291aae | ||
|
|
ede97a0ed2 | ||
|
|
caec621eaa | ||
|
|
c23519f392 | ||
|
|
4cbcbe84ec | ||
|
|
fddb673ee8 | ||
|
|
b561874f07 | ||
|
|
5e68193a6c | ||
|
|
d9866f6219 | ||
|
|
645961163d | ||
|
|
e9750a7712 | ||
|
|
0b197a6c6f | ||
|
|
70fdf3082e | ||
|
|
e58b699f41 | ||
|
|
6b379d8842 | ||
|
|
6fa8db276f | ||
|
|
7f7974ce25 | ||
|
|
f0c7b52223 | ||
|
|
0935636c7b | ||
|
|
1b38485a23 | ||
|
|
fa935481aa | ||
|
|
5ea6e54f96 | ||
|
|
92010244dc | ||
|
|
85e827043d | ||
|
|
25d844791c | ||
|
|
3ef11e335a | ||
|
|
58233bbed4 | ||
|
|
ad9238b29e | ||
|
|
5ce121ab1c | ||
|
|
5105a871be | ||
|
|
496ab3fd81 | ||
|
|
a1c528dbe2 | ||
|
|
50b587155d | ||
|
|
d1342a1984 | ||
|
|
f9331bc6b4 | ||
|
|
08e0114447 | ||
|
|
0f12718ab6 | ||
|
|
1b3d1fb776 |
@@ -4,17 +4,30 @@ y.output
|
||||
y.tab.h
|
||||
lexer.c
|
||||
config_gram.c
|
||||
config_gram.h
|
||||
.cvsignore
|
||||
.depend
|
||||
.deps
|
||||
INSTALL
|
||||
Makefile.in
|
||||
Makefile
|
||||
ac_cfg.h.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
compile
|
||||
missing
|
||||
mkinstalldirs
|
||||
stamp-h.in
|
||||
|
||||
stamp-h1
|
||||
ac_cfg.h
|
||||
avrdude.conf
|
||||
avrdude.conf.tmp
|
||||
avrdude.spec
|
||||
config.guess
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
avrdude
|
||||
|
||||
1039
avrdude/ChangeLog
1039
avrdude/ChangeLog
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@
|
||||
#
|
||||
|
||||
EXTRA_DIST = \
|
||||
ChangeLog \
|
||||
ChangeLog-2001 \
|
||||
ChangeLog-2002 \
|
||||
ChangeLog-2003 \
|
||||
@@ -46,8 +47,25 @@ avrdude_CPPFLAGS = -DCONFIG_DIR=\"$(sysconfdir)\"
|
||||
|
||||
avrdude_CFLAGS = @ENABLE_WARNINGS@
|
||||
|
||||
avrdude_LDADD = @LIBUSB@
|
||||
|
||||
bin_PROGRAMS = avrdude
|
||||
|
||||
# automake thinks these generated files should be in the distribution,
|
||||
# but this might cause trouble for some users, so we rather don't want
|
||||
# to have them there.
|
||||
#
|
||||
# See
|
||||
#
|
||||
# https://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=15536
|
||||
#
|
||||
# for why we don't want to have them.
|
||||
dist-hook:
|
||||
rm -f \
|
||||
$(distdir)/lexer.c \
|
||||
$(distdir)/config_gram.c \
|
||||
$(distdir)/config_gram.h
|
||||
|
||||
avrdude_SOURCES = \
|
||||
config_gram.y \
|
||||
lexer.l \
|
||||
@@ -69,6 +87,10 @@ avrdude_SOURCES = \
|
||||
crc16.h \
|
||||
fileio.c \
|
||||
fileio.h \
|
||||
freebsd_ppi.h \
|
||||
jtagmkI.c \
|
||||
jtagmkI.h \
|
||||
jtagmkI_private.h \
|
||||
jtagmkII.c \
|
||||
jtagmkII.h \
|
||||
jtagmkII_private.h \
|
||||
@@ -76,6 +98,7 @@ avrdude_SOURCES = \
|
||||
lists.c \
|
||||
lists.h \
|
||||
main.c \
|
||||
my_ddk_hidsdi.h \
|
||||
par.c \
|
||||
par.h \
|
||||
pgm.c \
|
||||
@@ -90,16 +113,23 @@ avrdude_SOURCES = \
|
||||
serbb.h \
|
||||
serbb_posix.c \
|
||||
serbb_win32.c \
|
||||
ser_avrdoper.c \
|
||||
ser_posix.c \
|
||||
ser_win32.c \
|
||||
solaris_ecpp.h \
|
||||
stk500.c \
|
||||
stk500.h \
|
||||
stk500_private.h \
|
||||
stk500v2.c \
|
||||
stk500v2.h \
|
||||
stk500v2_private.h \
|
||||
stk500generic.c \
|
||||
stk500generic.h \
|
||||
term.c \
|
||||
term.h \
|
||||
usbasp.c \
|
||||
usbasp.h \
|
||||
usbdevs.h \
|
||||
usb_libusb.c
|
||||
|
||||
man_MANS = avrdude.1
|
||||
@@ -108,6 +138,9 @@ sysconf_DATA = avrdude.conf
|
||||
|
||||
install-exec-local: backup-avrdude-conf
|
||||
|
||||
distclean-local:
|
||||
rm -f avrdude.conf
|
||||
|
||||
# This will get run before the config file is installed.
|
||||
backup-avrdude-conf:
|
||||
@echo "Backing up avrdude.conf in ${DESTDIR}${sysconfdir}"
|
||||
|
||||
56
avrdude/NEWS
56
avrdude/NEWS
@@ -5,8 +5,62 @@ Approximate change log for AVRDUDE by version.
|
||||
(For more detailed changes, see the ChangeLog file.)
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Current:
|
||||
Version 5.3:
|
||||
|
||||
* Add support for the AVR Dragon (all modes: ISP, JTAG, HVSP, PP,
|
||||
debugWire).
|
||||
|
||||
* Add support for debugWire (both, JTAG ICE mkII, and AVR Dragon).
|
||||
|
||||
* Add support for the AVR Doper USB HID-class programmer.
|
||||
|
||||
* Bugfixes.
|
||||
|
||||
Version 5.2:
|
||||
|
||||
* New devices supported:
|
||||
|
||||
- AT90USB646/647/1286/1287
|
||||
- ATmega2560/2561
|
||||
- ATmega325/3250/645/6450
|
||||
- ATtiny11 (HVSP only device)
|
||||
- ATtiny261/461/861
|
||||
|
||||
* Fixed paged flash write operations for AT90PWMx devices
|
||||
(error in datasheet).
|
||||
|
||||
* Add signature verification.
|
||||
|
||||
* Add high-voltage mode programming for the STK500 (both,
|
||||
parallel, and high-voltage serial programming).
|
||||
|
||||
* Add support for using the JTAG ICE mkII as a generic ISP
|
||||
programmer.
|
||||
|
||||
* Allow for specifying the ISP clock delay as an option for
|
||||
bit-bang programming adapters.
|
||||
|
||||
* Add support for Thomas Fischl's USBasp low-cost USB-attached
|
||||
programmer.
|
||||
|
||||
* The "stk500" programmer type is now implemented as a stub
|
||||
that tries to probe for either "stk500v1" or "stk500v2".
|
||||
|
||||
* Many bugfixes.
|
||||
|
||||
Version 5.1:
|
||||
|
||||
* New devices supported:
|
||||
|
||||
- ATmega640/1280/1281
|
||||
- ATtiny24/44/84
|
||||
|
||||
* JTAG mkII support now works with libusb-win32, too
|
||||
|
||||
* JTAG ICE mkI support has been added
|
||||
|
||||
* Solaris support has been added (including ecpp(7D) parallel-port
|
||||
bit-bang mode)
|
||||
|
||||
|
||||
Version 5.0:
|
||||
|
||||
117
avrdude/avr.c
117
avrdude/avr.c
@@ -51,7 +51,15 @@ int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
unsigned char data;
|
||||
OPCODE * readop;
|
||||
OPCODE * readop, * lext;
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: Error: %s programmer uses avr_read_byte_default() but does not\n"
|
||||
"provide a cmd() method.\n",
|
||||
progname, pgm->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pgm->pgm_led(pgm, ON);
|
||||
pgm->err_led(pgm, OFF);
|
||||
@@ -79,6 +87,18 @@ int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this device has a "load extended address" command, issue it.
|
||||
*/
|
||||
lext = mem->op[AVR_OP_LOAD_EXT_ADDR];
|
||||
if (lext != NULL) {
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
|
||||
avr_set_bits(lext, cmd);
|
||||
avr_set_addr(lext, cmd, addr);
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
}
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
|
||||
avr_set_bits(readop, cmd);
|
||||
@@ -95,26 +115,6 @@ int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* read a byte of data from the indicated memory region
|
||||
*/
|
||||
int avr_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char * value)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (pgm->read_byte) {
|
||||
rc = pgm->read_byte(pgm, p, mem, addr, value);
|
||||
if (rc == 0) {
|
||||
return rc;
|
||||
}
|
||||
/* read_byte() method failed, try again with default. */
|
||||
}
|
||||
|
||||
return avr_read_byte_default(pgm, p, mem, addr, value);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the number of "interesting" bytes in a memory buffer,
|
||||
* "interesting" being defined as up to the last non-0xff data
|
||||
@@ -182,20 +182,13 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
* efficiently than we can read it directly, so use its routine
|
||||
* instead
|
||||
*/
|
||||
if (mem->paged) {
|
||||
rc = pgm->paged_load(pgm, p, mem, mem->page_size, size);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
rc = pgm->paged_load(pgm, p, mem, mem->page_size, size);
|
||||
if (rc >= 0) {
|
||||
if (strcasecmp(mem->desc, "flash") == 0)
|
||||
return avr_mem_hiaddr(mem);
|
||||
else
|
||||
return rc;
|
||||
}
|
||||
else {
|
||||
rc = pgm->paged_load(pgm, p, mem, pgm->page_size, size);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
if (strcasecmp(mem->desc, "flash") == 0)
|
||||
return avr_mem_hiaddr(mem);
|
||||
else
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +199,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
}
|
||||
|
||||
for (i=0; i<size; i++) {
|
||||
rc = avr_read_byte(pgm, p, mem, i, &rbyte);
|
||||
rc = pgm->read_byte(pgm, p, mem, i, &rbyte);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "avr_read(): error reading address 0x%04lx\n", i);
|
||||
if (rc == -1)
|
||||
@@ -234,7 +227,15 @@ int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
OPCODE * wp;
|
||||
OPCODE * wp, * lext;
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: Error: %s programmer uses avr_write_page() but does not\n"
|
||||
"provide a cmd() method.\n",
|
||||
progname, pgm->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wp = mem->op[AVR_OP_WRITEPAGE];
|
||||
if (wp == NULL) {
|
||||
@@ -254,6 +255,18 @@ int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
pgm->pgm_led(pgm, ON);
|
||||
pgm->err_led(pgm, OFF);
|
||||
|
||||
/*
|
||||
* If this device has a "load extended address" command, issue it.
|
||||
*/
|
||||
lext = mem->op[AVR_OP_LOAD_EXT_ADDR];
|
||||
if (lext != NULL) {
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
|
||||
avr_set_bits(lext, cmd);
|
||||
avr_set_addr(lext, cmd, addr);
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
}
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
|
||||
avr_set_bits(wp, cmd);
|
||||
@@ -288,13 +301,21 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
int readok=0;
|
||||
struct timeval tv;
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: Error: %s programmer uses avr_write_byte_default() but does not\n"
|
||||
"provide a cmd() method.\n",
|
||||
progname, pgm->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mem->paged) {
|
||||
/*
|
||||
* check to see if the write is necessary by reading the existing
|
||||
* value and only write if we are changing the value; we can't
|
||||
* use this optimization for paged addressing.
|
||||
*/
|
||||
rc = avr_read_byte(pgm, p, mem, addr, &b);
|
||||
rc = pgm->read_byte(pgm, p, mem, addr, &b);
|
||||
if (rc != 0) {
|
||||
if (rc != -1) {
|
||||
return -2;
|
||||
@@ -321,7 +342,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
writeop = mem->op[AVR_OP_WRITE_LO];
|
||||
caddr = addr / 2;
|
||||
}
|
||||
else if (mem->op[AVR_OP_LOADPAGE_LO]) {
|
||||
else if (mem->paged && mem->op[AVR_OP_LOADPAGE_LO]) {
|
||||
if (addr & 0x01)
|
||||
writeop = mem->op[AVR_OP_LOADPAGE_HI];
|
||||
else
|
||||
@@ -386,7 +407,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
* specified for the chip.
|
||||
*/
|
||||
usleep(mem->max_write_delay);
|
||||
rc = avr_read_byte(pgm, p, mem, addr, &r);
|
||||
rc = pgm->read_byte(pgm, p, mem, addr, &r);
|
||||
if (rc != 0) {
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
pgm->err_led(pgm, OFF);
|
||||
@@ -400,7 +421,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
/*
|
||||
* Do polling, but timeout after max_write_delay.
|
||||
*/
|
||||
rc = avr_read_byte(pgm, p, mem, addr, &r);
|
||||
rc = pgm->read_byte(pgm, p, mem, addr, &r);
|
||||
if (rc != 0) {
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
pgm->err_led(pgm, ON);
|
||||
@@ -485,7 +506,6 @@ int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
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);
|
||||
@@ -505,15 +525,7 @@ int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
|
||||
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) {
|
||||
return rc;
|
||||
}
|
||||
/* write_byte() method failed, try again with default. */
|
||||
}
|
||||
|
||||
return avr_write_byte_default(pgm, p, mem, addr, data);
|
||||
return pgm->write_byte(pgm, p, mem, addr, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -567,7 +579,8 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
* efficiently than we can read it directly, so use its routine
|
||||
* instead
|
||||
*/
|
||||
return pgm->paged_write(pgm, p, m, m->page_size, size);
|
||||
if ((i = pgm->paged_write(pgm, p, m, m->page_size, size)) >= 0)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,7 +730,7 @@ int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles)
|
||||
}
|
||||
|
||||
for (i=4; i>0; i--) {
|
||||
rc = avr_read_byte(pgm, p, a, a->size-i, &v1);
|
||||
rc = pgm->read_byte(pgm, p, a, a->size-i, &v1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n",
|
||||
progname, rc);
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
extern struct avrpart parts[];
|
||||
|
||||
|
||||
int avr_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char * value);
|
||||
int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char * value);
|
||||
|
||||
int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
int verbose);
|
||||
@@ -44,6 +44,9 @@ 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_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char data);
|
||||
|
||||
int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||
int verbose);
|
||||
|
||||
|
||||
@@ -40,13 +40,14 @@
|
||||
|
||||
extern char * progname;
|
||||
extern int do_cycles;
|
||||
extern int ovsigck;
|
||||
|
||||
static char has_auto_incr_addr;
|
||||
|
||||
|
||||
static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
{
|
||||
return serial_send(pgm->fd, (unsigned char *)buf, len);
|
||||
return serial_send(&pgm->fd, (unsigned char *)buf, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +55,7 @@ static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = serial_recv(pgm->fd, (unsigned char *)buf, len);
|
||||
rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: avr910_recv(): programmer is not responding\n",
|
||||
@@ -67,7 +68,7 @@ static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
|
||||
static int avr910_drain(PROGRAMMER * pgm, int display)
|
||||
{
|
||||
return serial_drain(pgm->fd, display);
|
||||
return serial_drain(&pgm->fd, display);
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +135,7 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
char hw[2];
|
||||
char buf[10];
|
||||
char type;
|
||||
char c;
|
||||
char c, devtype_1st;
|
||||
int dev_supported = 0;
|
||||
AVRPART * part;
|
||||
|
||||
@@ -173,8 +174,11 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
|
||||
avr910_send(pgm, "t", 1);
|
||||
fprintf(stderr, "\nProgrammer supports the following devices:\n");
|
||||
devtype_1st = 0;
|
||||
while (1) {
|
||||
avr910_recv(pgm, &c, 1);
|
||||
if (devtype_1st == 0)
|
||||
devtype_1st = c;
|
||||
if (c == 0)
|
||||
break;
|
||||
part = locate_part_by_avr910_devcode(part_list, c);
|
||||
@@ -190,15 +194,18 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
|
||||
if (!dev_supported) {
|
||||
fprintf(stderr,
|
||||
"%s: error: selected device is not supported by programmer: %s\n",
|
||||
progname, p->id);
|
||||
exit(1);
|
||||
"%s: %s: selected device is not supported by programmer: %s\n",
|
||||
progname, ovsigck? "warning": "error", p->id);
|
||||
if (!ovsigck)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Tell the programmer which part we selected. */
|
||||
/* Tell the programmer which part we selected.
|
||||
If the user forced the selection, use the first device
|
||||
type that is supported by the programmer. */
|
||||
|
||||
buf[0] = 'T';
|
||||
buf[1] = p->avr910_devcode;
|
||||
buf[1] = ovsigck? devtype_1st: p->avr910_devcode;
|
||||
|
||||
avr910_send(pgm, buf, 2);
|
||||
avr910_vfy_cmd_sent(pgm, "select device");
|
||||
@@ -264,7 +271,7 @@ static int avr910_open(PROGRAMMER * pgm, char * port)
|
||||
}
|
||||
|
||||
strcpy(pgm->port, port);
|
||||
pgm->fd = serial_open(port, pgm->baudrate);
|
||||
serial_open(port, pgm->baudrate, &pgm->fd);
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
@@ -278,8 +285,8 @@ static void avr910_close(PROGRAMMER * pgm)
|
||||
{
|
||||
avr910_leave_prog_mode(pgm);
|
||||
|
||||
serial_close(pgm->fd);
|
||||
pgm->fd = -1;
|
||||
serial_close(&pgm->fd);
|
||||
pgm->fd.ifd = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -557,6 +564,8 @@ static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
|
||||
static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||
{
|
||||
unsigned char tmp;
|
||||
|
||||
if (m->size < 3) {
|
||||
fprintf(stderr, "%s: memsize too small for sig byte read", progname);
|
||||
return -1;
|
||||
@@ -564,6 +573,10 @@ static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||
|
||||
avr910_send(pgm, "s", 1);
|
||||
avr910_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;
|
||||
}
|
||||
|
||||
@@ -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, 2005, 2006 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 October 26, 2006
|
||||
.Os
|
||||
.Dt AVRDUDE 1
|
||||
.Sh NAME
|
||||
@@ -38,7 +38,9 @@
|
||||
.Op \&, Ns Ar exitspec
|
||||
.Oc
|
||||
.Op Fl F
|
||||
.Op Fl i Ar delay
|
||||
.Op Fl n
|
||||
.Op Fl O
|
||||
.Op Fl P Ar port
|
||||
.Op Fl q
|
||||
.Op Fl s
|
||||
@@ -55,7 +57,8 @@ is a program for downloading code and data to Atmel AVR
|
||||
microcontrollers.
|
||||
.Nm Avrdude
|
||||
supports Atmel's STK500 programmer,
|
||||
Atmel's JTAG ICE mkII,
|
||||
Atmel's AVRISP and AVRISP mkII devices,
|
||||
Atmel's JTAG ICE (both mkI and mkII, the latter also in ISP mode),
|
||||
programmers complying to AppNote AVR910 and AVR109 (including the Butterfly),
|
||||
as well as a simple hard-wired
|
||||
programmer connected directly to a
|
||||
@@ -79,7 +82,7 @@ and
|
||||
need to be connected to the parallel port. Optionally, some otherwise
|
||||
unused output pins of the parallel port can be used to supply power
|
||||
for the MCU part, so it is also possible to construct a passive
|
||||
standalone programming device. Some status LEDs indicating the
|
||||
stand-alone programming device. Some status LEDs indicating the
|
||||
current operating state of the programmer can be connected, and a
|
||||
signal is available to control a buffer/driver IC 74LS367 (or
|
||||
74HCT367). The latter can be useful to decouple the parallel port
|
||||
@@ -98,14 +101,37 @@ 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).
|
||||
Using firmware version 2, high-voltage programming is also supported,
|
||||
both parallel and serial
|
||||
(programmer types stk500pp and stk500hvsp).
|
||||
.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
|
||||
Atmel's JTAG ICE (both mkI and mkII) is supported as well to up- or download memory
|
||||
areas from/to an AVR target (no support for on-chip debugging).
|
||||
For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported.
|
||||
See below for the limitations of debugWire.
|
||||
.Pp
|
||||
The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP, debugWire).
|
||||
When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
|
||||
JTAG ICE mkII, so all device-specific comments for that device
|
||||
will apply as well.
|
||||
When used in ISP mode, the AVR Dragon behaves similar to an
|
||||
AVRISP mkII (or JTAG ICE mkII in ISP mode), so all device-specific
|
||||
comments will apply there.
|
||||
In particular, the Dragon starts out with a rather fast ISP clock
|
||||
frequency, so the
|
||||
.Fl B Ar bitclock
|
||||
option might be required to achieve a stable ISP communication.
|
||||
.Pp
|
||||
The USBasp ISP adapter is also supported, provided
|
||||
.Nm avrdude
|
||||
has been compiled with libusb support.
|
||||
It features a simple firwmare-only USB implementation, running on
|
||||
an ATmega8 (or ATmega88).
|
||||
.Pp
|
||||
Input files can be provided, and output files can be written in
|
||||
different file formats, such as raw binary files containing the data
|
||||
@@ -122,7 +148,7 @@ can program the EEPROM and flash ROM memory cells of supported AVR
|
||||
parts. Where supported by the serial instruction set, fuse bits and
|
||||
lock bits can be programmed as well. These are implemented within
|
||||
.Nm
|
||||
as seperate memory types and can be programmed using data from a file
|
||||
as separate memory types and can be programmed using data from a file
|
||||
(see the
|
||||
.Fl m
|
||||
option) or from terminal mode (see the
|
||||
@@ -169,18 +195,23 @@ pwm3 AT90PWM3
|
||||
8535 AT90S8535
|
||||
m103 ATmega103
|
||||
m128 ATmega128
|
||||
m1280 ATmega1280
|
||||
m1281 ATmega1281
|
||||
m16 ATmega16
|
||||
m161 ATmega161
|
||||
m162 ATmega162
|
||||
m163 ATmega163
|
||||
m164 ATmega164
|
||||
m169 ATmega169
|
||||
m2560 ATmega2560 (**)
|
||||
m2561 ATmega2561 (**)
|
||||
m32 ATmega32
|
||||
m324 ATmega324
|
||||
m329 ATmega329
|
||||
m3290 ATmega3290
|
||||
m48 ATmega48
|
||||
m64 ATmega64
|
||||
m640 ATmega640
|
||||
m644 ATmega644
|
||||
m649 ATmega649
|
||||
m6490 ATmega6490
|
||||
@@ -197,15 +228,19 @@ t26 ATtiny26
|
||||
t45 ATtiny45
|
||||
t85 ATtiny85
|
||||
.TE
|
||||
.Bl -tag -width "(*) "
|
||||
.Bl -tag -width "(**) "
|
||||
.It "(*)"
|
||||
The AT90S2323 and ATtiny22 use the same algorithm.
|
||||
.It "(**)"
|
||||
Flash addressing above 128 KB is not supported by all
|
||||
programming hardware. Known to work are jtag2, stk500v2,
|
||||
and bit-bang programmers.
|
||||
.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).
|
||||
Specify the bit clock period for the JTAG interface or the ISP clock (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
|
||||
@@ -317,10 +352,34 @@ 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 delay
|
||||
For bitbang-type programmers, delay for approximately
|
||||
.Ar delay
|
||||
microseconds between each bit state change.
|
||||
If the host system is very fast, or the target runs off a slow clock
|
||||
(like a 32 kHz crystal, or the 128 kHz internal RC oscillator), this
|
||||
can become necessary to satisfy the requirement that the ISP clock
|
||||
frequency must not be higher than 1/4 of the CPU clock frequency.
|
||||
This is implemented as a spin-loop delay to allow even for very
|
||||
short delays.
|
||||
On Unix-style operating systems, the spin loop is initially calibrated
|
||||
against a system timer, so the number of microseconds might be rather
|
||||
realistic, assuming a constant system load while
|
||||
.Nm
|
||||
is running.
|
||||
On Win32 operating systems, a preconfigured number of cycles per
|
||||
microsecond is assumed that might be off a bit for very fast or very
|
||||
slow machines.
|
||||
.It Fl n
|
||||
No-write - disables actually writing data to the MCU (useful for debugging
|
||||
.Nm avrdude
|
||||
).
|
||||
.It Fl O
|
||||
Perform a RC oscillator run-time calibration according to Atmel
|
||||
application note AVR053.
|
||||
This is only supported on the STK500v2, AVRISP mkII, and JTAG ICE mkII
|
||||
hardware.
|
||||
Note that the result will be stored in the EEPROM cell at address 0.
|
||||
.It Fl P Ar port
|
||||
Use
|
||||
.Ar port
|
||||
@@ -338,7 +397,7 @@ For the JTAG ICE mkII, if
|
||||
has been configured with libusb support,
|
||||
.Ar port
|
||||
can alternatively be specified as
|
||||
.Ar usb Ns Op \&: Ns Ar serialno .
|
||||
.Pa usb Ns Op \&: Ns Ar serialno .
|
||||
This will cause
|
||||
.Nm
|
||||
to search a JTAG ICE mkII on USB.
|
||||
@@ -349,6 +408,34 @@ 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.
|
||||
.Pp
|
||||
As the AVRISP mkII device can only be talked to over USB, the very
|
||||
same method of specifying the port is required there.
|
||||
.Pp
|
||||
For the USB programmer "AVR-Doper" running in HID mode, the port must
|
||||
be specified as
|
||||
.Ar avrdoper.
|
||||
Libusb support is required on Unix but not on Windows. For more
|
||||
information about AVR-Doper see http://www.obdev.at/avrusb/avrdoper.html.
|
||||
.Pp
|
||||
For programmers that attach to a serial port using some kind of
|
||||
higher level protocol (as opposed to bit-bang style programmers),
|
||||
.Ar port
|
||||
can be specified as
|
||||
.Pa net Ns \&: Ns Ar host Ns \&: Ns Ar port .
|
||||
In this case, instead of trying to open a local device, a TCP
|
||||
network connection to (TCP)
|
||||
.Ar port
|
||||
on
|
||||
.Ar host
|
||||
is established.
|
||||
The remote endpoint is assumed to be a terminal or console server
|
||||
that connects the network stream to a local serial port where the
|
||||
actual programmer has been attached to.
|
||||
The port is assumed to be properly configured, for example using a
|
||||
transparent 8-bit data connection without parity at 115200 Baud
|
||||
for a STK500.
|
||||
.Em This feature is currently not implemented for Win32 systems.
|
||||
.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.
|
||||
@@ -383,7 +470,7 @@ option to disable safemode prompting.
|
||||
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
|
||||
The available memory types are device-dependent, the actual
|
||||
configuration can be viewed with the
|
||||
.Cm part
|
||||
command in terminal mode.
|
||||
@@ -443,13 +530,31 @@ Motorola S-record
|
||||
.It Ar r
|
||||
raw binary; little-endian byte order, in the case of the flash ROM data
|
||||
.It Ar m
|
||||
immediate; actual byte values specified on the command line, seperated
|
||||
immediate; actual byte values specified on the command line, separated
|
||||
by commas or spaces. This is good for programming fuse bytes without
|
||||
having to create a single-byte file or enter terminal mode.
|
||||
.It Ar a
|
||||
auto detect; valid for input only, and only if the input is not
|
||||
provided at
|
||||
.Em stdin .
|
||||
.It Ar d
|
||||
decimal; this and the following formats are only valid on output.
|
||||
They generate one line of output for the respective memory section,
|
||||
forming a comma-separated list of the values.
|
||||
This can be particularly useful for subsequent processing, like for
|
||||
fuse bit settings.
|
||||
.It Ar h
|
||||
hexadecimal; each value will get the string
|
||||
.Em 0x
|
||||
prepended.
|
||||
.It Ar o
|
||||
octal; each value will get a
|
||||
.Em 0
|
||||
prepended unless it is less than 8 in which case it gets no prefix.
|
||||
.It Ar b
|
||||
binary; each value will get the string
|
||||
.Em 0b
|
||||
prepended.
|
||||
.El
|
||||
.Pp
|
||||
The default is to use auto detection for input files, and raw binary
|
||||
@@ -461,6 +566,14 @@ contains a colon, the
|
||||
field is no longer optional since the filename part following the colon
|
||||
would otherwise be misinterpreted as
|
||||
.Ar format .
|
||||
.Pp
|
||||
As an abbreviation, the form
|
||||
.Fl U Ar filename
|
||||
is equivalent to specifying
|
||||
.Fl U Em flash:w: Ns Ar filename Ns :a .
|
||||
This will only work if
|
||||
.Ar filename
|
||||
does not have a colon in it.
|
||||
.It Fl v
|
||||
Enable verbose output.
|
||||
.It Fl V
|
||||
@@ -575,6 +688,8 @@ 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.
|
||||
This parameter can also be used on the JTAG ICE mkII to specify the
|
||||
ISP clock period when operating the ICE in ISP mode.
|
||||
.It Ar parms
|
||||
.Em STK500 programmer only:
|
||||
Display the current voltage and master oscillator parameters.
|
||||
@@ -602,6 +717,33 @@ ll.
|
||||
10 MISO (from MCU)
|
||||
18-25 GND
|
||||
.TE
|
||||
.Ss debugWire limitations
|
||||
The debugWire protocol is Atmel's proprietary one-wire (plus ground)
|
||||
protocol to allow an in-circuit emulation of the smaller AVR devices,
|
||||
using the
|
||||
.Ql /RESET
|
||||
line.
|
||||
DebugWire mode is initiated by activating the
|
||||
.Ql DWEN
|
||||
fuse, and then power-cycling the target.
|
||||
While this mode is mainly intented for debugging/emulation, it
|
||||
also offers limited programming capabilities.
|
||||
Effectively, the only memory areas that can be read or programmed
|
||||
in this mode are flash ROM and EEPROM.
|
||||
It is also possible to read out the signature.
|
||||
All other memory areas cannot be accessed.
|
||||
There is no
|
||||
.Em chip erase
|
||||
functionality in debugWire mode; instead, while reprogramming the
|
||||
flash ROM, each flash ROM page is erased right before updating it.
|
||||
This is done transparently by the JTAG ICE mkII (or AVR Dragon).
|
||||
The only way back from debugWire mode is to initiate a special
|
||||
sequence of commands to the JTAG ICE mkII (or AVR Dragon), so the
|
||||
debugWire mode will be temporarily disabled, and the target can
|
||||
be accessed using normal ISP programming.
|
||||
This sequence is automatically initiated by using the JTAG ICE mkII
|
||||
or AVR Dragon in ISP mode, when they detect that ISP mode cannot be
|
||||
entered.
|
||||
.Sh FILES
|
||||
.Bl -tag -offset indent -width /dev/ppi0XXX
|
||||
.It Pa /dev/ppi0
|
||||
@@ -619,7 +761,31 @@ library
|
||||
Schematic of programming hardware
|
||||
.El
|
||||
.\" .Sh EXAMPLES
|
||||
.\" .Sh DIAGNOSTICS
|
||||
.Sh DIAGNOSTICS
|
||||
.Bd -literal
|
||||
avrdude: jtagmkII_setparm(): bad response to set parameter command: RSP_FAILED
|
||||
avrdude: jtagmkII_getsync(): ISP activation failed, trying debugWire
|
||||
avrdude: Target prepared for ISP, signed off.
|
||||
avrdude: Please restart avrdude without power-cycling the target.
|
||||
.Ed
|
||||
.Pp
|
||||
If the target AVR has been set up for debugWire mode (i. e. the
|
||||
.Em DWEN
|
||||
fuse is programmed), normal ISP connection attempts will fail as
|
||||
the
|
||||
.Em /RESET
|
||||
pin is not available.
|
||||
When using the JTAG ICE mkII in ISP mode, the message shown indicates
|
||||
that
|
||||
.Nm
|
||||
has guessed this condition, and tried to initiate a debugWire reset
|
||||
to the target.
|
||||
When successful, this will leave the target AVR in a state where it
|
||||
can respond to normal ISP communication again (until the next power
|
||||
cycle).
|
||||
Typically, the same command is going to be retried again immediately
|
||||
afterwards, and will then succeed connecting to the target using
|
||||
normal ISP communication.
|
||||
.Sh SEE ALSO
|
||||
.Xr avr-objcopy 1 ,
|
||||
.Xr ppi 4 ,
|
||||
@@ -640,14 +806,17 @@ This man page by
|
||||
Please report bugs via
|
||||
.Dl "http://savannah.nongnu.org/bugs/?group=avrdude" .
|
||||
.Pp
|
||||
The JTAGICE mkII programmer currently cannot write to the flash ROM
|
||||
The JTAG ICE programmers 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.
|
||||
Page-mode programming the EEPROM through JTAG (i.e. through an
|
||||
.Fl U
|
||||
option) requires a prior chip erase.
|
||||
This is an inherent feature of the way JTAG EEPROM programming works.
|
||||
This also applies to the STK500 in parallel programming mode.
|
||||
.Pp
|
||||
The USBasp driver does not offer any option to distinguish multiple
|
||||
devices connected simultaneously, so effectively only a single device
|
||||
is supported.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,9 @@
|
||||
|
||||
%define debug_package %{nil}
|
||||
|
||||
%define _with_docs 1
|
||||
%{?_without_docs: %define _with_docs 0}
|
||||
|
||||
Summary: AVRDUDE is software for programming Atmel AVR Microcontrollers.
|
||||
Name: avrdude
|
||||
Version: @VERSION@
|
||||
@@ -20,12 +23,14 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-root
|
||||
%description
|
||||
AVRDUDE is software for programming Atmel AVR Microcontrollers.
|
||||
|
||||
%if %{_with_docs}
|
||||
## The avrdude-docs subpackage
|
||||
%package docs
|
||||
Summary: Documentation for AVRDUDE.
|
||||
Group: Documentation
|
||||
%description docs
|
||||
Documentation for avrdude in html, postscript and pdf formats.
|
||||
Documentation for avrdude in info, html, postscript and pdf formats.
|
||||
%endif
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
@@ -33,7 +38,12 @@ Documentation for avrdude in html, postscript and pdf formats.
|
||||
%build
|
||||
|
||||
./configure --prefix=%{_prefix} --sysconfdir=/etc --mandir=%{_mandir} \
|
||||
--infodir=%{_infodir}
|
||||
--infodir=%{_infodir} \
|
||||
%if %{_with_docs}
|
||||
--enable-doc=yes
|
||||
%else
|
||||
--enable-doc=no
|
||||
%endif
|
||||
|
||||
make
|
||||
|
||||
@@ -51,34 +61,43 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%post
|
||||
%if %{_with_docs}
|
||||
%post docs
|
||||
[ -f %{_infodir}/avrdude.info ] && \
|
||||
/sbin/install-info %{_infodir}/avrdude.info %{_infodir}/dir || :
|
||||
[ -f %{_infodir}/avrdude.info.gz ] && \
|
||||
/sbin/install-info %{_infodir}/avrdude.info.gz %{_infodir}/dir || :
|
||||
|
||||
%preun
|
||||
%preun docs
|
||||
if [ $1 = 0 ]; then
|
||||
[ -f %{_infodir}/avrdude.info ] && \
|
||||
/sbin/install-info --delete %{_infodir}/avrdude.info %{_infodir}/dir || :
|
||||
[ -f %{_infodir}/avrdude.info.gz ] && \
|
||||
/sbin/install-info --delete %{_infodir}/avrdude.info.gz %{_infodir}/dir || :
|
||||
fi
|
||||
%endif
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%{_prefix}/bin/avrdude
|
||||
%{_mandir}/man1/avrdude.1.gz
|
||||
%{_infodir}/*info*
|
||||
%attr(0644,root,root) %config /etc/avrdude.conf
|
||||
|
||||
%if %{_with_docs}
|
||||
%files docs
|
||||
%doc %{_infodir}/*info*
|
||||
%doc doc/avrdude-html/*.html
|
||||
%doc doc/TODO
|
||||
%doc doc/avrdude.ps
|
||||
%doc doc/avrdude.pdf
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Fri Sep 23 2005 Galen Seitz <galens@seitzassoc.com>
|
||||
- Default to enable-doc=yes during configure.
|
||||
- Move info file to docs package.
|
||||
- Make building of docs package conditional. Basic idea copied from avr-gcc.
|
||||
|
||||
* Wed Aug 27 2003 Theodore A. Roth <troth@openavr.org>
|
||||
[Thanks to Artur Lipowski <LAL@pro.onet.pl>]
|
||||
- Do not build debug package.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2006 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
|
||||
@@ -174,6 +175,7 @@ char * avr_op_str(int op)
|
||||
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_LOAD_EXT_ADDR : return "LOAD_EXT_ADDR"; 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;
|
||||
@@ -317,7 +319,7 @@ void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type,
|
||||
m->max_write_delay,
|
||||
m->readback[0],
|
||||
m->readback[1]);
|
||||
if (verbose > 2) {
|
||||
if (verbose > 4) {
|
||||
fprintf(stderr,
|
||||
"%s Memory Ops:\n"
|
||||
"%s Oeration Inst Bit Bit Type Bitno Value\n"
|
||||
@@ -369,6 +371,8 @@ AVRPART * avr_new_part(void)
|
||||
p->flags = AVRPART_SERIALOK | AVRPART_PARALLELOK | AVRPART_ENABLEPAGEPROGRAMMING;
|
||||
p->config_file[0] = 0;
|
||||
p->lineno = 0;
|
||||
memset(p->signature, 0xFF, 3);
|
||||
p->ctl_stack_type = CTL_STACK_NONE;
|
||||
|
||||
p->mem = lcreat(NULL, 0);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2006 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
|
||||
@@ -41,6 +42,7 @@ enum {
|
||||
AVR_OP_WRITE_HI,
|
||||
AVR_OP_LOADPAGE_LO,
|
||||
AVR_OP_LOADPAGE_HI,
|
||||
AVR_OP_LOAD_EXT_ADDR,
|
||||
AVR_OP_WRITEPAGE,
|
||||
AVR_OP_CHIP_ERASE,
|
||||
AVR_OP_PGM_ENABLE,
|
||||
@@ -61,6 +63,12 @@ enum { /* these are assigned to reset_disposition of AVRPART */
|
||||
RESET_IO /* reset pin might be configured as an I/O pin */
|
||||
};
|
||||
|
||||
enum ctl_stack_t {
|
||||
CTL_STACK_NONE, /* no control stack defined */
|
||||
CTL_STACK_PP, /* parallel programming control stack */
|
||||
CTL_STACK_HVSP /* high voltage serial programming control stack */
|
||||
};
|
||||
|
||||
/*
|
||||
* serial programming instruction bit specifications
|
||||
*/
|
||||
@@ -81,9 +89,13 @@ typedef struct opcode {
|
||||
#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 AVRPART_HAS_DW 0x0040 /* part has a debugWire i/f */
|
||||
|
||||
#define AVR_DESCLEN 64
|
||||
#define AVR_IDLEN 32
|
||||
#define CTL_STACK_SIZE 32
|
||||
#define FLASH_INSTR_SIZE 3
|
||||
#define EEPROM_INSTR_SIZE 20
|
||||
typedef struct avrpart {
|
||||
char desc[AVR_DESCLEN]; /* long part name */
|
||||
char id[AVR_IDLEN]; /* short part name */
|
||||
@@ -92,6 +104,7 @@ typedef struct avrpart {
|
||||
int chip_erase_delay; /* microseconds */
|
||||
unsigned char pagel; /* for parallel programming */
|
||||
unsigned char bs2; /* for parallel programming */
|
||||
unsigned char signature[3]; /* expected value of signature bytes */
|
||||
int reset_disposition; /* see RESET_ enums */
|
||||
int retry_pulse; /* retry program enable by pulsing
|
||||
this pin (PIN_AVR_*) */
|
||||
@@ -108,6 +121,30 @@ typedef struct avrpart {
|
||||
int postdelay; /* stk500 v2 xml file parameter */
|
||||
int pollmethod; /* stk500 v2 xml file parameter */
|
||||
|
||||
enum ctl_stack_t ctl_stack_type; /* what to use the ctl stack for */
|
||||
unsigned char controlstack[CTL_STACK_SIZE]; /* stk500v2 PP/HVSP ctl stack */
|
||||
unsigned char flash_instr[FLASH_INSTR_SIZE]; /* flash instructions (debugWire, JTAG) */
|
||||
unsigned char eeprom_instr[EEPROM_INSTR_SIZE]; /* EEPROM instructions (debugWire, JTAG) */
|
||||
|
||||
int hventerstabdelay; /* stk500 v2 hv mode parameter */
|
||||
int progmodedelay; /* stk500 v2 hv mode parameter */
|
||||
int latchcycles; /* stk500 v2 hv mode parameter */
|
||||
int togglevtg; /* stk500 v2 hv mode parameter */
|
||||
int poweroffdelay; /* stk500 v2 hv mode parameter */
|
||||
int resetdelayms; /* stk500 v2 hv mode parameter */
|
||||
int resetdelayus; /* stk500 v2 hv mode parameter */
|
||||
int hvleavestabdelay; /* stk500 v2 hv mode parameter */
|
||||
int resetdelay; /* stk500 v2 hv mode parameter */
|
||||
int chiperasepulsewidth; /* stk500 v2 hv mode parameter */
|
||||
int chiperasepolltimeout; /* stk500 v2 hv mode parameter */
|
||||
int chiperasetime; /* stk500 v2 hv mode parameter */
|
||||
int programfusepulsewidth; /* stk500 v2 hv mode parameter */
|
||||
int programfusepolltimeout; /* stk500 v2 hv mode parameter */
|
||||
int programlockpulsewidth; /* stk500 v2 hv mode parameter */
|
||||
int programlockpolltimeout; /* stk500 v2 hv mode parameter */
|
||||
int synchcycles; /* stk500 v2 hv mode parameter */
|
||||
int hvspcmdexedelay; /* 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 */
|
||||
|
||||
@@ -28,47 +28,103 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if !defined(WIN32NATIVE)
|
||||
# include <signal.h>
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#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);
|
||||
static int delay_decrement;
|
||||
|
||||
return 0;
|
||||
#if !defined(WIN32NATIVE)
|
||||
static volatile int done;
|
||||
|
||||
typedef void (*mysighandler_t)(int);
|
||||
static mysighandler_t saved_alarmhandler;
|
||||
|
||||
static void alarmhandler(int signo)
|
||||
{
|
||||
done = 1;
|
||||
signal(SIGALRM, saved_alarmhandler);
|
||||
}
|
||||
#endif /* !WIN32NATIVE */
|
||||
|
||||
/*
|
||||
* Calibrate the microsecond delay loop below.
|
||||
*/
|
||||
static void bitbang_calibrate_delay(void)
|
||||
{
|
||||
/*
|
||||
* Right now, we don't have any Win32 implementation for this, so we
|
||||
* can only run on a preconfigured delay stepping there. The figure
|
||||
* below should at least be correct within an order of magnitude,
|
||||
* judging from the auto-calibration figures seen on various Unix
|
||||
* systems on comparable hardware.
|
||||
*/
|
||||
#if defined(WIN32NATIVE)
|
||||
delay_decrement = 100;
|
||||
#else /* !WIN32NATIVE */
|
||||
struct itimerval itv;
|
||||
volatile int i;
|
||||
|
||||
if (verbose >= 2)
|
||||
fprintf(stderr,
|
||||
"%s: Calibrating delay loop...",
|
||||
progname);
|
||||
i = 0;
|
||||
done = 0;
|
||||
saved_alarmhandler = signal(SIGALRM, alarmhandler);
|
||||
/*
|
||||
* Set ITIMER_REAL to 100 ms. All known systems have a timer
|
||||
* granularity of 10 ms or better, so counting the delay cycles
|
||||
* accumulating over 100 ms should give us a rather realistic
|
||||
* picture, without annoying the user by a lengthy startup time (as
|
||||
* an alarm(1) would do). Of course, if heavy system activity
|
||||
* happens just during calibration but stops before the remaining
|
||||
* part of AVRDUDE runs, this will yield wrong values. There's not
|
||||
* much we can do about this.
|
||||
*/
|
||||
itv.it_value.tv_sec = 0;
|
||||
itv.it_value.tv_usec = 100000;
|
||||
itv.it_interval.tv_sec = itv.it_interval.tv_usec = 0;
|
||||
setitimer(ITIMER_REAL, &itv, 0);
|
||||
while (!done)
|
||||
i--;
|
||||
itv.it_value.tv_sec = itv.it_value.tv_usec = 0;
|
||||
setitimer(ITIMER_REAL, &itv, 0);
|
||||
/*
|
||||
* Calculate back from 100 ms to 1 us.
|
||||
*/
|
||||
delay_decrement = -i / 100000;
|
||||
if (verbose >= 2)
|
||||
fprintf(stderr,
|
||||
" calibrated to %d cycles per us\n",
|
||||
delay_decrement);
|
||||
#endif /* WIN32NATIVE */
|
||||
}
|
||||
|
||||
|
||||
static int bitbang_getpin(PROGRAMMER * pgm, int pin)
|
||||
/*
|
||||
* Delay for approximately the number of microseconds specified.
|
||||
* usleep()'s granularity is usually like 1 ms or 10 ms, so it's not
|
||||
* really suitable for short delays in bit-bang algorithms.
|
||||
*/
|
||||
void bitbang_delay(int us)
|
||||
{
|
||||
if ( pgm->flag )
|
||||
return serbb_getpin(pgm->fd,pin);
|
||||
else
|
||||
return par_getpin(pgm->fd,pin);
|
||||
volatile int del = us * delay_decrement;
|
||||
|
||||
while (del > 0)
|
||||
del--;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
*/
|
||||
@@ -82,7 +138,7 @@ static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
|
||||
/*
|
||||
* 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
|
||||
* one pgm->setpin()-call resp. par clrpin()-call, then
|
||||
* - SCK is high for 2T
|
||||
* - SCK is low for 2T
|
||||
* - MOSI setuptime is 1T
|
||||
@@ -99,17 +155,17 @@ static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
|
||||
b = (byte >> i) & 0x01;
|
||||
|
||||
/* set the data input line as desired */
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_MOSI], b);
|
||||
pgm->setpin(pgm, pgm->pinno[PIN_AVR_MOSI], b);
|
||||
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_SCK], 1);
|
||||
pgm->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]);
|
||||
r = pgm->getpin(pgm, pgm->pinno[PIN_AVR_MISO]);
|
||||
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_SCK], 0);
|
||||
pgm->setpin(pgm, pgm->pinno[PIN_AVR_SCK], 0);
|
||||
|
||||
rbyte |= r << i;
|
||||
}
|
||||
@@ -120,25 +176,25 @@ static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
|
||||
|
||||
int bitbang_rdy_led(PROGRAMMER * pgm, int value)
|
||||
{
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_LED_RDY], !value);
|
||||
pgm->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);
|
||||
pgm->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);
|
||||
pgm->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);
|
||||
pgm->setpin(pgm, pgm->pinno[PIN_LED_VFY], !value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -233,14 +289,16 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
int rc;
|
||||
int tries;
|
||||
|
||||
bitbang_calibrate_delay();
|
||||
|
||||
pgm->powerup(pgm);
|
||||
usleep(20000);
|
||||
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_SCK], 0);
|
||||
bitbang_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0);
|
||||
pgm->setpin(pgm, pgm->pinno[PIN_AVR_SCK], 0);
|
||||
pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0);
|
||||
usleep(20000);
|
||||
|
||||
bitbang_highpulsepin(pgm, pgm->pinno[PIN_AVR_RESET]);
|
||||
pgm->highpulsepin(pgm, pgm->pinno[PIN_AVR_RESET]);
|
||||
|
||||
usleep(20000); /* 20 ms XXX should be a per-chip parameter */
|
||||
|
||||
@@ -261,7 +319,7 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
rc = pgm->program_enable(pgm, p);
|
||||
if ((rc == 0)||(rc == -1))
|
||||
break;
|
||||
bitbang_highpulsepin(pgm, pgm->pinno[p->retry_pulse/*PIN_AVR_SCK*/]);
|
||||
pgm->highpulsepin(pgm, pgm->pinno[p->retry_pulse/*PIN_AVR_SCK*/]);
|
||||
tries++;
|
||||
} while (tries < 65);
|
||||
|
||||
@@ -277,4 +335,30 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void verify_pin_assigned(PROGRAMMER * pgm, int pin, char * desc)
|
||||
{
|
||||
if (pgm->pinno[pin] == 0) {
|
||||
fprintf(stderr, "%s: error: no pin has been assigned for %s\n",
|
||||
progname, desc);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Verify all prerequisites for a bit-bang programmer are present.
|
||||
*/
|
||||
void bitbang_check_prerequisites(PROGRAMMER *pgm)
|
||||
{
|
||||
|
||||
verify_pin_assigned(pgm, PIN_AVR_RESET, "AVR RESET");
|
||||
verify_pin_assigned(pgm, PIN_AVR_SCK, "AVR SCK");
|
||||
verify_pin_assigned(pgm, PIN_AVR_MISO, "AVR MISO");
|
||||
verify_pin_assigned(pgm, PIN_AVR_MOSI, "AVR MOSI");
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
fprintf(stderr, "%s: error: no cmd() method defined for bitbang programmer\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
int bitbang_setpin(int fd, int pin, int value);
|
||||
int bitbang_getpin(int fd, int pin);
|
||||
int bitbang_highpulsepin(int fd, int pin);
|
||||
void bitbang_delay(unsigned int us);
|
||||
|
||||
void bitbang_check_prerequisites(PROGRAMMER *pgm);
|
||||
|
||||
int bitbang_rdy_led (PROGRAMMER * pgm, int value);
|
||||
int bitbang_err_led (PROGRAMMER * pgm, int value);
|
||||
|
||||
@@ -69,7 +69,7 @@ static int butterfly_send(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return serial_send(pgm->fd, (unsigned char *)buf, len);
|
||||
return serial_send(&pgm->fd, (unsigned char *)buf, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ static int butterfly_recv(PROGRAMMER * pgm, char * buf, size_t len)
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
rv = serial_recv(pgm->fd, (unsigned char *)buf, len);
|
||||
rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: butterfly_recv(): programmer is not responding\n",
|
||||
@@ -94,7 +94,7 @@ static int butterfly_drain(PROGRAMMER * pgm, int display)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
return serial_drain(pgm->fd, display);
|
||||
return serial_drain(&pgm->fd, display);
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +227,6 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
char buf[10];
|
||||
char type;
|
||||
char c;
|
||||
int dev_supported = 0;
|
||||
|
||||
no_show_func_info();
|
||||
|
||||
@@ -297,9 +296,9 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
exit(1);
|
||||
};
|
||||
butterfly_recv(pgm, &c, 1);
|
||||
buffersize = c<<8;
|
||||
buffersize = (unsigned int)(unsigned char)c<<8;
|
||||
butterfly_recv(pgm, &c, 1);
|
||||
buffersize += c;
|
||||
buffersize += (unsigned int)(unsigned char)c;
|
||||
fprintf(stderr,
|
||||
"Programmer supports buffered memory access with buffersize=%i bytes.\n",
|
||||
buffersize);
|
||||
@@ -313,22 +312,9 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
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';
|
||||
@@ -337,10 +323,9 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
butterfly_send(pgm, buf, 2);
|
||||
butterfly_vfy_cmd_sent(pgm, "select device");
|
||||
|
||||
if (dev_supported)
|
||||
butterfly_enter_prog_mode(pgm);
|
||||
butterfly_enter_prog_mode(pgm);
|
||||
|
||||
return dev_supported? 0: -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -374,7 +359,7 @@ static int butterfly_open(PROGRAMMER * pgm, char * port)
|
||||
if(pgm->baudrate == 0) {
|
||||
pgm->baudrate = 19200;
|
||||
}
|
||||
pgm->fd = serial_open(port, pgm->baudrate);
|
||||
serial_open(port, pgm->baudrate, &pgm->fd);
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
@@ -389,11 +374,12 @@ static void butterfly_close(PROGRAMMER * pgm)
|
||||
{
|
||||
no_show_func_info();
|
||||
|
||||
/* "exit programmer" added by Martin Thomas 2/2004 */
|
||||
/* "exit programmer" */
|
||||
butterfly_send(pgm, "E", 1);
|
||||
butterfly_vfy_cmd_sent(pgm, "exit bootloader");
|
||||
|
||||
serial_close(pgm->fd);
|
||||
pgm->fd = -1;
|
||||
serial_close(&pgm->fd);
|
||||
pgm->fd.ifd = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -675,17 +661,15 @@ void butterfly_initpgm(PROGRAMMER * pgm)
|
||||
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;
|
||||
pgm->read_byte = butterfly_read_byte;
|
||||
pgm->write_byte = butterfly_write_byte;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ typedef struct token_t {
|
||||
int primary;
|
||||
VALUE value;
|
||||
} TOKEN;
|
||||
typedef struct token_t *token_p;
|
||||
|
||||
|
||||
extern FILE * yyin;
|
||||
@@ -58,7 +59,7 @@ extern char default_serial[];
|
||||
|
||||
|
||||
#if !defined(HAS_YYSTYPE)
|
||||
#define YYSTYPE struct token_t *
|
||||
#define YYSTYPE token_p
|
||||
#endif
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2006 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
|
||||
@@ -35,9 +36,12 @@
|
||||
#include "pgm.h"
|
||||
#include "stk500.h"
|
||||
#include "stk500v2.h"
|
||||
#include "stk500generic.h"
|
||||
#include "avr910.h"
|
||||
#include "butterfly.h"
|
||||
#include "usbasp.h"
|
||||
#include "avr.h"
|
||||
#include "jtagmkI.h"
|
||||
#include "jtagmkII.h"
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
@@ -64,6 +68,7 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_WRITE_HI
|
||||
%token K_LOADPAGE_LO
|
||||
%token K_LOADPAGE_HI
|
||||
%token K_LOAD_EXT_ADDR
|
||||
%token K_WRITEPAGE
|
||||
%token K_CHIP_ERASE
|
||||
%token K_PGM_ENABLE
|
||||
@@ -83,6 +88,11 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_DEFAULT_SERIAL
|
||||
%token K_DESC
|
||||
%token K_DEVICECODE
|
||||
%token K_DRAGON_DW
|
||||
%token K_DRAGON_HVSP
|
||||
%token K_DRAGON_ISP
|
||||
%token K_DRAGON_JTAG
|
||||
%token K_DRAGON_PP
|
||||
%token K_STK500_DEVCODE
|
||||
%token K_AVR910_DEVCODE
|
||||
%token K_EEPROM
|
||||
@@ -90,7 +100,10 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_FLASH
|
||||
%token K_ID
|
||||
%token K_IO
|
||||
%token K_JTAG_MKI
|
||||
%token K_JTAG_MKII
|
||||
%token K_JTAG_MKII_DW
|
||||
%token K_JTAG_MKII_ISP
|
||||
%token K_LOADPAGE
|
||||
%token K_MAX_WRITE_DELAY
|
||||
%token K_MIN_WRITE_DELAY
|
||||
@@ -114,10 +127,15 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_SERBB
|
||||
%token K_SERIAL
|
||||
%token K_SCK
|
||||
%token K_SIGNATURE
|
||||
%token K_SIZE
|
||||
%token K_STK500
|
||||
%token K_STK500HVSP
|
||||
%token K_STK500PP
|
||||
%token K_STK500V2
|
||||
%token K_STK500GENERIC
|
||||
%token K_AVR910
|
||||
%token K_USBASP
|
||||
%token K_BUTTERFLY
|
||||
%token K_TYPE
|
||||
%token K_VCC
|
||||
@@ -128,9 +146,11 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_YES
|
||||
|
||||
/* stk500 v2 xml file parameters */
|
||||
/* ISP */
|
||||
%token K_TIMEOUT
|
||||
%token K_STABDELAY
|
||||
%token K_CMDEXEDELAY
|
||||
%token K_HVSPCMDEXEDELAY
|
||||
%token K_SYNCHLOOPS
|
||||
%token K_BYTEDELAY
|
||||
%token K_POLLVALUE
|
||||
@@ -142,6 +162,29 @@ static int parse_cmdbits(OPCODE * op);
|
||||
%token K_DELAY
|
||||
%token K_BLOCKSIZE
|
||||
%token K_READSIZE
|
||||
/* HV mode */
|
||||
%token K_HVENTERSTABDELAY
|
||||
%token K_PROGMODEDELAY
|
||||
%token K_LATCHCYCLES
|
||||
%token K_TOGGLEVTG
|
||||
%token K_POWEROFFDELAY
|
||||
%token K_RESETDELAYMS
|
||||
%token K_RESETDELAYUS
|
||||
%token K_HVLEAVESTABDELAY
|
||||
%token K_RESETDELAY
|
||||
%token K_SYNCHCYCLES
|
||||
%token K_HVCMDEXEDELAY
|
||||
|
||||
%token K_CHIPERASEPULSEWIDTH
|
||||
%token K_CHIPERASEPOLLTIMEOUT
|
||||
%token K_CHIPERASETIME
|
||||
%token K_PROGRAMFUSEPULSEWIDTH
|
||||
%token K_PROGRAMFUSEPOLLTIMEOUT
|
||||
%token K_PROGRAMLOCKPULSEWIDTH
|
||||
%token K_PROGRAMLOCKPOLLTIMEOUT
|
||||
|
||||
%token K_PP_CONTROLSTACK
|
||||
%token K_HVSP_CONTROLSTACK
|
||||
|
||||
/* JTAG ICE mkII specific parameters */
|
||||
%token K_ALLOWFULLPAGEBITSTREAM /*
|
||||
@@ -153,10 +196,13 @@ static int parse_cmdbits(OPCODE * op);
|
||||
*/
|
||||
%token K_ENABLEPAGEPROGRAMMING /* ? yes for mega256*, mega406 */
|
||||
%token K_HAS_JTAG /* MCU has JTAG i/f. */
|
||||
%token K_HAS_DW /* MCU has debugWire 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 K_FLASH_INSTR /* flash instructions */
|
||||
%token K_EEPROM_INSTR /* EEPROM instructions */
|
||||
|
||||
%token TKN_COMMA
|
||||
%token TKN_EQUAL
|
||||
@@ -346,24 +392,96 @@ prog_parm :
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_STK500HVSP {
|
||||
{
|
||||
stk500hvsp_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_STK500PP {
|
||||
{
|
||||
stk500pp_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_STK500GENERIC {
|
||||
{
|
||||
stk500generic_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_AVR910 {
|
||||
{
|
||||
avr910_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_USBASP {
|
||||
{
|
||||
usbasp_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_BUTTERFLY {
|
||||
{
|
||||
butterfly_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_JTAG_MKI {
|
||||
{
|
||||
jtagmkI_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_JTAG_MKII {
|
||||
{
|
||||
jtagmkII_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_JTAG_MKII_DW {
|
||||
{
|
||||
jtagmkII_dw_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_JTAG_MKII_ISP {
|
||||
{
|
||||
stk500v2_jtagmkII_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_DRAGON_DW {
|
||||
{
|
||||
jtagmkII_dragon_dw_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_DRAGON_HVSP {
|
||||
{
|
||||
stk500v2_dragon_hvsp_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_DRAGON_ISP {
|
||||
{
|
||||
stk500v2_dragon_isp_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_DRAGON_JTAG {
|
||||
{
|
||||
jtagmkII_dragon_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_DRAGON_PP {
|
||||
{
|
||||
stk500v2_dragon_pp_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;
|
||||
@@ -380,15 +498,7 @@ prog_parm :
|
||||
while (lsize(number_list)) {
|
||||
t = lrmv_n(number_list, 1);
|
||||
pin = t->value.number;
|
||||
if ((pin < 2) || (pin > 9)) {
|
||||
fprintf(stderr,
|
||||
"%s: error at line %d of %s: VCC must be one or more "
|
||||
"pins from the range 2-9\n",
|
||||
progname, lineno, infile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
current_prog->pinno[PPI_AVR_VCC] |= (1 << (pin-2));
|
||||
current_prog->pinno[PPI_AVR_VCC] |= (1 << pin);
|
||||
|
||||
free_token(t);
|
||||
}
|
||||
@@ -405,15 +515,7 @@ prog_parm :
|
||||
while (lsize(number_list)) {
|
||||
t = lrmv_n(number_list, 1);
|
||||
pin = t->value.number;
|
||||
if ((pin < 2) || (pin > 9)) {
|
||||
fprintf(stderr,
|
||||
"%s: error at line %d of %s: BUFF must be one or more "
|
||||
"pins from the range 2-9\n",
|
||||
progname, lineno, infile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
current_prog->pinno[PPI_AVR_BUFF] |= (1 << (pin-2));
|
||||
current_prog->pinno[PPI_AVR_BUFF] |= (1 << pin);
|
||||
|
||||
free_token(t);
|
||||
}
|
||||
@@ -459,6 +561,7 @@ opcode :
|
||||
K_WRITE_HI |
|
||||
K_LOADPAGE_LO |
|
||||
K_LOADPAGE_HI |
|
||||
K_LOAD_EXT_ADDR |
|
||||
K_WRITEPAGE |
|
||||
K_CHIP_ERASE |
|
||||
K_PGM_ENABLE
|
||||
@@ -522,6 +625,165 @@ part_parm :
|
||||
}
|
||||
} |
|
||||
|
||||
K_SIGNATURE TKN_EQUAL TKN_NUMBER TKN_NUMBER TKN_NUMBER {
|
||||
{
|
||||
current_part->signature[0] = $3->value.number;
|
||||
current_part->signature[1] = $4->value.number;
|
||||
current_part->signature[2] = $5->value.number;
|
||||
free_token($3);
|
||||
free_token($4);
|
||||
free_token($5);
|
||||
}
|
||||
} |
|
||||
|
||||
K_PP_CONTROLSTACK TKN_EQUAL num_list {
|
||||
{
|
||||
TOKEN * t;
|
||||
unsigned nbytes;
|
||||
int ok;
|
||||
|
||||
if (current_part->ctl_stack_type != CTL_STACK_NONE)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: error at line %d of %s: "
|
||||
"control stack already defined\n",
|
||||
progname, lineno, infile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
current_part->ctl_stack_type = CTL_STACK_PP;
|
||||
nbytes = 0;
|
||||
ok = 1;
|
||||
|
||||
while (lsize(number_list)) {
|
||||
t = lrmv_n(number_list, 1);
|
||||
if (nbytes < CTL_STACK_SIZE)
|
||||
{
|
||||
current_part->controlstack[nbytes] = t->value.number;
|
||||
nbytes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = 0;
|
||||
}
|
||||
free_token(t);
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: Warning: line %d of %s: "
|
||||
"too many bytes in control stack\n",
|
||||
progname, lineno, infile);
|
||||
}
|
||||
}
|
||||
} |
|
||||
|
||||
K_HVSP_CONTROLSTACK TKN_EQUAL num_list {
|
||||
{
|
||||
TOKEN * t;
|
||||
unsigned nbytes;
|
||||
int ok;
|
||||
|
||||
if (current_part->ctl_stack_type != CTL_STACK_NONE)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: error at line %d of %s: "
|
||||
"control stack already defined\n",
|
||||
progname, lineno, infile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
current_part->ctl_stack_type = CTL_STACK_HVSP;
|
||||
nbytes = 0;
|
||||
ok = 1;
|
||||
|
||||
while (lsize(number_list)) {
|
||||
t = lrmv_n(number_list, 1);
|
||||
if (nbytes < CTL_STACK_SIZE)
|
||||
{
|
||||
current_part->controlstack[nbytes] = t->value.number;
|
||||
nbytes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = 0;
|
||||
}
|
||||
free_token(t);
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: Warning: line %d of %s: "
|
||||
"too many bytes in control stack\n",
|
||||
progname, lineno, infile);
|
||||
}
|
||||
}
|
||||
} |
|
||||
|
||||
K_FLASH_INSTR TKN_EQUAL num_list {
|
||||
{
|
||||
TOKEN * t;
|
||||
unsigned nbytes;
|
||||
int ok;
|
||||
|
||||
nbytes = 0;
|
||||
ok = 1;
|
||||
|
||||
while (lsize(number_list)) {
|
||||
t = lrmv_n(number_list, 1);
|
||||
if (nbytes < FLASH_INSTR_SIZE)
|
||||
{
|
||||
current_part->flash_instr[nbytes] = t->value.number;
|
||||
nbytes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = 0;
|
||||
}
|
||||
free_token(t);
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: Warning: line %d of %s: "
|
||||
"too many bytes in flash instructions\n",
|
||||
progname, lineno, infile);
|
||||
}
|
||||
}
|
||||
} |
|
||||
|
||||
K_EEPROM_INSTR TKN_EQUAL num_list {
|
||||
{
|
||||
TOKEN * t;
|
||||
unsigned nbytes;
|
||||
int ok;
|
||||
|
||||
nbytes = 0;
|
||||
ok = 1;
|
||||
|
||||
while (lsize(number_list)) {
|
||||
t = lrmv_n(number_list, 1);
|
||||
if (nbytes < EEPROM_INSTR_SIZE)
|
||||
{
|
||||
current_part->eeprom_instr[nbytes] = t->value.number;
|
||||
nbytes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = 0;
|
||||
}
|
||||
free_token(t);
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: Warning: line %d of %s: "
|
||||
"too many bytes in EEPROM instructions\n",
|
||||
progname, lineno, infile);
|
||||
}
|
||||
}
|
||||
} |
|
||||
|
||||
K_CHIP_ERASE_DELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->chip_erase_delay = $3->value.number;
|
||||
@@ -568,6 +830,12 @@ part_parm :
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HVSPCMDEXEDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->hvspcmdexedelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_SYNCHLOOPS TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->synchloops = $3->value.number;
|
||||
@@ -610,6 +878,108 @@ part_parm :
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HVENTERSTABDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->hventerstabdelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_PROGMODEDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->progmodedelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_LATCHCYCLES TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->latchcycles = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_TOGGLEVTG TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->togglevtg = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_POWEROFFDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->poweroffdelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_RESETDELAYMS TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->resetdelayms = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_RESETDELAYUS TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->resetdelayus = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HVLEAVESTABDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->hvleavestabdelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_RESETDELAY TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->resetdelay = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_CHIPERASEPULSEWIDTH TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->chiperasepulsewidth = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_CHIPERASEPOLLTIMEOUT TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->chiperasepolltimeout = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_CHIPERASETIME TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->chiperasetime = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_PROGRAMFUSEPULSEWIDTH TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->programfusepulsewidth = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_PROGRAMFUSEPOLLTIMEOUT TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->programfusepolltimeout = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_PROGRAMLOCKPULSEWIDTH TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->programlockpulsewidth = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_PROGRAMLOCKPOLLTIMEOUT TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->programlockpolltimeout = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_SYNCHCYCLES TKN_EQUAL TKN_NUMBER
|
||||
{
|
||||
current_part->synchcycles = $3->value.number;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HAS_JTAG TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
@@ -620,6 +990,16 @@ part_parm :
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HAS_DW TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
current_part->flags |= AVRPART_HAS_DW;
|
||||
else if ($3->primary == K_NO)
|
||||
current_part->flags &= ~AVRPART_HAS_DW;
|
||||
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_ALLOWFULLPAGEBITSTREAM TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
@@ -907,6 +1287,7 @@ static int which_opcode(TOKEN * opcode)
|
||||
case K_WRITE_HI : return AVR_OP_WRITE_HI; break;
|
||||
case K_LOADPAGE_LO : return AVR_OP_LOADPAGE_LO; break;
|
||||
case K_LOADPAGE_HI : return AVR_OP_LOADPAGE_HI; break;
|
||||
case K_LOAD_EXT_ADDR : return AVR_OP_LOAD_EXT_ADDR; break;
|
||||
case K_WRITEPAGE : return AVR_OP_WRITEPAGE; break;
|
||||
case K_CHIP_ERASE : return AVR_OP_CHIP_ERASE; break;
|
||||
case K_PGM_ENABLE : return AVR_OP_PGM_ENABLE; break;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT(avrdude, 5.0cvs, avrdude-dev@nongnu.org)
|
||||
AC_INIT(avrdude, 5.3, avrdude-dev@nongnu.org)
|
||||
|
||||
AC_CANONICAL_BUILD
|
||||
AC_CANONICAL_HOST
|
||||
@@ -32,7 +32,7 @@ AC_CANONICAL_TARGET
|
||||
|
||||
AC_CONFIG_SRCDIR([main.c])
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_CONFIG_HEADER([ac_cfg.h])
|
||||
AM_CONFIG_HEADER(ac_cfg.h)
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
@@ -44,13 +44,65 @@ 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])
|
||||
AH_TEMPLATE([HAVE_LIBUSB],
|
||||
[Define if USB support is enabled via libusb])
|
||||
AC_CHECK_LIB([usb], [usb_get_string_simple], [have_libusb=yes])
|
||||
if test x$have_libusb = xyes; then
|
||||
case $target in
|
||||
*-*-darwin*)
|
||||
LIBUSB="-lusb -framework CoreFoundation -framework IOKit"
|
||||
;;
|
||||
*)
|
||||
LIBUSB="-lusb"
|
||||
;;
|
||||
esac
|
||||
AC_DEFINE([HAVE_LIBUSB])
|
||||
fi
|
||||
AC_SUBST(LIBUSB, $LIBUSB)
|
||||
|
||||
AC_MSG_CHECKING([for a Win32 HID libray])
|
||||
SAVED_LIBS="${LIBS}"
|
||||
case $target in
|
||||
*-*-mingw32*)
|
||||
LIBHID="-lhid -lsetupapi"
|
||||
HIDINCLUDE="#include <ddk/hidsdi.h>"
|
||||
;;
|
||||
*)
|
||||
LIBHID="-lhid"
|
||||
HIDINCLUDE='#include "my_ddk_hidsdi.h"'
|
||||
;;
|
||||
esac
|
||||
LIBS="${LIBS} ${LIBHID}"
|
||||
|
||||
AH_TEMPLATE([HAVE_LIBHID],
|
||||
[Define if HID support is enabled via the Win32 DDK])
|
||||
AC_TRY_RUN([#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
$HIDINCLUDE
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
GUID hidGuid;
|
||||
HidD_GetHidGuid(&hidGuid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
], [have_libhid=yes], [have_libhid=no], [have_libhid=no])
|
||||
AC_MSG_RESULT([$have_libhid])
|
||||
if test x$have_libhid = xyes; then
|
||||
AC_DEFINE([HAVE_LIBHID])
|
||||
else
|
||||
LIBHID=""
|
||||
fi
|
||||
LIBS="${SAVED_LIBS}"
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([fcntl.h limits.h stdlib.h string.h sys/ioctl.h sys/time.h termios.h unistd.h])
|
||||
AC_CHECK_HEADERS([limits.h stdlib.h string.h])
|
||||
AC_CHECK_HEADERS([fcntl.h sys/ioctl.h sys/time.h termios.h unistd.h])
|
||||
AC_CHECK_HEADERS([ddk/hidsdi.h],,,[#include <windows.h>
|
||||
#include <setupapi.h>])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
@@ -59,7 +111,7 @@ AC_HEADER_TIME
|
||||
# Checks for library functions.
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_FUNC_MALLOC
|
||||
AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul])
|
||||
AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul gettimeofday])
|
||||
|
||||
# Checks for misc stuff.
|
||||
|
||||
@@ -85,7 +137,7 @@ AC_ARG_ENABLE(
|
||||
[doc],
|
||||
AC_HELP_STRING(
|
||||
[--enable-doc],
|
||||
[Enable building documents(default)]),
|
||||
[Enable building documents]),
|
||||
[case "${enableval}" in
|
||||
yes) enabled_doc=yes ;;
|
||||
no) enabled_doc=no ;;
|
||||
@@ -93,6 +145,18 @@ AC_ARG_ENABLE(
|
||||
esac],
|
||||
[enabled_doc=no])
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
[parport],
|
||||
AC_HELP_STRING(
|
||||
[--enable-parport],
|
||||
[Enable accessing parallel ports(default)]),
|
||||
[case "${enableval}" in
|
||||
yes) enabled_parport=yes ;;
|
||||
no) enabled_parport=no ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for enable-parport option) ;;
|
||||
esac],
|
||||
[enabled_parport=yes])
|
||||
|
||||
if test "$enabled_doc" = "yes"; then
|
||||
|
||||
SUBDIRS_AC='doc @WINDOWS_DIRS@'
|
||||
@@ -104,14 +168,14 @@ DIST_SUBDIRS_AC='windows'
|
||||
fi
|
||||
|
||||
AC_SUBST(DOC_INST_DIR, $DOC_INST_DIR)
|
||||
AC_SUBST(SUBDIRS_AC, $SUBDIRS_AC)
|
||||
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.
|
||||
case $target in
|
||||
i[[3456]]86-*-linux*)
|
||||
i[[3456]]86-*-linux*|x86_64-*-linux*)
|
||||
DEFAULT_PAR_PORT="/dev/parport0"
|
||||
DEFAULT_SER_PORT="/dev/ttyS0"
|
||||
;;
|
||||
@@ -119,7 +183,7 @@ case $target in
|
||||
DEFAULT_PAR_PORT="unknown"
|
||||
DEFAULT_SER_PORT="/dev/ttyS0"
|
||||
;;
|
||||
i[[3456]]86-*-freebsd*)
|
||||
i[[3456]]86-*-freebsd*|amd64-*-freebsd*)
|
||||
DEFAULT_PAR_PORT="/dev/ppi0"
|
||||
DEFAULT_SER_PORT="/dev/cuaa0"
|
||||
;;
|
||||
@@ -127,6 +191,10 @@ case $target in
|
||||
DEFAULT_PAR_PORT="unknown"
|
||||
DEFAULT_SER_PORT="/dev/cuaa0"
|
||||
;;
|
||||
*-*-solaris*)
|
||||
DEFAULT_PAR_PORT="/dev/printers/0"
|
||||
DEFAULT_SER_PORT="/dev/term/a"
|
||||
;;
|
||||
*-*-msdos* | *-*-mingw32* | *-*-cygwin* | *-*-windows*)
|
||||
DEFAULT_PAR_PORT="lpt1"
|
||||
DEFAULT_SER_PORT="com1"
|
||||
@@ -137,20 +205,35 @@ case $target in
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_CHECKING([for parallel device])
|
||||
AC_MSG_RESULT([$DEFAULT_PAR_PORT])
|
||||
AC_SUBST(DEFAULT_PAR_PORT, $DEFAULT_PAR_PORT)
|
||||
if test "$enabled_parport" = "yes"; then
|
||||
AC_MSG_CHECKING([for parallel device])
|
||||
if test "$DEFAULT_PAR_PORT" = "unknown"; then
|
||||
AC_MSG_NOTICE([parallel port access disabled for this system])
|
||||
enabled_parport=no
|
||||
else
|
||||
AC_MSG_RESULT([$DEFAULT_PAR_PORT])
|
||||
fi
|
||||
AC_SUBST(DEFAULT_PAR_PORT, $DEFAULT_PAR_PORT)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for serial device])
|
||||
AC_MSG_RESULT([$DEFAULT_SER_PORT])
|
||||
AC_SUBST(DEFAULT_SER_PORT, $DEFAULT_SER_PORT)
|
||||
|
||||
if test "$enabled_parport" = "yes"; then
|
||||
AC_DEFINE(HAVE_PARPORT, 1, [parallel port access enabled])
|
||||
confsubst="-e /^@HAVE_PARPORT_/d"
|
||||
else
|
||||
confsubst="-e /^@HAVE_PARPORT_BEGIN@/,/^@HAVE_PARPORT_END@/d"
|
||||
fi
|
||||
export confsubst
|
||||
|
||||
# See if we need to drop into the windows subdir.
|
||||
case $target in
|
||||
*-*-mingw32* | *-*-cygwin* | *-*-windows*)
|
||||
WINDOWS_DIRS="windows"
|
||||
CFLAGS="-mno-cygwin -DWIN32NATIVE"
|
||||
LDFLAGS="-static"
|
||||
LDFLAGS="${LDFLAGS} -static"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(WINDOWS_DIRS,$WINDOWS_DIRS)
|
||||
@@ -168,9 +251,17 @@ fi
|
||||
AC_CONFIG_FILES([
|
||||
windows/Makefile
|
||||
avrdude.spec
|
||||
avrdude.conf
|
||||
Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
# The procedure to create avrdude.conf involves two steps. First,
|
||||
# normal autoconf substitution will be applied, resulting in
|
||||
# avrdude.conf.tmp. Finally, a sed command will be applied to filter
|
||||
# out unwanted parts (currently the parallel port programmer types)
|
||||
# based on previous configuration results, thereby producing the final
|
||||
# avrdude.conf file.
|
||||
|
||||
AC_CONFIG_FILES([avrdude.conf.tmp:avrdude.conf.in],
|
||||
[sed $confsubst avrdude.conf.tmp > avrdude.conf])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
22
avrdude/doc/.cvsignore
Normal file
22
avrdude/doc/.cvsignore
Normal file
@@ -0,0 +1,22 @@
|
||||
.cvsignore
|
||||
Makefile
|
||||
Makefile.in
|
||||
avrdude-html
|
||||
avrdude.aux
|
||||
avrdude.cp
|
||||
avrdude.cps
|
||||
avrdude.dvi
|
||||
avrdude.fn
|
||||
avrdude.info
|
||||
avrdude.ky
|
||||
avrdude.log
|
||||
avrdude.pdf
|
||||
avrdude.pg
|
||||
avrdude.ps
|
||||
avrdude.toc
|
||||
avrdude.tp
|
||||
avrdude.vr
|
||||
mdate-sh
|
||||
stamp-vti
|
||||
texinfo.tex
|
||||
version.texi
|
||||
@@ -28,7 +28,9 @@ This file documents the avrdude program.
|
||||
|
||||
For avrdude version @value{VERSION}, @value{UPDATED}.
|
||||
|
||||
Copyright @copyright{} 2003,2005 Brian Dean
|
||||
Copyright @copyright{} 2003, 2005 Brian Dean
|
||||
|
||||
Copyright @copyright{} 2006 J@"org Wunsch
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
@@ -59,11 +61,13 @@ by the Free Software Foundation.
|
||||
@author by Brian S. Dean
|
||||
|
||||
@page
|
||||
@hfill (Send bugs and comments on AVRDUDE to @w{@email{avrdude-dev@@nongnu.org}}.)
|
||||
Send comments on AVRDUDE to @w{@email{avrdude-dev@@nongnu.org}}.
|
||||
|
||||
@vfill
|
||||
Use @uref{http://savannah.nongnu.org/bugs/?group=avrdude} to report bugs.
|
||||
|
||||
Copyright @copyright{} 2003,2005 Brian S. Dean
|
||||
|
||||
Copyright @copyright{} 2006 J@"org Wunsch
|
||||
@sp 2
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
@@ -94,6 +98,14 @@ This file documents the avrdude program for downloading/uploading
|
||||
programs to Atmel AVR microcontrollers.
|
||||
|
||||
For avrdude version @value{VERSION}, @value{UPDATED}.
|
||||
|
||||
Send comments on AVRDUDE to @w{@email{avrdude-dev@@nongnu.org}}.
|
||||
|
||||
Use @uref{http://savannah.nongnu.org/bugs/?group=avrdude} to report bugs.
|
||||
|
||||
Copyright @copyright{} 2003,2005 Brian S. Dean
|
||||
|
||||
Copyright @copyright{} 2006 J@"org Wunsch
|
||||
@end ifinfo
|
||||
|
||||
@menu
|
||||
@@ -129,8 +141,9 @@ 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
|
||||
AVRDUDE supports the following basic programmer types: Atmel's STK500,
|
||||
Atmel's AVRISP and AVRISP mkII devices,
|
||||
Atmel's JTAG ICE (both mkI and mkII, the latter also in ISP mode), appnote
|
||||
avr910, appnote avr109 (including the AVR Butterfly),
|
||||
serial bit-bang adapters,
|
||||
and the PPI (parallel port interface). PPI represents a class
|
||||
@@ -166,9 +179,29 @@ 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.)
|
||||
(The JTAG ICE mkII protocol can also be run on top of USB.)
|
||||
Only the memory programming functionality of the JTAG ICE is supported
|
||||
by AVRDUDE.
|
||||
For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported.
|
||||
See below for the limitations of debugWire.
|
||||
|
||||
The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP, debugWire).
|
||||
(High-voltage programming is not yet supported.)
|
||||
When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
|
||||
JTAG ICE mkII, so all device-specific comments for that device
|
||||
will apply as well.
|
||||
When used in ISP mode, the AVR Dragon behaves similar to an
|
||||
AVRISP mkII (or JTAG ICE mkII in ISP mode), so all device-specific
|
||||
comments will apply there.
|
||||
In particular, the Dragon starts out with a rather fast ISP clock
|
||||
frequency, so the @code{-B @var{bitclock}}
|
||||
option might be required to achieve a stable ISP communication.
|
||||
|
||||
The USBasp ISP adapter is also supported, provided AVRDUDE
|
||||
has been compiled with libusb support.
|
||||
It features a simple firwmare-only USB implementation, running on
|
||||
an ATmega8 (or ATmega88).
|
||||
|
||||
|
||||
@menu
|
||||
* History::
|
||||
@@ -223,9 +256,9 @@ Roth.
|
||||
@noindent
|
||||
AVRDUDE is a command line tool, used as follows:
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
avrdude -p partno @var{options} @dots{}
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
Command line options are used to control AVRDUDE's behaviour. The
|
||||
@@ -242,140 +275,67 @@ but it can be added to the configuration file if you have the Atmel
|
||||
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
|
||||
|
||||
@itemx 2313
|
||||
AT90S2313
|
||||
|
||||
@itemx 2333
|
||||
AT90S2333
|
||||
|
||||
@itemx 2343
|
||||
AT90S2343 (*)
|
||||
|
||||
@itemx 4414
|
||||
AT90S4414
|
||||
|
||||
@itemx 4433
|
||||
AT90S4433
|
||||
|
||||
@itemx 4434
|
||||
AT90S4434
|
||||
|
||||
@itemx 8515
|
||||
AT90S8515
|
||||
|
||||
@itemx 8535
|
||||
AT90S8535
|
||||
|
||||
@itemx m103
|
||||
ATmega103
|
||||
|
||||
@itemx m128
|
||||
ATmega128
|
||||
|
||||
@itemx m16
|
||||
ATmega16
|
||||
|
||||
@itemx m161
|
||||
ATmega161
|
||||
|
||||
@itemx m162
|
||||
ATmega162
|
||||
|
||||
@itemx m163
|
||||
ATmega163
|
||||
|
||||
@itemx m164
|
||||
ATmega164
|
||||
|
||||
@itemx m169
|
||||
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
|
||||
|
||||
@itemx m8
|
||||
ATmega8
|
||||
|
||||
@itemx m8515
|
||||
ATmega8515
|
||||
|
||||
@itemx m8535
|
||||
ATmega8535
|
||||
|
||||
@itemx m88
|
||||
ATmega88
|
||||
|
||||
@itemx t12
|
||||
ATtiny12
|
||||
|
||||
@itemx t13
|
||||
ATtiny13
|
||||
|
||||
@itemx t15
|
||||
ATtiny15
|
||||
|
||||
@itemx t2313
|
||||
ATtiny2313
|
||||
|
||||
@itemx t25
|
||||
ATtiny25
|
||||
|
||||
@itemx t26
|
||||
ATtiny26
|
||||
|
||||
@itemx t45
|
||||
ATtiny45
|
||||
|
||||
@itemx t85
|
||||
ATtiny85
|
||||
|
||||
@end table
|
||||
@multitable @columnfractions .15 .3
|
||||
@item @code{c128} @tab AT90CAN128
|
||||
@item @code{pwm2} @tab AT90PWM2
|
||||
@item @code{pwm3} @tab AT90PWM3
|
||||
@item @code{1200} @tab AT90S1200
|
||||
@item @code{2313} @tab AT90S2313
|
||||
@item @code{2333} @tab AT90S2333
|
||||
@item @code{2343} @tab AT90S2343 (*)
|
||||
@item @code{4414} @tab AT90S4414
|
||||
@item @code{4433} @tab AT90S4433
|
||||
@item @code{4434} @tab AT90S4434
|
||||
@item @code{8515} @tab AT90S8515
|
||||
@item @code{8535} @tab AT90S8535
|
||||
@item @code{m103} @tab ATmega103
|
||||
@item @code{m128} @tab ATmega128
|
||||
@item @code{m1280} @tab ATmega1280
|
||||
@item @code{m1281} @tab ATmega1281
|
||||
@item @code{m16} @tab ATmega16
|
||||
@item @code{m161} @tab ATmega161
|
||||
@item @code{m162} @tab ATmega162
|
||||
@item @code{m163} @tab ATmega163
|
||||
@item @code{m164} @tab ATmega164
|
||||
@item @code{m169} @tab ATmega169
|
||||
@item @code{m2560} @tab ATmega2560 (**)
|
||||
@item @code{m2561} @tab ATmega2561 (**)
|
||||
@item @code{m32} @tab ATmega32
|
||||
@item @code{m324} @tab ATmega324
|
||||
@item @code{m329} @tab ATmega329
|
||||
@item @code{m3290} @tab ATmega3290
|
||||
@item @code{m48} @tab ATmega48
|
||||
@item @code{m64} @tab ATmega64
|
||||
@item @code{m640} @tab ATmega640
|
||||
@item @code{m644} @tab ATmega644
|
||||
@item @code{m649} @tab ATmega649
|
||||
@item @code{m6490} @tab ATmega6490
|
||||
@item @code{m8} @tab ATmega8
|
||||
@item @code{m8515} @tab ATmega8515
|
||||
@item @code{m8535} @tab ATmega8535
|
||||
@item @code{m88} @tab ATmega88
|
||||
@item @code{t12} @tab ATtiny12
|
||||
@item @code{t13} @tab ATtiny13
|
||||
@item @code{t15} @tab ATtiny15
|
||||
@item @code{t2313} @tab ATtiny2313
|
||||
@item @code{t25} @tab ATtiny25
|
||||
@item @code{t26} @tab ATtiny26
|
||||
@item @code{t45} @tab ATtiny45
|
||||
@item @code{t85} @tab ATtiny85
|
||||
@end multitable
|
||||
|
||||
(*) The AT90S2323 and ATtiny22 use the same algorithm.
|
||||
|
||||
(**) Flash addressing above 128 KB is not supported by all
|
||||
programming hardware. Known to work are jtag2, stk500v2,
|
||||
and bit-bang programmers.
|
||||
|
||||
@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).
|
||||
Specify the bit clock period for the JTAG interface or the ISP clock (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
|
||||
@@ -397,70 +357,87 @@ file without any code changes to AVRDUDE. Simply copy an existing entry
|
||||
and change the pin definitions to match that of the unknown programmer.
|
||||
Currently, the following programmer ids are understood and supported:
|
||||
|
||||
@table @code
|
||||
|
||||
@itemx abcmini
|
||||
@multitable @columnfractions .2 .6
|
||||
@item @code{abcmini} @tab
|
||||
ABCmini Board, aka Dick Smith HOTCHIP
|
||||
|
||||
@itemx alf
|
||||
Nightshade ALF-PgmAVR, http://nightshade.homeip.net/
|
||||
|
||||
@itemx avr109
|
||||
@item @code{alf} @tab
|
||||
Nightshade ALF-PgmAVR,@*
|
||||
@url{http://nightshade.homeip.net/}
|
||||
@item @code{avr109} @tab
|
||||
Atmel AppNote AVR109 Boot Loader
|
||||
|
||||
@itemx avr910
|
||||
@item @code{avr910} @tab
|
||||
Atmel Low Cost Serial Programmer
|
||||
|
||||
@itemx avr911
|
||||
@item @code{avr911} @tab
|
||||
Atmel AppNote AVR911 AVROSP (an alias for avr109)
|
||||
|
||||
@itemx avrisp
|
||||
Atmel AVR ISP
|
||||
|
||||
@itemx bascom
|
||||
@item @code{avrisp} @tab
|
||||
Atmel AVR ISP (an alias for stk500)
|
||||
@item @code{avrispv2} @tab
|
||||
Atmel AVR ISP, running a version 2.x firmware (an alias for stk500v2)
|
||||
@item @code{avrispmkII} @tab
|
||||
Atmel AVR ISP mkII (alias for stk500v2)
|
||||
@item @code{avrispmk2} @tab
|
||||
Atmel AVR ISP mkII (alias for stk500v2)
|
||||
@item @code{bascom} @tab
|
||||
Bascom SAMPLE programming cable
|
||||
|
||||
@itemx bsd
|
||||
Brian Dean's Programmer, http://www.bsdhome.com/avrdude/
|
||||
|
||||
@itemx butterfly
|
||||
@item @code{bsd} @tab
|
||||
Brian Dean's Programmer,@*
|
||||
@url{http://www.bsdhome.com/avrdude/}
|
||||
@item @code{butterfly} @tab
|
||||
Atmel Butterfly Development Board
|
||||
|
||||
@itemx dt006
|
||||
@item @code{dt006} @tab
|
||||
Dontronics DT006
|
||||
|
||||
@item jtagmkII
|
||||
@itemx jtag2slow
|
||||
@item @code{dragon_dw} @tab
|
||||
AVR Dragon in debugWire mode
|
||||
@item @code{dragon_hvsp} @tab
|
||||
AVR Dragon in high-voltage serial programming mode
|
||||
@item @code{dragon_isp} @tab
|
||||
AVR Dragon in ISP mode
|
||||
@item @code{dragon_jtag} @tab
|
||||
AVR Dragon in JTAG mode
|
||||
@item @code{dragon_pp} @tab
|
||||
AVR Dragon in (high-voltage) parallel programming mode
|
||||
@item @code{frank-stk200} @tab
|
||||
Frank's STK200 clone, @url{http://electropol.free.fr/spip/spip.php?article15}
|
||||
@item @code{jtagmkI} @tab
|
||||
Atmel JTAG ICE mkI, running at 115200 Bd
|
||||
@item @code{jtag1} @tab
|
||||
@emph{Same as before.}
|
||||
@item @code{jtag1slow} @tab
|
||||
Atmel JTAG ICE mkI, running at 19200 Bd
|
||||
@item @code{jtagmkII} @tab
|
||||
Atmel JTAG ICE mkII (default speed 19200 Bd)
|
||||
|
||||
@itemx jtag2fast
|
||||
@item @code{jtag2slow} @tab
|
||||
@emph{Same as before.}
|
||||
@item @code{jtag2fast} @tab
|
||||
Atmel JTAG ICE mkII, running at 115200 Bd
|
||||
|
||||
@itemx jtag2
|
||||
Same as before.
|
||||
|
||||
@itemx pavr
|
||||
@item @code{jtag2} @tab
|
||||
@emph{Same as before.}
|
||||
@item @code{jtag2isp} @tab
|
||||
Atmel JTAG ICE mkII in ISP mode.
|
||||
@item @code{jtag2dw} @tab
|
||||
Atmel JTAG ICE mkII in debugWire mode.
|
||||
@item @code{pavr} @tab
|
||||
Jason Kyle's pAVR Serial Programmer
|
||||
|
||||
@itemx picoweb
|
||||
Picoweb Programming Cable, http://www.picoweb.net/
|
||||
|
||||
@itemx pony-stk200
|
||||
@item @code{picoweb} @tab
|
||||
Picoweb Programming Cable,@*
|
||||
@url{http://www.picoweb.net/}
|
||||
@item @code{pony-stk200} @tab
|
||||
Pony Prog STK200
|
||||
|
||||
@itemx sp12
|
||||
@item @code{sp12} @tab
|
||||
Steve Bolt's Programmer
|
||||
|
||||
@itemx stk200
|
||||
@item @code{stk200} @tab
|
||||
STK200
|
||||
|
||||
@itemx stk500
|
||||
Atmel STK500
|
||||
|
||||
@itemx stk500v2
|
||||
Atmel STK500, running a verrsion 2.x firmware
|
||||
|
||||
@end table
|
||||
@item @code{stk500} @tab
|
||||
Atmel STK500, probing for either version 1.x or 2.x firmware
|
||||
@item @code{stk500v1} @tab
|
||||
Atmel STK500, running a version 1.x firmware
|
||||
@item @code{stk500hvsp} @tab
|
||||
Atmel STK500 in high-voltage serial programming mode(version 2.x firmware only)
|
||||
@item @code{stk500pp} @tab
|
||||
Atmel STK500 in parallel programming mode (version 2.xfirmware only)
|
||||
@item @code{stk500v2} @tab
|
||||
Atmel STK500, running a version 2.x firmware
|
||||
@end multitable
|
||||
|
||||
|
||||
|
||||
@@ -534,10 +511,34 @@ 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{delay}
|
||||
For bitbang-type programmers, delay for approximately
|
||||
@var{delay}
|
||||
microseconds between each bit state change.
|
||||
If the host system is very fast, or the target runs off a slow clock
|
||||
(like a 32 kHz crystal, or the 128 kHz internal RC oscillator), this
|
||||
can become necessary to satisfy the requirement that the ISP clock
|
||||
frequency must not be higher than 1/4 of the CPU clock frequency.
|
||||
This is implemented as a spin-loop delay to allow even for very
|
||||
short delays.
|
||||
On Unix-style operating systems, the spin loop is initially calibrated
|
||||
against a system timer, so the number of microseconds might be rather
|
||||
realistic, assuming a constant system load while AVRDUDE is running.
|
||||
On Win32 operating systems, a preconfigured number of cycles per
|
||||
microsecond is assumed that might be off a bit for very fast or very
|
||||
slow machines.
|
||||
|
||||
@item -n
|
||||
No-write - disables actually writing data to the MCU (useful for
|
||||
debugging AVRDUDE).
|
||||
|
||||
@item -O
|
||||
Perform a RC oscillator run-time calibration according to Atmel
|
||||
application note AVR053.
|
||||
This is only supported on the STK500v2, AVRISP mkII, and JTAG ICE mkII
|
||||
hardware.
|
||||
Note that the result will be stored in the EEPROM cell at address 0.
|
||||
|
||||
@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
|
||||
@@ -548,12 +549,38 @@ 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
|
||||
@code{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.
|
||||
For a trick how to find out the serial numbers of all JTAG ICEs
|
||||
attached to USB, see @ref{Example Command Line Invocations}.
|
||||
|
||||
As the AVRISP mkII device can only be talked to over USB, the very
|
||||
same method of specifying the port is required there.
|
||||
|
||||
For the USB programmer "AVR-Doper" running in HID mode, the port must
|
||||
be specified as @var{avrdoper}. Libusb support is required on Unix
|
||||
but not on Windows. For more information about AVR-Doper see
|
||||
@url{http://www.obdev.at/avrusb/avrdoper.html}.
|
||||
|
||||
For programmers that attach to a serial port using some kind of
|
||||
higher level protocol (as opposed to bit-bang style programmers),
|
||||
@var{port} can be specified as @code{net}:@var{host}:@var{port}.
|
||||
In this case, instead of trying to open a local device, a TCP
|
||||
network connection to (TCP) @var{port} on @var{host}
|
||||
is established.
|
||||
The remote endpoint is assumed to be a terminal or console server
|
||||
that connects the network stream to a local serial port where the
|
||||
actual programmer has been attached to.
|
||||
The port is assumed to be properly configured, for example using a
|
||||
transparent 8-bit data connection without parity at 115200 Baud
|
||||
for a STK500.
|
||||
|
||||
@emph{This feature is currently not implemented for Win32 systems.}
|
||||
|
||||
|
||||
@item -q
|
||||
Disable (or quell) output of the progress bar while reading or writing
|
||||
@@ -650,6 +677,23 @@ treated as decimal.
|
||||
auto detect; valid for input only, and only if the input is not provided
|
||||
at stdin.
|
||||
|
||||
@itemx d
|
||||
decimal; this and the following formats are only valid on output.
|
||||
They generate one line of output for the respective memory section,
|
||||
forming a comma-separated list of the values.
|
||||
This can be particularly useful for subsequent processing, like for
|
||||
fuse bit settings.
|
||||
|
||||
@itemx h
|
||||
hexadecimal; each value will get the string @emph{0x} prepended.
|
||||
|
||||
@itemx o
|
||||
octal; each value will get a @emph{0}
|
||||
prepended unless it is less than 8 in which case it gets no prefix.
|
||||
|
||||
@itemx b
|
||||
binary; each value will get the string @emph{0b} prepended.
|
||||
|
||||
@end table
|
||||
|
||||
The default is to use auto detection for input files, and raw binary
|
||||
@@ -659,6 +703,11 @@ 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}.
|
||||
|
||||
As an abbreviation, the form @code{-U} @var{filename}
|
||||
is equivalent to specifying
|
||||
@code{-U} @emph{flash:w:}@var{filename}@emph{:a}.
|
||||
This will only work if @var{filename} does not have a colon in it.
|
||||
|
||||
@item -v
|
||||
Enable verbose output.
|
||||
|
||||
@@ -699,7 +748,7 @@ should not be used.
|
||||
Download the file @code{diag.hex} to the ATmega128 chip using the
|
||||
STK500 programmer connected to the default serial port:
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
@cartouche
|
||||
% avrdude -p m128 -c stk500 -e -U flash:w:diag.hex
|
||||
|
||||
@@ -735,7 +784,7 @@ avrdude done. Thank you.
|
||||
|
||||
%
|
||||
@end cartouche
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
@page
|
||||
@noindent
|
||||
@@ -743,7 +792,7 @@ 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}:
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
@cartouche
|
||||
% avrdude -p m128 -c stk500 -U flash:r:"c:/diag flash.bin":r
|
||||
|
||||
@@ -764,7 +813,7 @@ avrdude done. Thank you.
|
||||
|
||||
%
|
||||
@end cartouche
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
@page
|
||||
@noindent
|
||||
@@ -772,7 +821,7 @@ Using the default programmer, download the file @code{diag.hex} to
|
||||
flash, @code{eeprom.hex} to EEPROM, and set the Extended, High, and Low
|
||||
fuse bytes to 0xff, 0x89, and 0x2e respectively:
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
@cartouche
|
||||
|
||||
% avrdude -p m128 -u -U flash:w:diag.hex \
|
||||
@@ -813,14 +862,14 @@ avrdude done. Thank you.
|
||||
|
||||
%
|
||||
@end cartouche
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
@page
|
||||
@noindent
|
||||
Connect to the JTAG ICE mkII which serial number ends up in 1C37 via
|
||||
USB, and enter terminal mode:
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
@cartouche
|
||||
|
||||
% avrdude -c jtag2 -p m649 -P usb:1c:37 -t
|
||||
@@ -836,8 +885,27 @@ avrdude: Device signature = 0x1e9603
|
||||
avrdude done. Thank you.
|
||||
|
||||
@end cartouche
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
List the serial numbers of all JTAG ICEs attached to USB. This is
|
||||
done by specifying an invalid serial number, and increasing the
|
||||
verbosity level.
|
||||
|
||||
@smallexample
|
||||
@cartouche
|
||||
|
||||
% avrdude -c jtag2 -p m128 -P usb:xx -v
|
||||
[...]
|
||||
Using Port : usb:xxx
|
||||
Using Programmer : jtag2
|
||||
avrdude: usbdev_open(): Found JTAG ICE, serno: 00A000001C6B
|
||||
avrdude: usbdev_open(): Found JTAG ICE, serno: 00A000001C3A
|
||||
avrdude: usbdev_open(): Found JTAG ICE, serno: 00A000001C30
|
||||
avrdude: usbdev_open(): did not find any (matching) USB device "usb:xxx"
|
||||
|
||||
@end cartouche
|
||||
@end smallexample
|
||||
|
||||
|
||||
@c
|
||||
@@ -939,6 +1007,8 @@ 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.
|
||||
This parameter can also be used on the JTAG ICE mkII to specify the
|
||||
ISP clock period when operating the ICE in ISP mode.
|
||||
|
||||
@item parms
|
||||
@emph{STK500 only:}
|
||||
@@ -958,7 +1028,7 @@ Display the current target supply voltage and JTAG bit clock rate/period.
|
||||
@noindent
|
||||
Display part parameters, modify eeprom cells, perform a chip erase:
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
@cartouche
|
||||
% avrdude -p m128 -c stk500 -t
|
||||
|
||||
@@ -1010,7 +1080,7 @@ avrdude> dump eeprom 0 16
|
||||
|
||||
avrdude>
|
||||
@end cartouche
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
|
||||
@noindent
|
||||
@@ -1020,7 +1090,7 @@ 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:
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
@cartouche
|
||||
% avrdude -p m128 -u -c stk500 -t
|
||||
|
||||
@@ -1050,7 +1120,7 @@ avrdude> w lfuse 0 0x2f
|
||||
|
||||
avrdude>
|
||||
@end cartouche
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
|
||||
@c
|
||||
@@ -1119,7 +1189,7 @@ option.
|
||||
@noindent
|
||||
The format of the programmer definition is as follows:
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
programmer
|
||||
id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
|
||||
desc = <description> ; # quoted string
|
||||
@@ -1135,7 +1205,7 @@ programmer
|
||||
pgmled = <num> ; # pin number
|
||||
vfyled = <num> ; # pin number
|
||||
;
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
|
||||
@c
|
||||
@@ -1144,7 +1214,7 @@ programmer
|
||||
@node Part Definitions, Other Notes, Programmer Definitions, Configuration File
|
||||
@section Part Definitions
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
part
|
||||
id = <id> ; # quoted string
|
||||
desc = <description> ; # quoted string
|
||||
@@ -1177,7 +1247,7 @@ part
|
||||
writepage = <instruction format> ;
|
||||
;
|
||||
;
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
@menu
|
||||
* Instruction Format::
|
||||
@@ -1226,7 +1296,7 @@ specification closely follows the instruction data provided in Atmel's
|
||||
data sheets for their parts. For example, the EEPROM read and write
|
||||
instruction for an AT90S2313 AVR part could be encoded as:
|
||||
|
||||
@example
|
||||
@smallexample
|
||||
|
||||
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";
|
||||
@@ -1234,7 +1304,7 @@ read = "1 0 1 0 0 0 0 0 x x x x x x x x",
|
||||
write = "1 1 0 0 0 0 0 0 x x x x x x x x",
|
||||
"x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
|
||||
|
||||
@end example
|
||||
@end smallexample
|
||||
|
||||
|
||||
|
||||
@@ -1464,6 +1534,9 @@ The following table lists the default names for a given system.
|
||||
@item Linux
|
||||
@tab @code{/dev/parport0}
|
||||
@tab @code{/dev/ttyS0}
|
||||
@item Solaris
|
||||
@tab @code{/dev/printers/0}
|
||||
@tab @code{/dev/term/a}
|
||||
@end multitable
|
||||
|
||||
On FreeBSD systems, AVRDUDE uses the ppi(4) interface for
|
||||
@@ -1474,6 +1547,10 @@ On Linux systems, AVRDUDE uses the ppdev interface for
|
||||
accessing the parallel port and the tty driver for serial port
|
||||
access.
|
||||
|
||||
On Solaris systems, AVRDUDE uses the ecpp(7D) driver for
|
||||
accessing the parallel port and the asy(7D) driver for serial port
|
||||
access.
|
||||
|
||||
@c
|
||||
@c Node
|
||||
@c
|
||||
@@ -1750,6 +1827,7 @@ line driven and for writing the batch files.
|
||||
|
||||
@noindent
|
||||
In general, please report any bugs encountered via
|
||||
@*
|
||||
@url{http://savannah.nongnu.org/bugs/?group=avrdude}.
|
||||
|
||||
|
||||
@@ -1791,35 +1869,104 @@ 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.
|
||||
JTAG ICEs.
|
||||
|
||||
Solution: None at this time. Currently, the JTAG ICE mkII code cannot
|
||||
Solution: None at this time. Currently, the JTAG ICE code cannot
|
||||
write to the flash ROM one byte at a time.
|
||||
|
||||
@item
|
||||
Problem: Page-mode programming the EEPROM (using the -U option) does
|
||||
not erase EEPROM cells before writing, and thus cannot overwrite any
|
||||
previous value != 0xff.
|
||||
|
||||
Solution: None. This is an inherent feature of the way JTAG EEPROM
|
||||
programming works, and is documented that way in the Atmel AVR
|
||||
datasheets.
|
||||
In order to successfully program the EEPROM that way, a prior chip
|
||||
erase (with the EESAVE fuse unprogrammed) is required.
|
||||
This also applies to the STK500 in high-voltage programming mode.
|
||||
|
||||
@item
|
||||
Problem: How do I turn off the @var{DWEN} fuse?
|
||||
|
||||
Solution: If the @var{DWEN} (debugWire enable) fuse is activated,
|
||||
the @var{/RESET} pin is not functional anymore, so normal ISP
|
||||
communication cannot be established.
|
||||
There are two options to deactivate that fuse again: high-voltage
|
||||
programming, or getting the JTAG ICE mkII talk debugWire, and
|
||||
prepare the target AVR to accept normal ISP communication again.
|
||||
|
||||
The first option requires a programmer that is capable of high-voltage
|
||||
programming (either serial or parallel, depending on the AVR device),
|
||||
for example the STK500. In high-voltage programming mode, the
|
||||
@var{/RESET} pin is activated initially using a 12 V pulse (thus the
|
||||
name @emph{high voltage}), so the target AVR can subsequently be
|
||||
reprogrammed, and the @var{DWEN} fuse can be cleared. Typically, this
|
||||
operation cannot be performed while the AVR is located in the target
|
||||
circuit though.
|
||||
|
||||
The second option requires a JTAG ICE mkII that can talk the debugWire
|
||||
protocol. The ICE needs to be connected to the target using the
|
||||
JTAG-to-ISP adapter, so the JTAG ICE mkII can be used as a debugWire
|
||||
initiator as well as an ISP programmer. AVRDUDE will then be activated
|
||||
using the @var{jtag2isp} programmer type. The initial ISP
|
||||
communication attempt will fail, but AVRDUDE then tries to iniate a
|
||||
debugWire reset. When successful, this will leave the target AVR in a
|
||||
state where it can accept standard ISP communication. The ICE is then
|
||||
signed off (which will make it signing off from the USB as well), so
|
||||
AVRDUDE has to be called again afterwards. This time, standard ISP
|
||||
communication can work, so the @var{DWEN} fuse can be cleared.
|
||||
|
||||
The pin mapping for the JTAG-to-ISP adapter is:
|
||||
|
||||
@multitable @columnfractions .2 .2
|
||||
@item @strong{JTAG pin} @tab @strong{ISP pin}
|
||||
@item 1 @tab 3
|
||||
@item 2 @tab 6
|
||||
@item 3 @tab 1
|
||||
@item 4 @tab 2
|
||||
@item 6 @tab 5
|
||||
@item 9 @tab 4
|
||||
@end multitable
|
||||
|
||||
@item
|
||||
Problem: Multiple USBasp programmers connected simultaneously are not
|
||||
found.
|
||||
|
||||
Solution: none at this time. The simplicity of the USBasp programmer
|
||||
doesn't offer a method to distinguish multiple programmers that are
|
||||
connected simultaneously, so effectively only one USBasp is supported.
|
||||
|
||||
@item
|
||||
Problem: I cannot do @dots{} when the target is in debugWire mode.
|
||||
|
||||
Solution: debugWire mode imposes several limitations.
|
||||
|
||||
The debugWire protocol is Atmel's proprietary one-wire (plus ground)
|
||||
protocol to allow an in-circuit emulation of the smaller AVR devices,
|
||||
using the @var{/RESET} line.
|
||||
DebugWire mode is initiated by activating the @var{DWEN}
|
||||
fuse, and then power-cycling the target.
|
||||
While this mode is mainly intented for debugging/emulation, it
|
||||
also offers limited programming capabilities.
|
||||
Effectively, the only memory areas that can be read or programmed
|
||||
in this mode are flash ROM and EEPROM.
|
||||
It is also possible to read out the signature.
|
||||
All other memory areas cannot be accessed.
|
||||
There is no
|
||||
@emph{chip erase}
|
||||
functionality in debugWire mode; instead, while reprogramming the
|
||||
flash ROM, each flash ROM page is erased right before updating it.
|
||||
This is done transparently by the JTAG ICE mkII (or AVR Dragon).
|
||||
The only way back from debugWire mode is to initiate a special
|
||||
sequence of commands to the JTAG ICE mkII (or AVR Dragon), so the
|
||||
debugWire mode will be temporarily disabled, and the target can
|
||||
be accessed using normal ISP programming.
|
||||
This sequence is automatically initiated by using the JTAG ICE mkII
|
||||
or AVR Dragon in ISP mode, when they detect that ISP mode cannot be
|
||||
entered.
|
||||
|
||||
|
||||
@end itemize
|
||||
|
||||
126
avrdude/fileio.c
126
avrdude/fileio.c
@@ -77,6 +77,10 @@ int fileio_ihex(struct fioparms * fio,
|
||||
int fileio_srec(struct fioparms * fio,
|
||||
char * filename, FILE * f, unsigned char * buf, int size);
|
||||
|
||||
int fileio_num(struct fioparms * fio,
|
||||
char * filename, FILE * f, unsigned char * buf, int size,
|
||||
FILEFMT fmt);
|
||||
|
||||
int fmt_autodetect(char * fname);
|
||||
|
||||
|
||||
@@ -658,6 +662,45 @@ int srec2b(char * infile, FILE * inf,
|
||||
return maxaddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple itoa() implementation. Caller needs to allocate enough
|
||||
* space in buf. Only positive integers are handled.
|
||||
*/
|
||||
static char *itoa_simple(int n, char *buf, int base)
|
||||
{
|
||||
div_t q;
|
||||
char c, *cp, *cp2;
|
||||
|
||||
cp = buf;
|
||||
/*
|
||||
* Divide by base until the number disappeared, but ensure at least
|
||||
* one digit will be emitted.
|
||||
*/
|
||||
do {
|
||||
q = div(n, base);
|
||||
n = q.quot;
|
||||
if (q.rem >= 10)
|
||||
c = q.rem - 10 + 'a';
|
||||
else
|
||||
c = q.rem + '0';
|
||||
*cp++ = c;
|
||||
} while (q.quot != 0);
|
||||
|
||||
/* Terminate the string. */
|
||||
*cp-- = '\0';
|
||||
|
||||
/* Now revert the result string. */
|
||||
cp2 = buf;
|
||||
while (cp > cp2) {
|
||||
c = *cp;
|
||||
*cp-- = *cp2;
|
||||
*cp2++ = c;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int fileio_rbin(struct fioparms * fio,
|
||||
char * filename, FILE * f, unsigned char * buf, int size)
|
||||
@@ -793,6 +836,78 @@ int fileio_srec(struct fioparms * fio,
|
||||
}
|
||||
|
||||
|
||||
int fileio_num(struct fioparms * fio,
|
||||
char * filename, FILE * f, unsigned char * buf, int size,
|
||||
FILEFMT fmt)
|
||||
{
|
||||
const char *prefix;
|
||||
char cbuf[20];
|
||||
int base, i, num;
|
||||
|
||||
switch (fmt) {
|
||||
case FMT_HEX:
|
||||
prefix = "0x";
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
case FMT_DEC:
|
||||
prefix = "";
|
||||
base = 10;
|
||||
break;
|
||||
|
||||
case FMT_OCT:
|
||||
prefix = "0";
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
case FMT_BIN:
|
||||
prefix = "0b";
|
||||
base = 2;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
switch (fio->op) {
|
||||
case FIO_WRITE:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: fileio: invalid operation=%d\n",
|
||||
progname, fio->op);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (i > 0) {
|
||||
if (putc(',', f) == EOF)
|
||||
goto writeerr;
|
||||
}
|
||||
num = (unsigned int)buf[i];
|
||||
/*
|
||||
* For a base of 8 and a value < 8 to convert, don't write the
|
||||
* prefix. The conversion will be indistinguishable from a
|
||||
* decimal one then.
|
||||
*/
|
||||
if (prefix[0] != '\0' && !(base == 8 && num < 8)) {
|
||||
if (fputs(prefix, f) == EOF)
|
||||
goto writeerr;
|
||||
}
|
||||
itoa_simple(num, cbuf, base);
|
||||
if (fputs(cbuf, f) == EOF)
|
||||
goto writeerr;
|
||||
}
|
||||
if (putc('\n', f) == EOF)
|
||||
goto writeerr;
|
||||
|
||||
return 0;
|
||||
|
||||
writeerr:
|
||||
fprintf(stderr, "%s: error writing to %s: %s\n",
|
||||
progname, filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int fileio_setparms(int op, struct fioparms * fp)
|
||||
{
|
||||
fp->op = op;
|
||||
@@ -911,7 +1026,7 @@ int fileio(int op, char * filename, FILEFMT format,
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
#if defined(WIN32NATIVE)
|
||||
/* Open Raw Binary format in binary mode on Windows.*/
|
||||
if(format == FMT_RBIN)
|
||||
{
|
||||
@@ -924,7 +1039,7 @@ int fileio(int op, char * filename, FILEFMT format,
|
||||
fio.mode = "wb";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* point at the requested memory buffer */
|
||||
buf = mem->buf;
|
||||
@@ -1005,6 +1120,13 @@ int fileio(int op, char * filename, FILEFMT format,
|
||||
rc = fileio_imm(&fio, fname, f, buf, size);
|
||||
break;
|
||||
|
||||
case FMT_HEX:
|
||||
case FMT_DEC:
|
||||
case FMT_OCT:
|
||||
case FMT_BIN:
|
||||
rc = fileio_num(&fio, fname, f, buf, size, format);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s: invalid %s file format: %d\n",
|
||||
progname, fio.iodesc, format);
|
||||
|
||||
@@ -27,7 +27,11 @@ typedef enum {
|
||||
FMT_SREC,
|
||||
FMT_IHEX,
|
||||
FMT_RBIN,
|
||||
FMT_IMM
|
||||
FMT_IMM,
|
||||
FMT_HEX,
|
||||
FMT_DEC,
|
||||
FMT_OCT,
|
||||
FMT_BIN
|
||||
} FILEFMT;
|
||||
|
||||
struct fioparms {
|
||||
|
||||
40
avrdude/freebsd_ppi.h
Normal file
40
avrdude/freebsd_ppi.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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$ */
|
||||
|
||||
#ifndef freebsd_ppi_h
|
||||
#define freebsd_ppi_h
|
||||
|
||||
#include <dev/ppbus/ppi.h>
|
||||
|
||||
#define ppi_claim(fd) {}
|
||||
|
||||
#define ppi_release(fd) {}
|
||||
|
||||
#define DO_PPI_READ(fd, reg, valp) \
|
||||
(void)ioctl(fd, \
|
||||
(reg) == PPIDATA? PPIGDATA: ((reg) == PPICTRL? PPIGCTRL: PPIGSTATUS), \
|
||||
valp)
|
||||
#define DO_PPI_WRITE(fd, reg, valp) \
|
||||
(void)ioctl(fd, \
|
||||
(reg) == PPIDATA? PPISDATA: ((reg) == PPICTRL? PPISCTRL: PPISSTATUS), \
|
||||
valp)
|
||||
|
||||
#endif /* freebsd_ppi_h */
|
||||
1380
avrdude/jtagmkI.c
Normal file
1380
avrdude/jtagmkI.c
Normal file
File diff suppressed because it is too large
Load Diff
28
avrdude/jtagmkI.h
Normal file
28
avrdude/jtagmkI.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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 jtagmkI_h
|
||||
#define jtagmkI_h
|
||||
|
||||
void jtagmkI_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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-2004, 2006 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,7 +22,17 @@
|
||||
#ifndef jtagmkII_h
|
||||
#define jtagmkII_h
|
||||
|
||||
int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len);
|
||||
int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg);
|
||||
void jtagmkII_close(PROGRAMMER * pgm);
|
||||
int jtagmkII_getsync(PROGRAMMER * pgm, int mode);
|
||||
int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm,
|
||||
unsigned char * value);
|
||||
|
||||
void jtagmkII_initpgm (PROGRAMMER * pgm);
|
||||
void jtagmkII_dw_initpgm (PROGRAMMER * pgm);
|
||||
void jtagmkII_dragon_initpgm (PROGRAMMER * pgm);
|
||||
void jtagmkII_dragon_dw_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2005 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2005, 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -26,6 +26,7 @@
|
||||
* Taken from Appnote AVR067
|
||||
*/
|
||||
|
||||
#if !defined(JTAGMKII_PRIVATE_EXPORTED)
|
||||
/*
|
||||
* Communication with the JTAG ICE works in frames. The protocol
|
||||
* somewhat resembles the STK500v2 protocol, yet it is sufficiently
|
||||
@@ -71,6 +72,8 @@
|
||||
*/
|
||||
#define MAX_MESSAGE 100000
|
||||
|
||||
#endif /* JTAGMKII_PRIVATE_EXPORTED */
|
||||
|
||||
/* ICE command codes */
|
||||
#define CMND_CHIP_ERASE 0x13
|
||||
#define CMND_CLEAR_EVENTS 0x22
|
||||
@@ -83,6 +86,7 @@
|
||||
#define CMND_GET_SIGN_ON 0x01
|
||||
#define CMND_GET_SYNC 0x0f
|
||||
#define CMND_GO 0x08
|
||||
#define CMND_ISP_PACKET 0x2F
|
||||
#define CMND_LEAVE_PROGMODE 0x15
|
||||
#define CMND_READ_MEMORY 0x05
|
||||
#define CMND_READ_PC 0x07
|
||||
@@ -173,7 +177,7 @@
|
||||
#define PAR_EMULATOR_MODE 0x03
|
||||
# define EMULATOR_MODE_DEBUGWIRE 0x00
|
||||
# define EMULATOR_MODE_JTAG 0x01
|
||||
# define EMULATOR_MODE_UNKNOWN 0x02
|
||||
# define EMULATOR_MODE_HV 0x02 /* HVSP or PP mode of AVR Dragon */
|
||||
# define EMULATOR_MODE_SPI 0x03
|
||||
#define PAR_IREG 0x04
|
||||
#define PAR_BAUD_RATE 0x05
|
||||
@@ -232,6 +236,7 @@
|
||||
# define PAGEPROG_NOT_ALLOWED 0x00
|
||||
# define PAGEPROG_ALLOWED 0x01
|
||||
|
||||
#if !defined(JTAGMKII_PRIVATE_EXPORTED)
|
||||
/*
|
||||
* In appnote AVR067, struct device_descriptor is written with
|
||||
* int/long field types. We cannot use them directly, as they were
|
||||
@@ -288,3 +293,4 @@ struct device_descriptor
|
||||
/* new as of early 2005, firmware 4.x */
|
||||
unsigned char EECRAddress[2]; /* EECR memory-mapped IO address */
|
||||
};
|
||||
#endif /* JTAGMKII_PRIVATE_EXPORTED */
|
||||
|
||||
169
avrdude/jtagmkI_private.h
Normal file
169
avrdude/jtagmkI_private.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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 mkI definitions
|
||||
*/
|
||||
|
||||
/* ICE command codes */
|
||||
/* 0x20 Get Synch [Resp_OK] */
|
||||
#define CMD_GET_SYNC ' '
|
||||
|
||||
/* 0x31 Single Step [Sync_CRC/EOP] [Resp_OK] */
|
||||
/* 0x32 Read PC [Sync_CRC/EOP] [Resp_OK] [program counter]
|
||||
* [Resp_OK] */
|
||||
/* 0x33 Write PC [program counter] [Sync_CRC/EOP] [Resp_OK]
|
||||
* [Resp_OK] */
|
||||
/* 0xA2 Firmware Upgrade [upgrade string] [Sync_CRC/EOP] [Resp_OK]
|
||||
* [Resp_OK] */
|
||||
/* 0xA0 Set Device Descriptor [device info] [Sync_CRC/EOP] [Resp_OK]
|
||||
* [Resp_OK] */
|
||||
#define CMD_SET_DEVICE_DESCRIPTOR 0xA0
|
||||
|
||||
/* 0x42 Set Parameter [parameter] [setting] [Sync_CRC/EOP] [Resp_OK]
|
||||
* [Resp_OK] */
|
||||
#define CMD_SET_PARAM 'B'
|
||||
|
||||
/* 0x46 Forced Stop [Sync_CRC/EOP] [Resp_OK] [checksum][program
|
||||
* counter] [Resp_OK] */
|
||||
#define CMD_STOP 'F'
|
||||
|
||||
/* 0x47 Go [Sync_CRC/EOP] [Resp_OK] */
|
||||
#define CMD_GO 'G'
|
||||
|
||||
/* 0x52 Read Memory [memory type] [word count] [start address]
|
||||
* [Sync_CRC/EOP] [Resp_OK] [word 0] ... [word n] [checksum]
|
||||
* [Resp_OK] */
|
||||
#define CMD_READ_MEM 'R'
|
||||
|
||||
/* 0x53 Get Sign On [Sync_CRC/EOP] [Resp_OK] ["AVRNOCD"] [Resp_OK] */
|
||||
#define CMD_GET_SIGNON 'S'
|
||||
|
||||
/* 0XA1 Erase Page spm [address] [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */
|
||||
|
||||
/* 0x57 Write Memory [memory type] [word count] [start address]
|
||||
* [Sync_CRC/EOP] [Resp_OK] [Cmd_DATA] [word 0] ... [word n] */
|
||||
#define CMD_WRITE_MEM 'W'
|
||||
|
||||
/* Second half of write memory: the data command. Undocumented. */
|
||||
#define CMD_DATA 'h'
|
||||
|
||||
/* 0x64 Get Debug Info [Sync_CRC/EOP] [Resp_OK] [0x00] [Resp_OK] */
|
||||
/* 0x71 Get Parameter [parameter] [Sync_CRC/EOP] [Resp_OK] [setting]
|
||||
* [Resp_OK] */
|
||||
#define CMD_GET_PARAM 'q'
|
||||
|
||||
/* 0x78 Reset [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */
|
||||
#define CMD_RESET 'x'
|
||||
|
||||
/* 0xA3 Enter Progmode [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */
|
||||
#define CMD_ENTER_PROGMODE 0xa3
|
||||
|
||||
/* 0xA4 Leave Progmode [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */
|
||||
#define CMD_LEAVE_PROGMODE 0xa4
|
||||
|
||||
/* 0xA5 Chip Erase [Sync_CRC/EOP] [Resp_OK] [Resp_OK] */
|
||||
#define CMD_CHIP_ERASE 0xa5
|
||||
|
||||
|
||||
/* ICE responses */
|
||||
#define RESP_OK 'A'
|
||||
#define RESP_BREAK 'B'
|
||||
#define RESP_INFO 'G'
|
||||
#define RESP_FAILED 'F'
|
||||
#define RESP_SYNC_ERROR 'E'
|
||||
#define RESP_SLEEP 'H'
|
||||
#define RESP_POWER 'I'
|
||||
|
||||
#define PARM_BITRATE 'b'
|
||||
#define PARM_SW_VERSION 0x7b
|
||||
#define PARM_HW_VERSION 0x7a
|
||||
#define PARM_IREG_HIGH 0x81
|
||||
#define PARM_IREG_LOW 0x82
|
||||
#define PARM_OCD_VTARGET 0x84
|
||||
#define PARM_OCD_BREAK_CAUSE 0x85
|
||||
#define PARM_CLOCK 0x86
|
||||
#define PARM_EXTERNAL_RESET 0x8b
|
||||
#define PARM_FLASH_PAGESIZE_LOW 0x88
|
||||
#define PARM_FLASH_PAGESIZE_HIGH 0x89
|
||||
#define PARM_EEPROM_PAGESIZE 0x8a
|
||||
#define PARM_TIMERS_RUNNING 0xa0
|
||||
#define PARM_BP_FLOW 0xa1
|
||||
#define PARM_BP_X_HIGH 0xa2
|
||||
#define PARM_BP_X_LOW 0xa3
|
||||
#define PARM_BP_Y_HIGH 0xa4
|
||||
#define PARM_BP_Y_LOW 0xa5
|
||||
#define PARM_BP_MODE 0xa6
|
||||
#define PARM_JTAGID_BYTE0 0xa7
|
||||
#define PARM_JTAGID_BYTE1 0xa8
|
||||
#define PARM_JTAGID_BYTE2 0xa9
|
||||
#define PARM_JTAGID_BYTE3 0xaa
|
||||
#define PARM_UNITS_BEFORE 0xab
|
||||
#define PARM_UNITS_AFTER 0xac
|
||||
#define PARM_BIT_BEFORE 0xad
|
||||
#define PARM_BIT_AFTER 0xae
|
||||
#define PARM_PSB0_LOW 0xaf
|
||||
#define PARM_PSBO_HIGH 0xb0
|
||||
#define PARM_PSB1_LOW 0xb1
|
||||
#define PARM_PSB1_HIGH 0xb2
|
||||
#define PARM_MCU_MODE 0xb3
|
||||
|
||||
#define JTAG_BITRATE_1_MHz 0xff
|
||||
#define JTAG_BITRATE_500_kHz 0xfe
|
||||
#define JTAG_BITRATE_250_kHz 0xfd
|
||||
#define JTAG_BITRATE_125_kHz 0xfb
|
||||
|
||||
/* 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 */
|
||||
|
||||
struct device_descriptor
|
||||
{
|
||||
unsigned char ucReadIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */
|
||||
unsigned char ucWriteIO[8]; /*LSB = IOloc 0, MSB = IOloc63 */
|
||||
unsigned char ucReadIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */
|
||||
unsigned char ucWriteIOShadow[8]; /*LSB = IOloc 0, MSB = IOloc63 */
|
||||
unsigned char ucReadExtIO[20]; /*LSB = IOloc 96, MSB = IOloc255 */
|
||||
unsigned char ucWriteExtIO[20]; /*LSB = IOloc 96, MSB = IOloc255 */
|
||||
unsigned char ucReadIOExtShadow[20]; /*LSB = IOloc 96, MSB = IOloc255 */
|
||||
unsigned char ucWriteIOExtShadow[20];/*LSB = IOloc 96, MSB = IOloc255 */
|
||||
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; /*Topmost (last) extended I/O */
|
||||
/*location, 0 if no external I/O */
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2006 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
|
||||
@@ -46,17 +47,22 @@ HEXDIGIT [0-9a-fA-F]
|
||||
ID [_a-zA-Z][_a-zA-Z0-9]*
|
||||
SIGN [+-]
|
||||
|
||||
%x str
|
||||
%x strng
|
||||
%x incl
|
||||
%x comment
|
||||
|
||||
/* Bump resources for classic lex. */
|
||||
%e2000
|
||||
%p5000
|
||||
%n1000
|
||||
|
||||
%%
|
||||
|
||||
{SIGN}*{DIGIT}+ { yylval = number(yytext); return TKN_NUMBER; }
|
||||
{SIGN}*{DIGIT}+"."{DIGIT}* { yylval = number(yytext); return TKN_NUMBER; }
|
||||
{SIGN}*"."{DIGIT}* { yylval = number(yytext); return TKN_NUMBER; }
|
||||
|
||||
"\"" { string_buf_ptr = string_buf; BEGIN(str); }
|
||||
"\"" { string_buf_ptr = string_buf; BEGIN(strng); }
|
||||
|
||||
0x{HEXDIGIT}+ { yylval = hexnumber(yytext); return TKN_NUMBER; }
|
||||
|
||||
@@ -64,7 +70,7 @@ SIGN [+-]
|
||||
|
||||
# { /* The following eats '#' style comments to end of line */
|
||||
BEGIN(comment); }
|
||||
<comment>[^\n] /* eat comments */
|
||||
<comment>[^\n] { /* eat comments */ }
|
||||
<comment>\n { lineno++; BEGIN(INITIAL); }
|
||||
|
||||
|
||||
@@ -99,25 +105,24 @@ SIGN [+-]
|
||||
}
|
||||
|
||||
|
||||
<str>{
|
||||
\" { *string_buf_ptr = 0; string_buf_ptr = string_buf;
|
||||
yylval = string(string_buf_ptr); BEGIN(INITIAL); return TKN_STRING; }
|
||||
\\n *string_buf_ptr++ = '\n';
|
||||
\\t *string_buf_ptr++ = '\t';
|
||||
\\r *string_buf_ptr++ = '\r';
|
||||
\\b *string_buf_ptr++ = '\b';
|
||||
\\f *string_buf_ptr++ = '\f';
|
||||
\\(.|\n) *(string_buf_ptr++) = yytext[1];
|
||||
[^\\\n\"]+ { char *yptr = yytext; while (*yptr)
|
||||
<strng>\" { *string_buf_ptr = 0; string_buf_ptr = string_buf;
|
||||
yylval = string(string_buf_ptr); BEGIN(INITIAL); return TKN_STRING; }
|
||||
<strng>\\n *string_buf_ptr++ = '\n';
|
||||
<strng>\\t *string_buf_ptr++ = '\t';
|
||||
<strng>\\r *string_buf_ptr++ = '\r';
|
||||
<strng>\\b *string_buf_ptr++ = '\b';
|
||||
<strng>\\f *string_buf_ptr++ = '\f';
|
||||
<strng>\\(.|\n) *(string_buf_ptr++) = yytext[1];
|
||||
<strng>[^\\\n\"]+ { char *yptr = yytext; while (*yptr)
|
||||
*(string_buf_ptr++) = *(yptr++); }
|
||||
\n { fprintf(stderr, "error at line %d: unterminated character constant\n",
|
||||
lineno);
|
||||
exit(1); }
|
||||
}
|
||||
<strng>\n { fprintf(stderr, "error at line %d: unterminated character constant\n",
|
||||
lineno);
|
||||
exit(1); }
|
||||
|
||||
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
|
||||
avr910 { yylval=NULL; return K_AVR910; }
|
||||
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
|
||||
usbasp { yylval=NULL; return K_USBASP; }
|
||||
bank_size { yylval=NULL; return K_PAGE_SIZE; }
|
||||
banked { yylval=NULL; return K_PAGED; }
|
||||
baudrate { yylval=NULL; return K_BAUDRATE; }
|
||||
@@ -130,15 +135,24 @@ 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; }
|
||||
dragon_dw { yylval=NULL; return K_DRAGON_DW; }
|
||||
dragon_hvsp { yylval=NULL; return K_DRAGON_HVSP; }
|
||||
dragon_isp { yylval=NULL; return K_DRAGON_ISP; }
|
||||
dragon_jtag { yylval=NULL; return K_DRAGON_JTAG; }
|
||||
dragon_pp { yylval=NULL; return K_DRAGON_PP; }
|
||||
eecr { yylval=NULL; return K_EECR; }
|
||||
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; }
|
||||
has_debugwire { yylval=NULL; return K_HAS_DW; }
|
||||
id { yylval=NULL; return K_ID; }
|
||||
idr { yylval=NULL; return K_IDR; }
|
||||
jtagmki { yylval=NULL; return K_JTAG_MKI; }
|
||||
jtagmkii { yylval=NULL; return K_JTAG_MKII; }
|
||||
jtagmkii_dw { yylval=NULL; return K_JTAG_MKII_DW; }
|
||||
jtagmkii_isp { yylval=NULL; return K_JTAG_MKII_ISP; }
|
||||
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; }
|
||||
@@ -162,10 +176,14 @@ 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; }
|
||||
signature { yylval=NULL; return K_SIGNATURE; }
|
||||
size { yylval=NULL; return K_SIZE; }
|
||||
spmcr { yylval=NULL; return K_SPMCR; }
|
||||
stk500 { yylval=NULL; return K_STK500; }
|
||||
stk500hvsp { yylval=NULL; return K_STK500HVSP; }
|
||||
stk500pp { yylval=NULL; return K_STK500PP; }
|
||||
stk500v2 { yylval=NULL; return K_STK500V2; }
|
||||
stk500generic { yylval=NULL; return K_STK500GENERIC; }
|
||||
stk500_devcode { yylval=NULL; return K_STK500_DEVCODE; }
|
||||
type { yylval=NULL; return K_TYPE; }
|
||||
vcc { yylval=NULL; return K_VCC; }
|
||||
@@ -174,6 +192,7 @@ vfyled { yylval=NULL; return K_VFYLED; }
|
||||
timeout { yylval=NULL; return K_TIMEOUT; }
|
||||
stabdelay { yylval=NULL; return K_STABDELAY; }
|
||||
cmdexedelay { yylval=NULL; return K_CMDEXEDELAY; }
|
||||
hvspcmdexedelay { yylval=NULL; return K_HVSPCMDEXEDELAY; }
|
||||
synchloops { yylval=NULL; return K_SYNCHLOOPS; }
|
||||
bytedelay { yylval=NULL; return K_BYTEDELAY; }
|
||||
pollvalue { yylval=NULL; return K_POLLVALUE; }
|
||||
@@ -185,8 +204,27 @@ mode { yylval=NULL; return K_MODE; }
|
||||
delay { yylval=NULL; return K_DELAY; }
|
||||
blocksize { yylval=NULL; return K_BLOCKSIZE; }
|
||||
readsize { yylval=NULL; return K_READSIZE; }
|
||||
|
||||
|
||||
pp_controlstack { yylval=NULL; return K_PP_CONTROLSTACK; }
|
||||
hvsp_controlstack { yylval=NULL; return K_HVSP_CONTROLSTACK; }
|
||||
hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; }
|
||||
progmodedelay { yylval=NULL; return K_PROGMODEDELAY; }
|
||||
latchcycles { yylval=NULL; return K_LATCHCYCLES; }
|
||||
togglevtg { yylval=NULL; return K_TOGGLEVTG; }
|
||||
poweroffdelay { yylval=NULL; return K_POWEROFFDELAY; }
|
||||
resetdelayms { yylval=NULL; return K_RESETDELAYMS; }
|
||||
resetdelayus { yylval=NULL; return K_RESETDELAYUS; }
|
||||
hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; }
|
||||
resetdelay { yylval=NULL; return K_RESETDELAY; }
|
||||
synchcycles { yylval=NULL; return K_SYNCHCYCLES; }
|
||||
chiperasepulsewidth { yylval=NULL; return K_CHIPERASEPULSEWIDTH; }
|
||||
chiperasepolltimeout { yylval=NULL; return K_CHIPERASEPOLLTIMEOUT; }
|
||||
chiperasetime { yylval=NULL; return K_CHIPERASETIME; }
|
||||
programfusepulsewidth { yylval=NULL; return K_PROGRAMFUSEPULSEWIDTH; }
|
||||
programfusepolltimeout { yylval=NULL; return K_PROGRAMFUSEPOLLTIMEOUT; }
|
||||
programlockpulsewidth { yylval=NULL; return K_PROGRAMLOCKPULSEWIDTH; }
|
||||
programlockpolltimeout { yylval=NULL; return K_PROGRAMLOCKPOLLTIMEOUT; }
|
||||
flash_instr { yylval=NULL; return K_FLASH_INSTR; }
|
||||
eeprom_instr { yylval=NULL; return K_EEPROM_INSTR; }
|
||||
|
||||
dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
|
||||
io { yylval=new_token(K_IO); return K_IO; }
|
||||
@@ -203,6 +241,7 @@ write_lo { yylval=new_token(K_WRITE_LO); return K_WRITE_LO; }
|
||||
write_hi { yylval=new_token(K_WRITE_HI); return K_WRITE_HI; }
|
||||
loadpage_lo { yylval=new_token(K_LOADPAGE_LO); return K_LOADPAGE_LO; }
|
||||
loadpage_hi { yylval=new_token(K_LOADPAGE_HI); return K_LOADPAGE_HI; }
|
||||
load_ext_addr { yylval=new_token(K_LOAD_EXT_ADDR); return K_LOAD_EXT_ADDR; }
|
||||
writepage { yylval=new_token(K_WRITEPAGE); return K_WRITEPAGE; }
|
||||
chip_erase { yylval=new_token(K_CHIP_ERASE); return K_CHIP_ERASE; }
|
||||
pgm_enable { yylval=new_token(K_PGM_ENABLE); return K_PGM_ENABLE; }
|
||||
@@ -216,7 +255,7 @@ yes { yylval=new_token(K_YES); return K_YES; }
|
||||
"~" { yylval = NULL; pyytext(); return TKN_TILDE; }
|
||||
|
||||
"\n" { lineno++; }
|
||||
[ \r\t]+ /* ignore whitespace */
|
||||
[ \r\t]+ { /* ignore whitespace */ }
|
||||
|
||||
c: { fprintf(stderr, "error at %s:%d: possible old-style config file entry\n",
|
||||
infile, lineno);
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
#ifndef __linux_ppdev_h__
|
||||
#define __linux_ppdev_h__
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003, 2005 Theodore A. Roth
|
||||
*
|
||||
* 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 linux_ppdev_h
|
||||
#define linux_ppdev_h
|
||||
|
||||
#define OBSOLETE__IOW _IOW
|
||||
|
||||
@@ -9,29 +30,28 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define PPISDATA PPWDATA
|
||||
#define PPIGDATA PPRDATA
|
||||
|
||||
#define PPISCTRL PPWCONTROL
|
||||
#define PPIGCTRL PPRCONTROL
|
||||
|
||||
#define PPISSTATUS PPWSTATUS
|
||||
#define PPIGSTATUS PPRSTATUS
|
||||
|
||||
#define ppi_claim(pgm) \
|
||||
if (ioctl(pgm->fd, PPCLAIM)) { \
|
||||
#define ppi_claim(fd) \
|
||||
if (ioctl(fd, PPCLAIM)) { \
|
||||
fprintf(stderr, "%s: can't claim device \"%s\": %s\n\n", \
|
||||
progname, port, strerror(errno)); \
|
||||
close(pgm->fd); \
|
||||
close(fd); \
|
||||
exit(1); \
|
||||
}
|
||||
}
|
||||
|
||||
#define ppi_release(pgm) \
|
||||
if (ioctl(pgm->fd, PPRELEASE)) { \
|
||||
#define ppi_release(fd) \
|
||||
if (ioctl(fd, PPRELEASE)) { \
|
||||
fprintf(stderr, "%s: can't release device: %s\n\n", \
|
||||
progname, strerror(errno)); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define DO_PPI_READ(fd, reg, valp) \
|
||||
(void)ioctl(fd, \
|
||||
(reg) == PPIDATA? PPRDATA: ((reg) == PPICTRL? PPRCONTROL: PPRSTATUS), \
|
||||
valp)
|
||||
#define DO_PPI_WRITE(fd, reg, valp) \
|
||||
(void)ioctl(fd, \
|
||||
(reg) == PPIDATA? PPWDATA: ((reg) == PPICTRL? PPWCONTROL: PPWSTATUS), \
|
||||
valp)
|
||||
|
||||
#endif /* __linux_ppdev_h__ */
|
||||
#endif /* linux_ppdev_h */
|
||||
|
||||
@@ -1290,8 +1290,8 @@ int lprint ( FILE * f, LISTID lid )
|
||||
|
||||
l = (LIST *)lid;
|
||||
|
||||
fprintf ( f, "list id 0x%08x internal data structures:\n",
|
||||
(unsigned int)lid );
|
||||
fprintf ( f, "list id %p internal data structures:\n",
|
||||
lid );
|
||||
#if CHECK_MAGIC
|
||||
if ((l->magic1 != MAGIC) || (l->magic2 != MAGIC)) {
|
||||
fprintf ( f, " *** WARNING: LIST MAGIC IS CORRUPT ***\n" );
|
||||
|
||||
185
avrdude/main.c
185
avrdude/main.c
@@ -76,6 +76,7 @@ char * version = VERSION;
|
||||
|
||||
int verbose; /* verbose output */
|
||||
int quell_progress; /* un-verebose output */
|
||||
int ovsigck; /* 1=override sig check, 0=don't */
|
||||
char * progname;
|
||||
char progbuf[PATH_MAX]; /* temporary buffer of spaces the same
|
||||
length as progname; used for lining up
|
||||
@@ -101,13 +102,15 @@ void usage(void)
|
||||
"Options:\n"
|
||||
" -p <partno> Required. Specify AVR device.\n"
|
||||
" -b <baudrate> Override RS-232 baud rate.\n"
|
||||
" -B <bitclock> Specify JTAG bit clock period (us).\n"
|
||||
" -B <bitclock> Specify JTAG/STK500v2 bit clock period (us).\n"
|
||||
" -C <config-file> Specify location of configuration file.\n"
|
||||
" -c <programmer> Specify programmer type.\n"
|
||||
" -D Disable auto erase for flash memory\n"
|
||||
" -i <delay> ISP Clock Delay [in microseconds]\n"
|
||||
" -P <port> Specify connection port.\n"
|
||||
" -F Override invalid signature check.\n"
|
||||
" -e Perform a chip erase.\n"
|
||||
" -O Perform RC oscillator calibration (see AVR053). \n"
|
||||
" -U <memtype>:r|w|v:<filename>[:format]\n"
|
||||
" Memory operation specification.\n"
|
||||
" Multiple -U options are allowed, each request\n"
|
||||
@@ -129,39 +132,6 @@ void usage(void)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse the -E string
|
||||
*/
|
||||
int getexitspecs(char *s, int *set, int *clr)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
while ((cp = strtok(s, ","))) {
|
||||
if (strcmp(cp, "reset") == 0) {
|
||||
*clr |= par_getpinmask(pgm->pinno[PIN_AVR_RESET]);
|
||||
}
|
||||
else if (strcmp(cp, "noreset") == 0) {
|
||||
*set |= par_getpinmask(pgm->pinno[PIN_AVR_RESET]);
|
||||
}
|
||||
else if (strcmp(cp, "vcc") == 0) {
|
||||
if (pgm->pinno[PPI_AVR_VCC])
|
||||
*set |= pgm->pinno[PPI_AVR_VCC];
|
||||
}
|
||||
else if (strcmp(cp, "novcc") == 0) {
|
||||
if (pgm->pinno[PPI_AVR_VCC])
|
||||
*clr |= pgm->pinno[PPI_AVR_VCC];
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
s = 0; /* strtok() should be called with the actual string only once */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int read_config(char * file)
|
||||
{
|
||||
FILE * f;
|
||||
@@ -197,17 +167,6 @@ void programmer_display(char * p)
|
||||
|
||||
|
||||
|
||||
void verify_pin_assigned(int pin, char * desc)
|
||||
{
|
||||
if (pgm->pinno[pin] == 0) {
|
||||
fprintf(stderr, "%s: error: no pin has been assigned for %s\n",
|
||||
progname, desc);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PROGRAMMER * locate_programmer(LISTID programmers, char * configid)
|
||||
{
|
||||
LNODEID ln1, ln2;
|
||||
@@ -381,9 +340,20 @@ UPDATE * parse_op(char * s)
|
||||
buf[i++] = *p++;
|
||||
|
||||
if (*p != ':') {
|
||||
fprintf(stderr, "%s: invalid update specification\n", progname);
|
||||
free(upd);
|
||||
return NULL;
|
||||
upd->memtype = (char *)malloc(strlen("flash")+1);
|
||||
if (upd->memtype == NULL) {
|
||||
outofmem:
|
||||
fprintf(stderr, "%s: out of memory\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(upd->memtype, "flash");
|
||||
upd->op = DEVICE_WRITE;
|
||||
upd->filename = (char *)malloc(strlen(buf) + 1);
|
||||
if (upd->filename == NULL)
|
||||
goto outofmem;
|
||||
strcpy(upd->filename, buf);
|
||||
upd->format = FMT_AUTO;
|
||||
return upd;
|
||||
}
|
||||
|
||||
buf[i] = 0;
|
||||
@@ -457,6 +427,10 @@ UPDATE * parse_op(char * s)
|
||||
case 'i': upd->format = FMT_IHEX; break;
|
||||
case 'r': upd->format = FMT_RBIN; break;
|
||||
case 'm': upd->format = FMT_IMM; break;
|
||||
case 'b': upd->format = FMT_BIN; break;
|
||||
case 'd': upd->format = FMT_DEC; break;
|
||||
case 'h': upd->format = FMT_HEX; break;
|
||||
case 'o': upd->format = FMT_OCT; break;
|
||||
default:
|
||||
fprintf(stderr, "%s: invalid file format '%s' in update specifier\n",
|
||||
progname, p);
|
||||
@@ -589,7 +563,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite,
|
||||
*/
|
||||
if (quell_progress < 2) {
|
||||
fprintf(stderr, "%s: writing %s (%d bytes):\n",
|
||||
progname, upd->memtype, size);
|
||||
progname, mem->desc, size);
|
||||
}
|
||||
|
||||
if (!nowrite) {
|
||||
@@ -615,7 +589,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite,
|
||||
|
||||
if (quell_progress < 2) {
|
||||
fprintf(stderr, "%s: %d bytes of %s written\n", progname,
|
||||
vsize, upd->memtype);
|
||||
vsize, mem->desc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -647,7 +621,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite,
|
||||
fprintf(stderr, "%s: input file %s contains %d bytes\n",
|
||||
progname, upd->filename, size);
|
||||
fprintf(stderr, "%s: reading on-chip %s data:\n",
|
||||
progname, upd->memtype);
|
||||
progname, mem->desc);
|
||||
}
|
||||
|
||||
report_progress (0,1,"Reading");
|
||||
@@ -709,15 +683,13 @@ int main(int argc, char * argv [])
|
||||
|
||||
/* options / operating mode variables */
|
||||
int erase; /* 1=erase chip, 0=don't */
|
||||
int calibrate; /* 1=calibrate RC oscillator, 0=don't */
|
||||
int auto_erase; /* 0=never erase unless explicity told to do
|
||||
so, 1=erase if we are going to program flash */
|
||||
int ovsigck; /* 1=override sig check, 0=don't */
|
||||
char * port; /* device port (/dev/xxx) */
|
||||
int terminal; /* 1=enter terminal mode, 0=don't */
|
||||
int nowrite; /* don't actually write anything to the chip */
|
||||
int verify; /* perform a verify operation */
|
||||
int ppisetbits; /* bits to set in ppi data register at exit */
|
||||
int ppiclrbits; /* bits to clear in ppi data register at exit */
|
||||
char * exitspecs; /* exit specs string from command line */
|
||||
char * programmer; /* programmer id */
|
||||
char * partdesc; /* part id */
|
||||
@@ -728,6 +700,7 @@ int main(int argc, char * argv [])
|
||||
char * e; /* for strtol() error checking */
|
||||
int baudrate; /* override default programmer baud rate */
|
||||
double bitclock; /* Specify programmer bit clock (JTAG ICE) */
|
||||
int ispdelay; /* Specify the delay for ISP clock */
|
||||
int safemode; /* Enable safemode, 1=safemode on, 0=normal */
|
||||
int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */
|
||||
unsigned char safemode_lfuse = 0xff;
|
||||
@@ -742,11 +715,11 @@ int main(int argc, char * argv [])
|
||||
char * homedir;
|
||||
#endif
|
||||
|
||||
progname = rindex(argv[0],'/');
|
||||
progname = strrchr(argv[0],'/');
|
||||
|
||||
#if defined (WIN32NATIVE)
|
||||
/* take care of backslash as dir sep in W32 */
|
||||
if (!progname) progname = rindex(argv[0],'\\');
|
||||
if (!progname) progname = strrchr(argv[0],'\\');
|
||||
#endif /* WIN32NATIVE */
|
||||
|
||||
if (progname)
|
||||
@@ -768,6 +741,7 @@ int main(int argc, char * argv [])
|
||||
partdesc = NULL;
|
||||
port = default_parallel;
|
||||
erase = 0;
|
||||
calibrate = 0;
|
||||
auto_erase = 1;
|
||||
p = NULL;
|
||||
ovsigck = 0;
|
||||
@@ -775,8 +749,6 @@ int main(int argc, char * argv [])
|
||||
nowrite = 0;
|
||||
verify = 1; /* on by default */
|
||||
quell_progress = 0;
|
||||
ppisetbits = 0;
|
||||
ppiclrbits = 0;
|
||||
exitspecs = NULL;
|
||||
pgm = NULL;
|
||||
programmer = default_programmer;
|
||||
@@ -785,6 +757,7 @@ int main(int argc, char * argv [])
|
||||
set_cycles = -1;
|
||||
baudrate = 0;
|
||||
bitclock = 0.0;
|
||||
ispdelay = 0;
|
||||
safemode = 1; /* Safemode on by default */
|
||||
silentsafe = 0; /* Ask by default */
|
||||
|
||||
@@ -835,7 +808,7 @@ int main(int argc, char * argv [])
|
||||
/*
|
||||
* process command line arguments
|
||||
*/
|
||||
while ((ch = getopt(argc,argv,"?b:B:c:C:DeE:Fnp:P:qstU:uvVyY:")) != -1) {
|
||||
while ((ch = getopt(argc,argv,"?b:B:c:C:DeE:Fi:np:OP:qstU:uvVyY:")) != -1) {
|
||||
|
||||
switch (ch) {
|
||||
case 'b': /* override default programmer baud rate */
|
||||
@@ -856,6 +829,15 @@ int main(int argc, char * argv [])
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i': /* specify isp clock delay */
|
||||
ispdelay = strtol(optarg, &e,10);
|
||||
if ((e == optarg) || (*e != 0) || ispdelay == 0) {
|
||||
fprintf(stderr, "%s: invalid isp clock delay specified '%s'\n",
|
||||
progname, optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c': /* programmer id */
|
||||
programmer = optarg;
|
||||
break;
|
||||
@@ -885,6 +867,10 @@ int main(int argc, char * argv [])
|
||||
nowrite = 1;
|
||||
break;
|
||||
|
||||
case 'O': /* perform RC oscillator calibration */
|
||||
calibrate = 1;
|
||||
break;
|
||||
|
||||
case 'p' : /* specify AVR part */
|
||||
partdesc = optarg;
|
||||
break;
|
||||
@@ -982,9 +968,9 @@ int main(int argc, char * argv [])
|
||||
* they are running
|
||||
*/
|
||||
fprintf(stderr,
|
||||
"\n%s: Version %s\n"
|
||||
"\n%s: Version %s, compiled on %s at %s\n"
|
||||
"%sCopyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/\n\n",
|
||||
progname, version, progbuf);
|
||||
progname, version, __DATE__, __TIME__, progbuf);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
@@ -1106,20 +1092,18 @@ int main(int argc, char * argv [])
|
||||
|
||||
|
||||
if (exitspecs != NULL) {
|
||||
if (strcmp(pgm->type, "PPI") != 0) {
|
||||
if (pgm->parseexitspecs == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: WARNING: -E option is only valid with \"PPI\" "
|
||||
"programmer types\n",
|
||||
"%s: WARNING: -E option not supported by this programmer type\n",
|
||||
progname);
|
||||
exitspecs = NULL;
|
||||
}
|
||||
else if (getexitspecs(exitspecs, &ppisetbits, &ppiclrbits) < 0) {
|
||||
else if (pgm->parseexitspecs(pgm, exitspecs) < 0) {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set up seperate instances of the avr part, one for use in
|
||||
* programming, one for use in verifying. These are separate
|
||||
@@ -1128,13 +1112,6 @@ int main(int argc, char * argv [])
|
||||
p = avr_dup_part(p);
|
||||
v = avr_dup_part(p);
|
||||
|
||||
if (strcmp(pgm->type, "PPI") == 0) {
|
||||
verify_pin_assigned(PIN_AVR_RESET, "AVR RESET");
|
||||
verify_pin_assigned(PIN_AVR_SCK, "AVR SCK");
|
||||
verify_pin_assigned(PIN_AVR_MISO, "AVR MISO");
|
||||
verify_pin_assigned(PIN_AVR_MOSI, "AVR MOSI");
|
||||
}
|
||||
|
||||
/*
|
||||
* open the programmer
|
||||
*/
|
||||
@@ -1163,9 +1140,17 @@ int main(int argc, char * argv [])
|
||||
if (verbose) {
|
||||
fprintf(stderr, "%sSetting bit clk period: %.1f\n", progbuf, bitclock);
|
||||
}
|
||||
|
||||
pgm->bitclock = bitclock * 1e-6;
|
||||
}
|
||||
|
||||
if (ispdelay != 0) {
|
||||
if (verbose) {
|
||||
fprintf(stderr, "%sSetting isp clock delay: %3i\n", progbuf, ispdelay);
|
||||
}
|
||||
pgm->ispdelay = ispdelay;
|
||||
}
|
||||
|
||||
rc = pgm->open(pgm, port);
|
||||
if (rc < 0) {
|
||||
exitrc = 1;
|
||||
@@ -1173,6 +1158,21 @@ int main(int argc, char * argv [])
|
||||
goto main_exit;
|
||||
}
|
||||
|
||||
if (calibrate) {
|
||||
/*
|
||||
* perform an RC oscillator calibration
|
||||
* as outlined in appnote AVR053
|
||||
*/
|
||||
fprintf(stderr, "%s: performing RC oscillator calibration\n", progname);
|
||||
exitrc = pgm->perform_osccal(pgm);
|
||||
if (exitrc == 0 && quell_progress < 2) {
|
||||
fprintf(stderr,
|
||||
"%s: calibration value is now stored in EEPROM at address 0\n",
|
||||
progname);
|
||||
}
|
||||
goto main_exit;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
avr_display(stderr, p, progbuf, verbose);
|
||||
fprintf(stderr, "\n");
|
||||
@@ -1185,14 +1185,6 @@ int main(int argc, char * argv [])
|
||||
|
||||
exitrc = 0;
|
||||
|
||||
/*
|
||||
* handle exit specs. FIXME: this should be moved to "par.c"
|
||||
*/
|
||||
if (strcmp(pgm->type, "PPI") == 0) {
|
||||
pgm->ppidata &= ~ppiclrbits;
|
||||
pgm->ppidata |= ppisetbits;
|
||||
}
|
||||
|
||||
/*
|
||||
* enable the programmer
|
||||
*/
|
||||
@@ -1234,8 +1226,8 @@ int main(int argc, char * argv [])
|
||||
/*
|
||||
* Let's read the signature bytes to make sure there is at least a
|
||||
* chip on the other end that is responding correctly. A check
|
||||
* against 0xffffffff should ensure that the signature bytes are
|
||||
* valid.
|
||||
* against 0xffffff / 0x000000 should ensure that the signature bytes
|
||||
* are valid.
|
||||
*/
|
||||
rc = avr_signature(pgm, p);
|
||||
if (rc != 0) {
|
||||
@@ -1253,24 +1245,26 @@ int main(int argc, char * argv [])
|
||||
}
|
||||
|
||||
if (sig != NULL) {
|
||||
int ff;
|
||||
int ff, zz;
|
||||
|
||||
if (quell_progress < 2) {
|
||||
fprintf(stderr, "%s: Device signature = 0x", progname);
|
||||
}
|
||||
ff = 1;
|
||||
ff = zz = 1;
|
||||
for (i=0; i<sig->size; i++) {
|
||||
if (quell_progress < 2) {
|
||||
fprintf(stderr, "%02x", sig->buf[i]);
|
||||
}
|
||||
if (sig->buf[i] != 0xff)
|
||||
ff = 0;
|
||||
if (sig->buf[i] != 0x00)
|
||||
zz = 0;
|
||||
}
|
||||
if (quell_progress < 2) {
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
if (ff) {
|
||||
if (ff || zz) {
|
||||
fprintf(stderr,
|
||||
"%s: Yikes! Invalid device signature.\n", progname);
|
||||
if (!ovsigck) {
|
||||
@@ -1282,6 +1276,23 @@ int main(int argc, char * argv [])
|
||||
goto main_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (sig->size != 3 ||
|
||||
sig->buf[0] != p->signature[0] ||
|
||||
sig->buf[1] != p->signature[1] ||
|
||||
sig->buf[2] != p->signature[2]) {
|
||||
fprintf(stderr,
|
||||
"%s: Expected signature for %s is %02X %02X %02X\n",
|
||||
progname, p->desc,
|
||||
p->signature[0], p->signature[1], p->signature[2]);
|
||||
if (!ovsigck) {
|
||||
fprintf(stderr, "%sDouble check chip, "
|
||||
"or use -F to override this check.\n",
|
||||
progbuf);
|
||||
exitrc = 1;
|
||||
goto main_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (safemode == 1) {
|
||||
@@ -1420,7 +1431,7 @@ int main(int argc, char * argv [])
|
||||
|
||||
/* Try reading back fuses, make sure they are reliable to read back */
|
||||
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
||||
&safemodeafter_efuse, &safemode_fuse, pgm, p, verbose) != 0) {
|
||||
&safemodeafter_efuse, &safemodeafter_fuse, pgm, p, verbose) != 0) {
|
||||
/* Uh-oh.. try once more to read back fuses */
|
||||
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
||||
&safemodeafter_efuse, &safemodeafter_fuse, pgm, p, verbose) != 0) {
|
||||
|
||||
49
avrdude/my_ddk_hidsdi.h
Normal file
49
avrdude/my_ddk_hidsdi.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2006 Christian Starkjohann
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
/*
|
||||
The following is a replacement for hidsdi.h from the Windows DDK. It defines some
|
||||
of the types and function prototypes of this header for our project. If you
|
||||
have the Windows DDK version of this file or a version shipped with MinGW, use
|
||||
that instead.
|
||||
*/
|
||||
#ifndef MY_DDK_HIDSDI_H
|
||||
#define MY_DDK_HIDSDI_H
|
||||
#include <pshpack4.h>
|
||||
#include <ddk/hidusage.h>
|
||||
#include <ddk/hidpi.h>
|
||||
typedef struct{
|
||||
ULONG Size;
|
||||
USHORT VendorID;
|
||||
USHORT ProductID;
|
||||
USHORT VersionNumber;
|
||||
}HIDD_ATTRIBUTES;
|
||||
void __stdcall HidD_GetHidGuid(OUT LPGUID hidGuid);
|
||||
BOOLEAN __stdcall HidD_GetAttributes(IN HANDLE device, OUT HIDD_ATTRIBUTES *attributes);
|
||||
BOOLEAN __stdcall HidD_GetManufacturerString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
|
||||
BOOLEAN __stdcall HidD_GetProductString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
|
||||
BOOLEAN __stdcall HidD_GetSerialNumberString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
|
||||
BOOLEAN __stdcall HidD_GetFeature(IN HANDLE device, OUT void *reportBuffer, IN ULONG bufferLen);
|
||||
BOOLEAN __stdcall HidD_SetFeature(IN HANDLE device, IN void *reportBuffer, IN ULONG bufferLen);
|
||||
BOOLEAN __stdcall HidD_GetNumInputBuffers(IN HANDLE device, OUT ULONG *numBuffers);
|
||||
BOOLEAN __stdcall HidD_SetNumInputBuffers(IN HANDLE device, OUT ULONG numBuffers);
|
||||
#include <poppack.h>
|
||||
#endif /* MY_DDK_HIDSDI_H */
|
||||
267
avrdude/par.c
267
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-2006 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,9 +29,11 @@
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <dev/ppbus/ppi.h>
|
||||
# include "freebsd_ppi.h"
|
||||
#elif defined(__linux__)
|
||||
#include "linux_ppdev.h"
|
||||
# include "linux_ppdev.h"
|
||||
#elif defined(__sun__) && defined(__svr4__) /* Solaris */
|
||||
# include "solaris_ecpp.h"
|
||||
#endif
|
||||
|
||||
#include "avr.h"
|
||||
@@ -40,7 +42,11 @@
|
||||
#include "ppi.h"
|
||||
#include "bitbang.h"
|
||||
|
||||
#define SLOW_TOGGLE 0
|
||||
extern char * progname;
|
||||
extern int do_cycles;
|
||||
extern int verbose;
|
||||
|
||||
#if HAVE_PARPORT
|
||||
|
||||
struct ppipins_t {
|
||||
int pin;
|
||||
@@ -49,7 +55,7 @@ struct ppipins_t {
|
||||
int inverted;
|
||||
};
|
||||
|
||||
struct ppipins_t ppipins[] = {
|
||||
static struct ppipins_t ppipins[] = {
|
||||
{ 1, PPICTRL, 0x01, 1 },
|
||||
{ 2, PPIDATA, 0x01, 0 },
|
||||
{ 3, PPIDATA, 0x02, 0 },
|
||||
@@ -71,14 +77,11 @@ struct ppipins_t ppipins[] = {
|
||||
|
||||
#define NPINS (sizeof(ppipins)/sizeof(struct ppipins_t))
|
||||
|
||||
|
||||
extern char * progname;
|
||||
extern int do_cycles;
|
||||
extern int verbose;
|
||||
|
||||
int par_setpin(int fd, int pin, int value)
|
||||
static int par_setpin(PROGRAMMER * pgm, int pin, int value)
|
||||
{
|
||||
int inverted;
|
||||
|
||||
inverted = pin & PIN_INVERSE;
|
||||
pin &= PIN_MASK;
|
||||
|
||||
if (pin < 1 || pin > 17)
|
||||
@@ -87,25 +90,38 @@ int par_setpin(int fd, int pin, int value)
|
||||
pin--;
|
||||
|
||||
if (ppipins[pin].inverted)
|
||||
inverted = !inverted;
|
||||
|
||||
if (inverted)
|
||||
value = !value;
|
||||
|
||||
if (value)
|
||||
ppi_set(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
ppi_set(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
else
|
||||
ppi_clr(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
ppi_clr(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
if (pgm->ispdelay > 1)
|
||||
bitbang_delay(pgm->ispdelay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void par_setmany(PROGRAMMER * pgm, unsigned int pinset, int value)
|
||||
{
|
||||
int pin;
|
||||
|
||||
int par_getpin(int fd, int pin)
|
||||
for (pin = 1; pin <= 17; pin++) {
|
||||
if (pinset & (1 << pin))
|
||||
par_setpin(pgm, pin, value);
|
||||
}
|
||||
}
|
||||
|
||||
static int par_getpin(PROGRAMMER * pgm, int pin)
|
||||
{
|
||||
int value;
|
||||
int inverted;
|
||||
|
||||
inverted = pin & PIN_INVERSE;
|
||||
pin &= PIN_MASK;
|
||||
|
||||
if (pin < 1 || pin > 17)
|
||||
@@ -113,79 +129,82 @@ int par_getpin(int fd, int pin)
|
||||
|
||||
pin--;
|
||||
|
||||
value = ppi_get(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
value = ppi_get(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
|
||||
if (value)
|
||||
value = 1;
|
||||
|
||||
if (ppipins[pin].inverted)
|
||||
inverted = !inverted;
|
||||
|
||||
if (inverted)
|
||||
value = !value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
int par_highpulsepin(int fd, int pin)
|
||||
static int par_highpulsepin(PROGRAMMER * pgm, int pin)
|
||||
{
|
||||
int inverted;
|
||||
|
||||
inverted = pin & PIN_INVERSE;
|
||||
pin &= PIN_MASK;
|
||||
|
||||
if (pin < 1 || pin > 17)
|
||||
return -1;
|
||||
|
||||
pin--;
|
||||
|
||||
ppi_set(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
ppi_clr(fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
if (ppipins[pin].inverted)
|
||||
inverted = !inverted;
|
||||
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
if (inverted) {
|
||||
ppi_clr(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
if (pgm->ispdelay > 1)
|
||||
bitbang_delay(pgm->ispdelay);
|
||||
|
||||
ppi_set(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
if (pgm->ispdelay > 1)
|
||||
bitbang_delay(pgm->ispdelay);
|
||||
} else {
|
||||
ppi_set(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
if (pgm->ispdelay > 1)
|
||||
bitbang_delay(pgm->ispdelay);
|
||||
|
||||
ppi_clr(&pgm->fd, ppipins[pin].reg, ppipins[pin].bit);
|
||||
if (pgm->ispdelay > 1)
|
||||
bitbang_delay(pgm->ispdelay);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int par_getpinmask(int pin)
|
||||
static char * pins_to_str(unsigned int pmask)
|
||||
{
|
||||
pin &= PIN_MASK;
|
||||
|
||||
if (pin < 1 || pin > 17)
|
||||
return -1;
|
||||
|
||||
return ppipins[pin-1].bit;
|
||||
}
|
||||
|
||||
|
||||
char vccpins_buf[64];
|
||||
char * vccpins_str(unsigned int pmask)
|
||||
{
|
||||
unsigned int mask;
|
||||
static char buf[64];
|
||||
int pin;
|
||||
char b2[8];
|
||||
char * b;
|
||||
|
||||
b = vccpins_buf;
|
||||
|
||||
b[0] = 0;
|
||||
for (pin = 2, mask = 1; mask < 0x80; mask = mask << 1, pin++) {
|
||||
if (pmask & mask) {
|
||||
buf[0] = 0;
|
||||
for (pin = 1; pin <= 17; pin++) {
|
||||
if (pmask & (1 << pin)) {
|
||||
sprintf(b2, "%d", pin);
|
||||
if (b[0] != 0)
|
||||
strcat(b, ",");
|
||||
strcat(b, b2);
|
||||
if (buf[0] != 0)
|
||||
strcat(buf, ",");
|
||||
strcat(buf, b2);
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 1); /* power up */
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
@@ -193,17 +212,17 @@ 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 */
|
||||
par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 0); /* power down */
|
||||
}
|
||||
|
||||
void par_disable(PROGRAMMER * pgm)
|
||||
static void par_disable(PROGRAMMER * pgm)
|
||||
{
|
||||
ppi_set(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_BUFF]);
|
||||
par_setmany(pgm, pgm->pinno[PPI_AVR_BUFF], 1); /* turn off */
|
||||
}
|
||||
|
||||
void par_enable(PROGRAMMER * pgm)
|
||||
static void par_enable(PROGRAMMER * pgm)
|
||||
{
|
||||
/*
|
||||
* Prepare to start talking to the connected device - pull reset low
|
||||
@@ -216,39 +235,39 @@ void par_enable(PROGRAMMER * pgm)
|
||||
* and not via the buffer chip.
|
||||
*/
|
||||
|
||||
par_setpin(pgm->fd, pgm->pinno[PIN_AVR_RESET], 0);
|
||||
par_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0);
|
||||
usleep(1);
|
||||
|
||||
/*
|
||||
* enable the 74367 buffer, if connected; this signal is active low
|
||||
*/
|
||||
ppi_clr(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_BUFF]);
|
||||
par_setmany(pgm, pgm->pinno[PPI_AVR_BUFF], 0);
|
||||
}
|
||||
|
||||
int par_open(PROGRAMMER * pgm, char * port)
|
||||
static int par_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
int rc;
|
||||
|
||||
pgm->fd = ppi_open(port);
|
||||
if (pgm->fd < 0) {
|
||||
bitbang_check_prerequisites(pgm);
|
||||
|
||||
ppi_open(port, &pgm->fd);
|
||||
if (pgm->fd.ifd < 0) {
|
||||
fprintf(stderr, "%s: failed to open parallel port \"%s\"\n\n",
|
||||
progname, port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ppi_claim(pgm);
|
||||
|
||||
/*
|
||||
* save pin values, so they can be restored when device is closed
|
||||
*/
|
||||
rc = ppi_getall(pgm->fd, PPIDATA);
|
||||
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);
|
||||
rc = ppi_getall(&pgm->fd, PPICTRL);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: error reading status of ppi ctrl port\n", progname);
|
||||
return -1;
|
||||
@@ -259,46 +278,76 @@ int par_open(PROGRAMMER * pgm, char * port)
|
||||
}
|
||||
|
||||
|
||||
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_setall(&pgm->fd, PPIDATA, pgm->ppidata);
|
||||
ppi_setall(&pgm->fd, PPICTRL, pgm->ppictrl);
|
||||
|
||||
ppi_release(pgm);
|
||||
par_setpin(pgm, pgm->pinno[PPI_AVR_BUFF], 1);
|
||||
|
||||
ppi_close(pgm->fd);
|
||||
pgm->fd = -1;
|
||||
/*
|
||||
* Handle exit specs.
|
||||
*/
|
||||
switch (pgm->exit_reset) {
|
||||
case EXIT_RESET_ENABLED:
|
||||
par_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0);
|
||||
break;
|
||||
|
||||
case EXIT_RESET_DISABLED:
|
||||
par_setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1);
|
||||
break;
|
||||
|
||||
case EXIT_RESET_UNSPEC:
|
||||
/* Leave it alone. */
|
||||
break;
|
||||
}
|
||||
switch (pgm->exit_vcc) {
|
||||
case EXIT_VCC_ENABLED:
|
||||
par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 1);
|
||||
break;
|
||||
|
||||
case EXIT_VCC_DISABLED:
|
||||
par_setmany(pgm, pgm->pinno[PPI_AVR_VCC], 0);
|
||||
break;
|
||||
|
||||
case EXIT_VCC_UNSPEC:
|
||||
/* Leave it alone. */
|
||||
break;
|
||||
}
|
||||
|
||||
ppi_close(&pgm->fd);
|
||||
pgm->fd.ifd = -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",
|
||||
vccpins_str(pgm->pinno[PPI_AVR_VCC]));
|
||||
snprintf(vccpins, sizeof(vccpins), "%s",
|
||||
pins_to_str(pgm->pinno[PPI_AVR_VCC]));
|
||||
}
|
||||
else {
|
||||
strcpy(vccpins, " (not used)");
|
||||
}
|
||||
|
||||
if (pgm->pinno[PPI_AVR_BUFF]) {
|
||||
snprintf(buffpins, sizeof(buffpins), " = pins %s",
|
||||
vccpins_str(pgm->pinno[PPI_AVR_BUFF]));
|
||||
snprintf(buffpins, sizeof(buffpins), "%s",
|
||||
pins_to_str(pgm->pinno[PPI_AVR_BUFF]));
|
||||
}
|
||||
else {
|
||||
strcpy(buffpins, " (not used)");
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"%s VCC = 0x%02x%s\n"
|
||||
"%s BUFF = 0x%02x%s\n"
|
||||
"%s VCC = %s\n"
|
||||
"%s BUFF = %s\n"
|
||||
"%s RESET = %d\n"
|
||||
"%s SCK = %d\n"
|
||||
"%s MOSI = %d\n"
|
||||
@@ -308,8 +357,8 @@ void par_display(PROGRAMMER * pgm, char * p)
|
||||
"%s PGM LED = %d\n"
|
||||
"%s VFY LED = %d\n",
|
||||
|
||||
p, pgm->pinno[PPI_AVR_VCC], vccpins,
|
||||
p, pgm->pinno[PPI_AVR_BUFF], buffpins,
|
||||
p, vccpins,
|
||||
p, buffpins,
|
||||
p, pgm->pinno[PIN_AVR_RESET],
|
||||
p, pgm->pinno[PIN_AVR_SCK],
|
||||
p, pgm->pinno[PIN_AVR_MOSI],
|
||||
@@ -321,10 +370,42 @@ void par_display(PROGRAMMER * pgm, char * p)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* parse the -E string
|
||||
*/
|
||||
static int par_parseexitspecs(PROGRAMMER * pgm, char *s)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
while ((cp = strtok(s, ","))) {
|
||||
if (strcmp(cp, "reset") == 0) {
|
||||
pgm->exit_reset = EXIT_RESET_ENABLED;
|
||||
}
|
||||
else if (strcmp(cp, "noreset") == 0) {
|
||||
pgm->exit_reset = EXIT_RESET_DISABLED;
|
||||
}
|
||||
else if (strcmp(cp, "vcc") == 0) {
|
||||
pgm->exit_vcc = EXIT_VCC_ENABLED;
|
||||
}
|
||||
else if (strcmp(cp, "novcc") == 0) {
|
||||
pgm->exit_vcc = EXIT_VCC_DISABLED;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
s = 0; /* strtok() should be called with the actual string only once */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void par_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
strcpy(pgm->type, "PPI");
|
||||
|
||||
pgm->exit_vcc = EXIT_VCC_UNSPEC;
|
||||
pgm->exit_reset = EXIT_RESET_UNSPEC;
|
||||
|
||||
pgm->rdy_led = bitbang_rdy_led;
|
||||
pgm->err_led = bitbang_err_led;
|
||||
pgm->pgm_led = bitbang_pgm_led;
|
||||
@@ -340,7 +421,21 @@ void par_initpgm(PROGRAMMER * pgm)
|
||||
pgm->cmd = bitbang_cmd;
|
||||
pgm->open = par_open;
|
||||
pgm->close = par_close;
|
||||
|
||||
/* this is a parallel port bitbang device */
|
||||
pgm->flag = 0;
|
||||
pgm->setpin = par_setpin;
|
||||
pgm->getpin = par_getpin;
|
||||
pgm->highpulsepin = par_highpulsepin;
|
||||
pgm->parseexitspecs = par_parseexitspecs;
|
||||
pgm->read_byte = avr_read_byte_default;
|
||||
pgm->write_byte = avr_write_byte_default;
|
||||
}
|
||||
|
||||
#else /* !HAVE_PARPORT */
|
||||
|
||||
void par_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: parallel port access not available in this configuration\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
#endif /* HAVE_PARPORT */
|
||||
|
||||
@@ -24,11 +24,6 @@
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -30,9 +30,11 @@
|
||||
extern char * progname;
|
||||
|
||||
static int pgm_default_2 (struct programmer_t *, AVRPART *);
|
||||
static int pgm_default_3 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char * value);
|
||||
static void pgm_default_4 (struct programmer_t *);
|
||||
static int pgm_default_5 (struct programmer_t *, unsigned char cmd[4],
|
||||
unsigned char res[4]);
|
||||
static int pgm_default_5 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char data);
|
||||
static void pgm_default_6 (struct programmer_t *, char *);
|
||||
|
||||
|
||||
@@ -96,9 +98,10 @@ PROGRAMMER * pgm_new(void)
|
||||
pgm->powerdown = pgm_default_powerup_powerdown;
|
||||
pgm->program_enable = pgm_default_2;
|
||||
pgm->chip_erase = pgm_default_2;
|
||||
pgm->cmd = pgm_default_5;
|
||||
pgm->open = pgm_default_open;
|
||||
pgm->close = pgm_default_4;
|
||||
pgm->read_byte = pgm_default_3;
|
||||
pgm->write_byte = pgm_default_5;
|
||||
|
||||
/*
|
||||
* predefined functions - these functions have a valid default
|
||||
@@ -114,15 +117,15 @@ PROGRAMMER * pgm_new(void)
|
||||
* optional functions - these are checked to make sure they are
|
||||
* assigned before they are called
|
||||
*/
|
||||
pgm->cmd = NULL;
|
||||
pgm->paged_write = NULL;
|
||||
pgm->paged_load = NULL;
|
||||
pgm->write_setup = NULL;
|
||||
pgm->write_byte = NULL;
|
||||
pgm->read_byte = NULL;
|
||||
pgm->read_sig_bytes = NULL;
|
||||
pgm->set_vtarget = NULL;
|
||||
pgm->set_varef = NULL;
|
||||
pgm->set_fosc = NULL;
|
||||
pgm->perform_osccal = NULL;
|
||||
|
||||
return pgm;
|
||||
}
|
||||
@@ -140,13 +143,20 @@ static int pgm_default_2 (struct programmer_t * pgm, AVRPART * p)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int pgm_default_3 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char * value)
|
||||
{
|
||||
pgm_default();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void pgm_default_4 (struct programmer_t * pgm)
|
||||
{
|
||||
pgm_default();
|
||||
}
|
||||
|
||||
static int pgm_default_5 (struct programmer_t * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
static int pgm_default_5 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char data)
|
||||
{
|
||||
pgm_default();
|
||||
return -1;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "avrpart.h"
|
||||
#include "lists.h"
|
||||
#include "pindefs.h"
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
#define ON 1
|
||||
#define OFF 0
|
||||
@@ -38,17 +38,32 @@
|
||||
|
||||
extern LISTID programmers;
|
||||
|
||||
typedef enum {
|
||||
EXIT_VCC_UNSPEC,
|
||||
EXIT_VCC_ENABLED,
|
||||
EXIT_VCC_DISABLED
|
||||
} exit_vcc_t;
|
||||
|
||||
typedef enum {
|
||||
EXIT_RESET_UNSPEC,
|
||||
EXIT_RESET_ENABLED,
|
||||
EXIT_RESET_DISABLED
|
||||
} exit_reset_t;
|
||||
|
||||
typedef struct programmer_t {
|
||||
LISTID id;
|
||||
char desc[PGM_DESCLEN];
|
||||
char type[PGM_TYPELEN];
|
||||
char port[PGM_PORTLEN];
|
||||
unsigned int pinno[N_PINS];
|
||||
exit_vcc_t exit_vcc;
|
||||
exit_reset_t exit_reset;
|
||||
int ppidata;
|
||||
int ppictrl;
|
||||
int baudrate;
|
||||
double bitclock; /* JTAG ICE clock period in microseconds */
|
||||
int fd;
|
||||
int ispdelay; /* ISP clock delay */
|
||||
union filedescriptor fd;
|
||||
int page_size; /* page size if the programmer supports paged write/load */
|
||||
int (*rdy_led) (struct programmer_t * pgm, int value);
|
||||
int (*err_led) (struct programmer_t * pgm, int value);
|
||||
@@ -81,6 +96,11 @@ typedef struct programmer_t {
|
||||
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);
|
||||
int (*setpin) (struct programmer_t * pgm, int pin, int value);
|
||||
int (*getpin) (struct programmer_t * pgm, int pin);
|
||||
int (*highpulsepin) (struct programmer_t * pgm, int pin);
|
||||
int (*parseexitspecs) (struct programmer_t * pgm, char *s);
|
||||
int (*perform_osccal) (struct programmer_t * pgm);
|
||||
char config_file[PATH_MAX]; /* config file where defined */
|
||||
int lineno; /* config file line number */
|
||||
char flag; /* for private use of the programmer */
|
||||
@@ -91,6 +111,7 @@ PROGRAMMER * pgm_new(void);
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
|
||||
#include "ac_cfg.h"
|
||||
#include <windows.h>
|
||||
|
||||
/* usleep replacements */
|
||||
@@ -102,19 +123,12 @@ PROGRAMMER * pgm_new(void);
|
||||
*/
|
||||
void usleep(unsigned long us);
|
||||
|
||||
void gettimeofday(struct timeval*, void*z);
|
||||
|
||||
#define rindex strrchr
|
||||
#if !defined(HAVE_GETTIMEOFDAY)
|
||||
struct timezone;
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
#endif /* HAVE_GETTIMEOFDAY */
|
||||
|
||||
#endif /* __win32native_h */
|
||||
|
||||
|
||||
#if !defined(ppi_claim)
|
||||
# define ppi_claim(pgm)
|
||||
#endif
|
||||
|
||||
#if !defined(ppi_release)
|
||||
# define ppi_release(pgm)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
148
avrdude/ppi.c
148
avrdude/ppi.c
@@ -19,10 +19,13 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__linux__)
|
||||
|
||||
#if !defined(WIN32NATIVE)
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#if HAVE_PARPORT
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -31,9 +34,11 @@
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <dev/ppbus/ppi.h>
|
||||
# include "freebsd_ppi.h"
|
||||
#elif defined(__linux__)
|
||||
#include "linux_ppdev.h"
|
||||
# include "linux_ppdev.h"
|
||||
#elif defined(__sun__) && defined(__svr4__) /* Solaris */
|
||||
# include "solaris_ecpp.h"
|
||||
#endif
|
||||
|
||||
#include "avr.h"
|
||||
@@ -49,26 +54,19 @@ enum {
|
||||
PPI_SHADOWREAD
|
||||
};
|
||||
|
||||
int ppi_shadow_access(int fd, int reg, unsigned char *v, unsigned char action)
|
||||
int ppi_shadow_access(union filedescriptor *fdp, int reg, unsigned char *v, unsigned char action)
|
||||
{
|
||||
static unsigned char shadow[3];
|
||||
int shadow_num;
|
||||
unsigned long set, get;
|
||||
|
||||
switch (reg) {
|
||||
case PPIDATA:
|
||||
set = PPISDATA;
|
||||
get = PPIGDATA;
|
||||
shadow_num = 0;
|
||||
break;
|
||||
case PPICTRL:
|
||||
set = PPISCTRL;
|
||||
get = PPIGCTRL;
|
||||
shadow_num = 1;
|
||||
break;
|
||||
case PPISTATUS:
|
||||
set = PPISSTATUS;
|
||||
get = PPIGSTATUS;
|
||||
shadow_num = 2;
|
||||
break;
|
||||
default:
|
||||
@@ -83,12 +81,12 @@ int ppi_shadow_access(int fd, int reg, unsigned char *v, unsigned char action)
|
||||
*v = shadow[shadow_num];
|
||||
break;
|
||||
case PPI_READ:
|
||||
ioctl(fd, get, v);
|
||||
DO_PPI_READ(fdp->ifd, reg, v);
|
||||
shadow[shadow_num]=*v;
|
||||
break;
|
||||
case PPI_WRITE:
|
||||
shadow[shadow_num]=*v;
|
||||
ioctl(fd, set, v);
|
||||
DO_PPI_WRITE(fdp->ifd, reg, v);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@@ -97,14 +95,14 @@ int ppi_shadow_access(int fd, int reg, unsigned char *v, unsigned char action)
|
||||
/*
|
||||
* set the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_set(int fd, int reg, int bit)
|
||||
int ppi_set(union filedescriptor *fdp, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD);
|
||||
rc = ppi_shadow_access(fdp, reg, &v, PPI_SHADOWREAD);
|
||||
v |= bit;
|
||||
rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE);
|
||||
rc |= ppi_shadow_access(fdp, reg, &v, PPI_WRITE);
|
||||
|
||||
if (rc)
|
||||
return -1;
|
||||
@@ -116,14 +114,14 @@ int ppi_set(int fd, int reg, int bit)
|
||||
/*
|
||||
* clear the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_clr(int fd, int reg, int bit)
|
||||
int ppi_clr(union filedescriptor *fdp, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD);
|
||||
rc = ppi_shadow_access(fdp, reg, &v, PPI_SHADOWREAD);
|
||||
v &= ~bit;
|
||||
rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE);
|
||||
rc |= ppi_shadow_access(fdp, reg, &v, PPI_WRITE);
|
||||
|
||||
if (rc)
|
||||
return -1;
|
||||
@@ -135,12 +133,12 @@ int ppi_clr(int fd, int reg, int bit)
|
||||
/*
|
||||
* get the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_get(int fd, int reg, int bit)
|
||||
int ppi_get(union filedescriptor *fdp, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_READ);
|
||||
rc = ppi_shadow_access(fdp, reg, &v, PPI_READ);
|
||||
v &= bit;
|
||||
|
||||
if (rc)
|
||||
@@ -152,14 +150,14 @@ int ppi_get(int fd, int reg, int bit)
|
||||
/*
|
||||
* toggle the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_toggle(int fd, int reg, int bit)
|
||||
int ppi_toggle(union filedescriptor *fdp, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_SHADOWREAD);
|
||||
rc = ppi_shadow_access(fdp, reg, &v, PPI_SHADOWREAD);
|
||||
v ^= bit;
|
||||
rc |= ppi_shadow_access(fd, reg, &v, PPI_WRITE);
|
||||
rc |= ppi_shadow_access(fdp, reg, &v, PPI_WRITE);
|
||||
|
||||
if (rc)
|
||||
return -1;
|
||||
@@ -171,12 +169,12 @@ int ppi_toggle(int fd, int reg, int bit)
|
||||
/*
|
||||
* get all bits of the specified register.
|
||||
*/
|
||||
int ppi_getall(int fd, int reg)
|
||||
int ppi_getall(union filedescriptor *fdp, int reg)
|
||||
{
|
||||
unsigned char v;
|
||||
int rc;
|
||||
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_READ);
|
||||
rc = ppi_shadow_access(fdp, reg, &v, PPI_READ);
|
||||
|
||||
if (rc)
|
||||
return -1;
|
||||
@@ -187,13 +185,13 @@ int ppi_getall(int fd, int reg)
|
||||
/*
|
||||
* set all bits of the specified register to val.
|
||||
*/
|
||||
int ppi_setall(int fd, int reg, int val)
|
||||
int ppi_setall(union filedescriptor *fdp, int reg, int val)
|
||||
{
|
||||
unsigned char v;
|
||||
int rc;
|
||||
|
||||
v = val;
|
||||
rc = ppi_shadow_access(fd, reg, &v, PPI_WRITE);
|
||||
rc = ppi_shadow_access(fdp, reg, &v, PPI_WRITE);
|
||||
|
||||
if (rc)
|
||||
return -1;
|
||||
@@ -202,7 +200,7 @@ int ppi_setall(int fd, int reg, int val)
|
||||
}
|
||||
|
||||
|
||||
int ppi_open(char * port)
|
||||
void ppi_open(char * port, union filedescriptor *fdp)
|
||||
{
|
||||
int fd;
|
||||
unsigned char v;
|
||||
@@ -211,96 +209,30 @@ int ppi_open(char * port)
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "%s: can't open device \"%s\": %s\n",
|
||||
progname, port, strerror(errno));
|
||||
return -1;
|
||||
fdp->ifd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
ppi_claim (fd);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
ppi_shadow_access (fdp, PPIDATA, &v, PPI_READ);
|
||||
ppi_shadow_access (fdp, PPICTRL, &v, PPI_READ);
|
||||
ppi_shadow_access (fdp, PPISTATUS, &v, PPI_READ);
|
||||
|
||||
return fd;
|
||||
fdp->ifd = fd;
|
||||
}
|
||||
|
||||
|
||||
void ppi_close(int fd)
|
||||
void ppi_close(union filedescriptor *fdp)
|
||||
{
|
||||
close(fd);
|
||||
ppi_release (fdp->ifd);
|
||||
close(fdp->ifd);
|
||||
}
|
||||
|
||||
#endif /* HAVE_PARPORT */
|
||||
|
||||
#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
|
||||
|
||||
#endif /* !WIN32NATIVE */
|
||||
|
||||
@@ -33,21 +33,21 @@ enum {
|
||||
|
||||
|
||||
|
||||
int ppi_get (int fd, int reg, int bit);
|
||||
int ppi_get (union filedescriptor *fdp, int reg, int bit);
|
||||
|
||||
int ppi_set (int fd, int reg, int bit);
|
||||
int ppi_set (union filedescriptor *fdp, int reg, int bit);
|
||||
|
||||
int ppi_clr (int fd, int reg, int bit);
|
||||
int ppi_clr (union filedescriptor *fdp, int reg, int bit);
|
||||
|
||||
int ppi_getall (int fd, int reg);
|
||||
int ppi_getall (union filedescriptor *fdp, int reg);
|
||||
|
||||
int ppi_setall (int fd, int reg, int val);
|
||||
int ppi_setall (union filedescriptor *fdp, int reg, int val);
|
||||
|
||||
int ppi_toggle (int fd, int reg, int bit);
|
||||
int ppi_toggle (union filedescriptor *fdp, int reg, int bit);
|
||||
|
||||
int ppi_open (char * port);
|
||||
void ppi_open (char * port, union filedescriptor *fdp);
|
||||
|
||||
void ppi_close (int fd);
|
||||
void ppi_close (union filedescriptor *fdp);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003, 2004 Eric B. Weddington <ericw@evcohs.com>
|
||||
* Copyright (C) 2003, 2004, 2006
|
||||
* Eric B. Weddington <eweddington@cso.atmel.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,7 +30,7 @@ reg = register as defined in an enum in ppi.h. This must be converted
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#if defined (WIN32NATIVE)
|
||||
|
||||
@@ -42,6 +43,7 @@ reg = register as defined in an enum in ppi.h. This must be converted
|
||||
#include <windows.h>
|
||||
#include <sys/time.h>
|
||||
#include <windows.h>
|
||||
#include "serial.h"
|
||||
#include "ppi.h"
|
||||
|
||||
extern char *progname;
|
||||
@@ -73,7 +75,7 @@ static const winpp winports[DEVICE_MAX] =
|
||||
|
||||
/* FUNCTION PROTOTYPES */
|
||||
static int winnt_pp_open(void);
|
||||
static unsigned short port_get(int fd, int reg);
|
||||
static unsigned short port_get(union filedescriptor *fdp, int reg);
|
||||
static unsigned char reg2offset(int reg);
|
||||
static unsigned char inb(unsigned short port);
|
||||
static void outb(unsigned char value, unsigned short port);
|
||||
@@ -82,7 +84,7 @@ static void outb(unsigned char value, unsigned short port);
|
||||
|
||||
/* FUNCTION DEFINITIONS */
|
||||
|
||||
int ppi_open(char *port)
|
||||
void ppi_open(char *port, union filedescriptor *fdp)
|
||||
{
|
||||
unsigned char i;
|
||||
int fd;
|
||||
@@ -92,7 +94,8 @@ int ppi_open(char *port)
|
||||
if(fd < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: can't open device \"giveio\"\n\n", progname);
|
||||
return(-1);
|
||||
fdp->ifd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Search the windows port names for a match */
|
||||
@@ -109,10 +112,11 @@ int ppi_open(char *port)
|
||||
if(fd < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: can't open device \"%s\"\n\n", progname, port);
|
||||
return(-1);
|
||||
fdp->ifd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
return(fd);
|
||||
fdp->ifd = fd;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +161,7 @@ static int winnt_pp_open(void)
|
||||
|
||||
|
||||
|
||||
void ppi_close(int fd)
|
||||
void ppi_close(union filedescriptor *fdp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -167,12 +171,12 @@ void ppi_close(int fd)
|
||||
/*
|
||||
* set the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_set(int fd, int reg, int bit)
|
||||
int ppi_set(union filedescriptor *fdp, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
unsigned short port;
|
||||
|
||||
port = port_get(fd, reg);
|
||||
port = port_get(fdp, reg);
|
||||
v = inb(port);
|
||||
v |= bit;
|
||||
outb(v, port);
|
||||
@@ -183,12 +187,12 @@ int ppi_set(int fd, int reg, int bit)
|
||||
/*
|
||||
* clear the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_clr(int fd, int reg, int bit)
|
||||
int ppi_clr(union filedescriptor *fdp, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
unsigned short port;
|
||||
|
||||
port = port_get(fd, reg);
|
||||
port = port_get(fdp, reg);
|
||||
v = inb(port);
|
||||
v &= ~bit;
|
||||
outb(v, port);
|
||||
@@ -200,11 +204,11 @@ int ppi_clr(int fd, int reg, int bit)
|
||||
/*
|
||||
* get the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_get(int fd, int reg, int bit)
|
||||
int ppi_get(union filedescriptor *fdp, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
|
||||
v = inb(port_get(fd, reg));
|
||||
v = inb(port_get(fdp, reg));
|
||||
v &= bit;
|
||||
|
||||
return(v);
|
||||
@@ -216,12 +220,12 @@ int ppi_get(int fd, int reg, int bit)
|
||||
/*
|
||||
* toggle the indicated bit of the specified register.
|
||||
*/
|
||||
int ppi_toggle(int fd, int reg, int bit)
|
||||
int ppi_toggle(union filedescriptor *fdp, int reg, int bit)
|
||||
{
|
||||
unsigned char v;
|
||||
unsigned short port;
|
||||
|
||||
port = port_get(fd, reg);
|
||||
port = port_get(fdp, reg);
|
||||
|
||||
v = inb(port);
|
||||
v ^= bit;
|
||||
@@ -234,11 +238,11 @@ int ppi_toggle(int fd, int reg, int bit)
|
||||
/*
|
||||
* get all bits of the specified register.
|
||||
*/
|
||||
int ppi_getall(int fd, int reg)
|
||||
int ppi_getall(union filedescriptor *fdp, int reg)
|
||||
{
|
||||
unsigned char v;
|
||||
|
||||
v = inb(port_get(fd, reg));
|
||||
v = inb(port_get(fdp, reg));
|
||||
|
||||
return((int)v);
|
||||
}
|
||||
@@ -249,9 +253,9 @@ int ppi_getall(int fd, int reg)
|
||||
/*
|
||||
* set all bits of the specified register to val.
|
||||
*/
|
||||
int ppi_setall(int fd, int reg, int val)
|
||||
int ppi_setall(union filedescriptor *fdp, int reg, int val)
|
||||
{
|
||||
outb((unsigned char)val, port_get(fd, reg));
|
||||
outb((unsigned char)val, port_get(fdp, reg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -259,9 +263,9 @@ int ppi_setall(int fd, int reg, int val)
|
||||
|
||||
|
||||
/* Calculate port address to access. */
|
||||
static unsigned short port_get(int fd, int reg)
|
||||
static unsigned short port_get(union filedescriptor *fdp, int reg)
|
||||
{
|
||||
return((unsigned short)(fd + reg2offset(reg)));
|
||||
return((unsigned short)(fdp->ifd + reg2offset(reg)));
|
||||
}
|
||||
|
||||
|
||||
@@ -316,7 +320,9 @@ static void outb(unsigned char value, unsigned short port)
|
||||
return;
|
||||
}
|
||||
|
||||
void gettimeofday(struct timeval*tv, void*z){
|
||||
#if !defined(HAVE_GETTIMEOFDAY)
|
||||
struct timezone;
|
||||
int gettimeofday(struct timeval *tv, struct timezone *unused){
|
||||
// i've found only ms resolution, avrdude expects us
|
||||
|
||||
SYSTEMTIME st;
|
||||
@@ -324,7 +330,10 @@ void gettimeofday(struct timeval*tv, void*z){
|
||||
|
||||
tv->tv_sec=(long)(st.wSecond+st.wMinute*60+st.wHour*3600);
|
||||
tv->tv_usec=(long)(st.wMilliseconds*1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_GETTIMEOFDAY */
|
||||
|
||||
// #define W32USLEEPDBG
|
||||
|
||||
|
||||
@@ -49,8 +49,14 @@ int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm,
|
||||
|
||||
/* 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);
|
||||
if (avr_write_byte(pgm, p, m, 0, fuse) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pgm->read_byte(pgm, p, m, 0, &fuseread) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Report information to user if needed */
|
||||
if (verbose > 0) {
|
||||
@@ -99,15 +105,25 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse,
|
||||
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(pgm->read_byte(pgm, p, m, 0, &safemode_fuse) != 0)
|
||||
{
|
||||
safemode_fuse = 1 + value; //failed - ensure they differ
|
||||
}
|
||||
if(pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
value = 1 + safemode_fuse; //failed - ensure they differ
|
||||
}
|
||||
if (value == safemode_fuse) {
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
value = 1 + safemode_fuse;
|
||||
}
|
||||
if (value == safemode_fuse)
|
||||
{
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fusegood == 0) {
|
||||
fprintf(stderr,
|
||||
@@ -126,10 +142,19 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse,
|
||||
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 (pgm->read_byte(pgm, p, m, 0, &safemode_lfuse) != 0)
|
||||
{
|
||||
safemode_lfuse = 1 + value;
|
||||
}
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
value = safemode_lfuse + 1;
|
||||
}
|
||||
if (value == safemode_lfuse) {
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
value = safemode_lfuse + 1;
|
||||
}
|
||||
if (value == safemode_lfuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
@@ -152,10 +177,19 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse,
|
||||
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 (pgm->read_byte(pgm, p, m, 0, &safemode_hfuse) != 0)
|
||||
{
|
||||
safemode_hfuse = value + 1;
|
||||
}
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
value = safemode_hfuse + 1;
|
||||
}
|
||||
if (value == safemode_hfuse) {
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
value = safemode_hfuse + 1;
|
||||
}
|
||||
if (value == safemode_hfuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
@@ -178,10 +212,19 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse,
|
||||
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 (pgm->read_byte(pgm, p, m, 0, &safemode_efuse) != 0)
|
||||
{
|
||||
safemode_efuse = value + 1;
|
||||
}
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
value = safemode_efuse + 1;
|
||||
}
|
||||
if (value == safemode_efuse) {
|
||||
avr_read_byte(pgm, p, m, 0, &value);
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
value = safemode_efuse + 1;
|
||||
}
|
||||
if (value == safemode_efuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
|
||||
648
avrdude/ser_avrdoper.c
Normal file
648
avrdude/ser_avrdoper.c
Normal file
@@ -0,0 +1,648 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2006 Christian Starkjohann
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
/*
|
||||
* Serial Interface emulation for USB programmer "AVR-Doper" in HID mode.
|
||||
*/
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#if defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID))
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Numeric constants for 'reportType' parameters */
|
||||
#define USB_HID_REPORT_TYPE_INPUT 1
|
||||
#define USB_HID_REPORT_TYPE_OUTPUT 2
|
||||
#define USB_HID_REPORT_TYPE_FEATURE 3
|
||||
|
||||
/* These are the error codes which can be returned by functions of this
|
||||
* module.
|
||||
*/
|
||||
#define USB_ERROR_NONE 0
|
||||
#define USB_ERROR_ACCESS 1
|
||||
#define USB_ERROR_NOTFOUND 2
|
||||
#define USB_ERROR_BUSY 16
|
||||
#define USB_ERROR_IO 5
|
||||
|
||||
#define USB_VENDOR_ID 0x16c0
|
||||
#define USB_PRODUCT_ID 0x05df
|
||||
|
||||
extern char *progname;
|
||||
extern int verbose;
|
||||
|
||||
static int reportDataSizes[4] = {13, 29, 61, 125};
|
||||
|
||||
static unsigned char avrdoperRxBuffer[280]; /* buffer for receive data */
|
||||
static int avrdoperRxLength = 0; /* amount of valid bytes in rx buffer */
|
||||
static int avrdoperRxPosition = 0; /* amount of bytes already consumed in rx buffer */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#ifdef WIN32NATIVE
|
||||
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
|
||||
#if defined(HAVE_DDK_HIDSDI_H)
|
||||
# include <ddk/hidsdi.h>
|
||||
#else
|
||||
# include "my_ddk_hidsdi.h"
|
||||
#endif
|
||||
#include <ddk/hidpi.h>
|
||||
|
||||
#ifdef USB_DEBUG
|
||||
#define DEBUG_PRINT(arg) printf arg
|
||||
#else
|
||||
#define DEBUG_PRINT(arg)
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void convertUniToAscii(char *buffer)
|
||||
{
|
||||
unsigned short *uni = (void *)buffer;
|
||||
char *ascii = buffer;
|
||||
|
||||
while(*uni != 0){
|
||||
if(*uni >= 256){
|
||||
*ascii++ = '?';
|
||||
}else{
|
||||
*ascii++ = *uni++;
|
||||
}
|
||||
}
|
||||
*ascii++ = 0;
|
||||
}
|
||||
|
||||
static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName,
|
||||
int product, char *productName, int usesReportIDs)
|
||||
{
|
||||
GUID hidGuid; /* GUID for HID driver */
|
||||
HDEVINFO deviceInfoList;
|
||||
SP_DEVICE_INTERFACE_DATA deviceInfo;
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = NULL;
|
||||
DWORD size;
|
||||
int i, openFlag = 0; /* may be FILE_FLAG_OVERLAPPED */
|
||||
int errorCode = USB_ERROR_NOTFOUND;
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
HIDD_ATTRIBUTES deviceAttributes;
|
||||
|
||||
HidD_GetHidGuid(&hidGuid);
|
||||
deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL,
|
||||
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
|
||||
deviceInfo.cbSize = sizeof(deviceInfo);
|
||||
for(i=0;;i++){
|
||||
if(handle != INVALID_HANDLE_VALUE){
|
||||
CloseHandle(handle);
|
||||
handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if(!SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo))
|
||||
break; /* no more entries */
|
||||
/* first do a dummy call just to determine the actual size required */
|
||||
SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL);
|
||||
if(deviceDetails != NULL)
|
||||
free(deviceDetails);
|
||||
deviceDetails = malloc(size);
|
||||
deviceDetails->cbSize = sizeof(*deviceDetails);
|
||||
/* this call is for real: */
|
||||
SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails,
|
||||
size, &size, NULL);
|
||||
DEBUG_PRINT(("checking HID path \"%s\"\n", deviceDetails->DevicePath));
|
||||
/* attempt opening for R/W -- we don't care about devices which can't be accessed */
|
||||
handle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
openFlag, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE){
|
||||
DEBUG_PRINT(("opening failed: %d\n", (int)GetLastError()));
|
||||
/* errorCode = USB_ERROR_ACCESS; opening will always fail for mouse -- ignore */
|
||||
continue;
|
||||
}
|
||||
deviceAttributes.Size = sizeof(deviceAttributes);
|
||||
HidD_GetAttributes(handle, &deviceAttributes);
|
||||
DEBUG_PRINT(("device attributes: vid=%d pid=%d\n",
|
||||
deviceAttributes.VendorID, deviceAttributes.ProductID));
|
||||
if(deviceAttributes.VendorID != vendor || deviceAttributes.ProductID != product)
|
||||
continue; /* ignore this device */
|
||||
errorCode = USB_ERROR_NOTFOUND;
|
||||
if(vendorName != NULL && productName != NULL){
|
||||
char buffer[512];
|
||||
if(!HidD_GetManufacturerString(handle, buffer, sizeof(buffer))){
|
||||
DEBUG_PRINT(("error obtaining vendor name\n"));
|
||||
errorCode = USB_ERROR_IO;
|
||||
continue;
|
||||
}
|
||||
convertUniToAscii(buffer);
|
||||
DEBUG_PRINT(("vendorName = \"%s\"\n", buffer));
|
||||
if(strcmp(vendorName, buffer) != 0)
|
||||
continue;
|
||||
if(!HidD_GetProductString(handle, buffer, sizeof(buffer))){
|
||||
DEBUG_PRINT(("error obtaining product name\n"));
|
||||
errorCode = USB_ERROR_IO;
|
||||
continue;
|
||||
}
|
||||
convertUniToAscii(buffer);
|
||||
DEBUG_PRINT(("productName = \"%s\"\n", buffer));
|
||||
if(strcmp(productName, buffer) != 0)
|
||||
continue;
|
||||
}
|
||||
break; /* we have found the device we are looking for! */
|
||||
}
|
||||
SetupDiDestroyDeviceInfoList(deviceInfoList);
|
||||
if(deviceDetails != NULL)
|
||||
free(deviceDetails);
|
||||
if(handle != INVALID_HANDLE_VALUE){
|
||||
fdp->pfd = (void *)handle;
|
||||
errorCode = 0;
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void usbCloseDevice(union filedescriptor *fdp)
|
||||
{
|
||||
CloseHandle((HANDLE)fdp->pfd);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len)
|
||||
{
|
||||
HANDLE handle = (HANDLE)fdp->pfd;
|
||||
BOOLEAN rval = 0;
|
||||
DWORD bytesWritten;
|
||||
|
||||
switch(reportType){
|
||||
case USB_HID_REPORT_TYPE_INPUT:
|
||||
break;
|
||||
case USB_HID_REPORT_TYPE_OUTPUT:
|
||||
rval = WriteFile(handle, buffer, len, &bytesWritten, NULL);
|
||||
break;
|
||||
case USB_HID_REPORT_TYPE_FEATURE:
|
||||
rval = HidD_SetFeature(handle, buffer, len);
|
||||
break;
|
||||
}
|
||||
return rval == 0 ? USB_ERROR_IO : 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber,
|
||||
char *buffer, int *len)
|
||||
{
|
||||
HANDLE handle = (HANDLE)fdp->pfd;
|
||||
BOOLEAN rval = 0;
|
||||
DWORD bytesRead;
|
||||
|
||||
switch(reportType){
|
||||
case USB_HID_REPORT_TYPE_INPUT:
|
||||
buffer[0] = reportNumber;
|
||||
rval = ReadFile(handle, buffer, *len, &bytesRead, NULL);
|
||||
if(rval)
|
||||
*len = bytesRead;
|
||||
break;
|
||||
case USB_HID_REPORT_TYPE_OUTPUT:
|
||||
break;
|
||||
case USB_HID_REPORT_TYPE_FEATURE:
|
||||
buffer[0] = reportNumber;
|
||||
rval = HidD_GetFeature(handle, buffer, *len);
|
||||
break;
|
||||
}
|
||||
return rval == 0 ? USB_ERROR_IO : 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#else /* !WIN32NATIVE */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#include <usb.h>
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define USBRQ_HID_GET_REPORT 0x01
|
||||
#define USBRQ_HID_SET_REPORT 0x09
|
||||
|
||||
static int usesReportIDs;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen)
|
||||
{
|
||||
char buffer[256];
|
||||
int rval, i;
|
||||
|
||||
if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
||||
(USB_DT_STRING << 8) + index, langid, buffer,
|
||||
sizeof(buffer), 1000)) < 0)
|
||||
return rval;
|
||||
if(buffer[1] != USB_DT_STRING)
|
||||
return 0;
|
||||
if((unsigned char)buffer[0] < rval)
|
||||
rval = (unsigned char)buffer[0];
|
||||
rval /= 2;
|
||||
/* lossy conversion to ISO Latin1 */
|
||||
for(i=1;i<rval;i++){
|
||||
if(i > buflen) /* destination buffer overflow */
|
||||
break;
|
||||
buf[i-1] = buffer[2 * i];
|
||||
if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
||||
buf[i-1] = '?';
|
||||
}
|
||||
buf[i-1] = 0;
|
||||
return i-1;
|
||||
}
|
||||
|
||||
static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName,
|
||||
int product, char *productName, int doReportIDs)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *handle = NULL;
|
||||
int errorCode = USB_ERROR_NOTFOUND;
|
||||
static int didUsbInit = 0;
|
||||
|
||||
if(!didUsbInit){
|
||||
usb_init();
|
||||
didUsbInit = 1;
|
||||
}
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
for(bus=usb_get_busses(); bus; bus=bus->next){
|
||||
for(dev=bus->devices; dev; dev=dev->next){
|
||||
if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){
|
||||
char string[256];
|
||||
int len;
|
||||
handle = usb_open(dev); /* we need to open the device in order to query strings */
|
||||
if(!handle){
|
||||
errorCode = USB_ERROR_ACCESS;
|
||||
fprintf(stderr, "Warning: cannot open USB device: %s\n",
|
||||
usb_strerror());
|
||||
continue;
|
||||
}
|
||||
if(vendorName == NULL && productName == NULL){ /* name does not matter */
|
||||
break;
|
||||
}
|
||||
/* now check whether the names match: */
|
||||
len = usbGetStringAscii(handle, dev->descriptor.iManufacturer,
|
||||
0x0409, string, sizeof(string));
|
||||
if(len < 0){
|
||||
errorCode = USB_ERROR_IO;
|
||||
fprintf(stderr,
|
||||
"Warning: cannot query manufacturer for device: %s\n",
|
||||
usb_strerror());
|
||||
}else{
|
||||
errorCode = USB_ERROR_NOTFOUND;
|
||||
/* fprintf(stderr, "seen device from vendor ->%s<-\n", string); */
|
||||
if(strcmp(string, vendorName) == 0){
|
||||
len = usbGetStringAscii(handle, dev->descriptor.iProduct,
|
||||
0x0409, string, sizeof(string));
|
||||
if(len < 0){
|
||||
errorCode = USB_ERROR_IO;
|
||||
fprintf(stderr,
|
||||
"Warning: cannot query product for device: %s\n",
|
||||
usb_strerror());
|
||||
}else{
|
||||
errorCode = USB_ERROR_NOTFOUND;
|
||||
/* fprintf(stderr, "seen product ->%s<-\n", string); */
|
||||
if(strcmp(string, productName) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
usb_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
if(handle)
|
||||
break;
|
||||
}
|
||||
if(handle != NULL){
|
||||
int rval, retries = 3;
|
||||
if(usb_set_configuration(handle, 1)){
|
||||
fprintf(stderr, "Warning: could not set configuration: %s\n",
|
||||
usb_strerror());
|
||||
}
|
||||
/* now try to claim the interface and detach the kernel HID driver on
|
||||
* linux and other operating systems which support the call.
|
||||
*/
|
||||
while((rval = usb_claim_interface(handle, 0)) != 0 && retries-- > 0){
|
||||
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
|
||||
if(usb_detach_kernel_driver_np(handle, 0) < 0){
|
||||
fprintf(stderr, "Warning: could not detach kernel HID driver: %s\n",
|
||||
usb_strerror());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if(rval != 0)
|
||||
fprintf(stderr, "Warning: could not claim interface\n");
|
||||
/* Continue anyway, even if we could not claim the interface. Control transfers
|
||||
* should still work.
|
||||
*/
|
||||
errorCode = 0;
|
||||
fdp->pfd = (void *)handle;
|
||||
usesReportIDs = doReportIDs;
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void usbCloseDevice(union filedescriptor *fdp)
|
||||
{
|
||||
usb_close((usb_dev_handle *)fdp->pfd);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len)
|
||||
{
|
||||
int bytesSent;
|
||||
|
||||
if(!usesReportIDs){
|
||||
buffer++; /* skip dummy report ID */
|
||||
len--;
|
||||
}
|
||||
bytesSent = usb_control_msg((usb_dev_handle *)fdp->pfd, USB_TYPE_CLASS |
|
||||
USB_RECIP_INTERFACE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT,
|
||||
reportType << 8 | buffer[0], 0, buffer, len, 5000);
|
||||
if(bytesSent != len){
|
||||
if(bytesSent < 0)
|
||||
fprintf(stderr, "Error sending message: %s\n", usb_strerror());
|
||||
return USB_ERROR_IO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber,
|
||||
char *buffer, int *len)
|
||||
{
|
||||
int bytesReceived, maxLen = *len;
|
||||
|
||||
if(!usesReportIDs){
|
||||
buffer++; /* make room for dummy report ID */
|
||||
maxLen--;
|
||||
}
|
||||
bytesReceived = usb_control_msg((usb_dev_handle *)fdp->pfd, USB_TYPE_CLASS |
|
||||
USB_RECIP_INTERFACE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT,
|
||||
reportType << 8 | reportNumber, 0, buffer, maxLen, 5000);
|
||||
if(bytesReceived < 0){
|
||||
fprintf(stderr, "Error sending message: %s\n", usb_strerror());
|
||||
return USB_ERROR_IO;
|
||||
}
|
||||
*len = bytesReceived;
|
||||
if(!usesReportIDs){
|
||||
buffer[-1] = reportNumber; /* add dummy report ID */
|
||||
*len++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WIN32NATIVE */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void dumpBlock(char *prefix, unsigned char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(len <= 8){ /* more compact format for short blocks */
|
||||
fprintf(stderr, "%s: %d bytes: ", prefix, len);
|
||||
for(i = 0; i < len; i++){
|
||||
fprintf(stderr, "%02x ", buf[i]);
|
||||
}
|
||||
fprintf(stderr, " \"");
|
||||
for(i = 0; i < len; i++){
|
||||
if(buf[i] >= 0x20 && buf[i] < 0x7f){
|
||||
fputc(buf[i], stderr);
|
||||
}else{
|
||||
fputc('.', stderr);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\"\n");
|
||||
}else{
|
||||
fprintf(stderr, "%s: %d bytes:\n", prefix, len);
|
||||
while(len > 0){
|
||||
for(i = 0; i < 16; i++){
|
||||
if(i < len){
|
||||
fprintf(stderr, "%02x ", buf[i]);
|
||||
}else{
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
if(i == 7)
|
||||
fputc(' ', stderr);
|
||||
}
|
||||
fprintf(stderr, " \"");
|
||||
for(i = 0; i < 16; i++){
|
||||
if(i < len){
|
||||
if(buf[i] >= 0x20 && buf[i] < 0x7f){
|
||||
fputc(buf[i], stderr);
|
||||
}else{
|
||||
fputc('.', stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\"\n");
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *usbErrorText(int usbErrno)
|
||||
{
|
||||
static char buffer[32];
|
||||
|
||||
switch(usbErrno){
|
||||
case USB_ERROR_NONE: return "Success.";
|
||||
case USB_ERROR_ACCESS: return "Access denied.";
|
||||
case USB_ERROR_NOTFOUND:return "Device not found.";
|
||||
case USB_ERROR_BUSY: return "Device is busy.";
|
||||
case USB_ERROR_IO: return "I/O Error.";
|
||||
default:
|
||||
sprintf(buffer, "Unknown error %d.", usbErrno);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void avrdoper_open(char *port, long baud, union filedescriptor *fdp)
|
||||
{
|
||||
int rval;
|
||||
char *vname = "obdev.at";
|
||||
char *devname = "AVR-Doper";
|
||||
|
||||
rval = usbOpenDevice(fdp, USB_VENDOR_ID, vname, USB_PRODUCT_ID, devname, 1);
|
||||
if(rval != 0){
|
||||
fprintf(stderr, "%s: avrdoper_open(): %s\n", progname, usbErrorText(rval));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void avrdoper_close(union filedescriptor *fdp)
|
||||
{
|
||||
usbCloseDevice(fdp);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int chooseDataSize(int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < sizeof(reportDataSizes)/sizeof(reportDataSizes[0]); i++){
|
||||
if(reportDataSizes[i] >= len)
|
||||
return i;
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
static int avrdoper_send(union filedescriptor *fdp, unsigned char *buf, size_t buflen)
|
||||
{
|
||||
if(verbose > 3)
|
||||
dumpBlock("Send", buf, buflen);
|
||||
while(buflen > 0){
|
||||
unsigned char buffer[256];
|
||||
int rval, lenIndex = chooseDataSize(buflen);
|
||||
int thisLen = buflen > reportDataSizes[lenIndex] ?
|
||||
reportDataSizes[lenIndex] : buflen;
|
||||
buffer[0] = lenIndex + 1; /* report ID */
|
||||
buffer[1] = thisLen;
|
||||
memcpy(buffer + 2, buf, thisLen);
|
||||
if(verbose > 3)
|
||||
fprintf(stderr, "Sending %d bytes data chunk\n", thisLen);
|
||||
rval = usbSetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, (char *)buffer,
|
||||
reportDataSizes[lenIndex] + 2);
|
||||
if(rval != 0){
|
||||
fprintf(stderr, "%s: avrdoper_send(): %s\n", progname, usbErrorText(rval));
|
||||
exit(1);
|
||||
}
|
||||
buflen -= thisLen;
|
||||
buf += thisLen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void avrdoperFillBuffer(union filedescriptor *fdp)
|
||||
{
|
||||
int bytesPending = reportDataSizes[1]; /* guess how much data is buffered in device */
|
||||
|
||||
avrdoperRxPosition = avrdoperRxLength = 0;
|
||||
while(bytesPending > 0){
|
||||
int len, usbErr, lenIndex = chooseDataSize(bytesPending);
|
||||
unsigned char buffer[128];
|
||||
len = sizeof(avrdoperRxBuffer) - avrdoperRxLength; /* bytes remaining */
|
||||
if(reportDataSizes[lenIndex] + 2 > len) /* requested data would not fit into buffer */
|
||||
break;
|
||||
len = reportDataSizes[lenIndex] + 2;
|
||||
usbErr = usbGetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, lenIndex + 1,
|
||||
(char *)buffer, &len);
|
||||
if(usbErr != 0){
|
||||
fprintf(stderr, "%s: avrdoperFillBuffer(): %s\n", progname, usbErrorText(usbErr));
|
||||
exit(1);
|
||||
}
|
||||
if(verbose > 3)
|
||||
fprintf(stderr, "Received %d bytes data chunk of total %d\n", len - 2, buffer[1]);
|
||||
len -= 2; /* compensate for report ID and length byte */
|
||||
bytesPending = buffer[1] - len; /* amount still buffered */
|
||||
if(len > buffer[1]) /* cut away padding */
|
||||
len = buffer[1];
|
||||
if(avrdoperRxLength + len > sizeof(avrdoperRxBuffer)){
|
||||
fprintf(stderr,
|
||||
"%s: avrdoperFillBuffer(): internal error: buffer overflow\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
memcpy(avrdoperRxBuffer + avrdoperRxLength, buffer + 2, len);
|
||||
avrdoperRxLength += len;
|
||||
}
|
||||
}
|
||||
|
||||
static int avrdoper_recv(union filedescriptor *fdp, unsigned char *buf, size_t buflen)
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
int remaining = buflen;
|
||||
|
||||
while(remaining > 0){
|
||||
int len, available = avrdoperRxLength - avrdoperRxPosition;
|
||||
if(available <= 0){ /* buffer is empty */
|
||||
avrdoperFillBuffer(fdp);
|
||||
continue;
|
||||
}
|
||||
len = remaining < available ? remaining : available;
|
||||
memcpy(p, avrdoperRxBuffer + avrdoperRxPosition, len);
|
||||
p += len;
|
||||
remaining -= len;
|
||||
avrdoperRxPosition += len;
|
||||
}
|
||||
if(verbose > 3)
|
||||
dumpBlock("Receive", buf, buflen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int avrdoper_drain(union filedescriptor *fdp, int display)
|
||||
{
|
||||
do{
|
||||
avrdoperFillBuffer(fdp);
|
||||
}while(avrdoperRxLength > 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct serial_device avrdoper_serdev =
|
||||
{
|
||||
.open = avrdoper_open,
|
||||
.close = avrdoper_close,
|
||||
.send = avrdoper_send,
|
||||
.recv = avrdoper_recv,
|
||||
.drain = avrdoper_drain,
|
||||
.flags = SERDEV_FL_NONE,
|
||||
};
|
||||
|
||||
#endif /* defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) */
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2006 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
|
||||
@@ -33,6 +34,9 @@
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
@@ -65,6 +69,9 @@ static struct baud_mapping baud_lookup_table [] = {
|
||||
{ 0, 0 } /* Terminator. */
|
||||
};
|
||||
|
||||
static struct termios original_termios;
|
||||
static int saved_original_termios;
|
||||
|
||||
static speed_t serial_baud_lookup(long baud)
|
||||
{
|
||||
struct baud_mapping *map = baud_lookup_table;
|
||||
@@ -75,99 +82,195 @@ static speed_t serial_baud_lookup(long baud)
|
||||
map++;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: serial_baud_lookup(): unknown baud rate: %ld",
|
||||
fprintf(stderr, "%s: serial_baud_lookup(): unknown baud rate: %ld\n",
|
||||
progname, baud);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int ser_setspeed(int fd, long baud)
|
||||
static int ser_setspeed(union filedescriptor *fd, long baud)
|
||||
{
|
||||
int rc;
|
||||
struct termios termios;
|
||||
speed_t speed = serial_baud_lookup (baud);
|
||||
|
||||
if (!isatty(fd))
|
||||
return -1;
|
||||
if (!isatty(fd->ifd))
|
||||
return -ENOTTY;
|
||||
|
||||
/*
|
||||
* initialize terminal modes
|
||||
*/
|
||||
rc = tcgetattr(fd, &termios);
|
||||
rc = tcgetattr(fd->ifd, &termios);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_setspeed(): tcgetattr() failed, %s",
|
||||
progname, strerror(errno));
|
||||
fprintf(stderr, "%s: ser_setspeed(): tcgetattr() failed",
|
||||
progname);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
termios.c_iflag = 0;
|
||||
/*
|
||||
* copy termios for ser_close if we haven't already
|
||||
*/
|
||||
if (! saved_original_termios++) {
|
||||
original_termios = termios;
|
||||
}
|
||||
|
||||
termios.c_iflag = IGNBRK;
|
||||
termios.c_oflag = 0;
|
||||
termios.c_cflag = 0;
|
||||
termios.c_cflag |= (CS8 | CREAD | CLOCAL);
|
||||
termios.c_lflag = 0;
|
||||
termios.c_cflag = (CS8 | CREAD | CLOCAL);
|
||||
termios.c_cc[VMIN] = 1;
|
||||
termios.c_cc[VTIME] = 0;
|
||||
|
||||
cfsetospeed(&termios, speed);
|
||||
cfsetispeed(&termios, speed);
|
||||
|
||||
rc = tcsetattr(fd, TCSANOW, &termios);
|
||||
rc = tcsetattr(fd->ifd, TCSANOW | TCSAFLUSH, &termios);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_setspeed(): tcsetattr() failed, %s",
|
||||
progname, strerror(errno));
|
||||
fprintf(stderr, "%s: ser_setspeed(): tcsetattr() failed",
|
||||
progname);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* set non blocking mode
|
||||
* Everything is now set up for a local line without modem control
|
||||
* or flow control, so clear O_NONBLOCK again.
|
||||
*/
|
||||
rc = fcntl(fd, F_GETFL, 0);
|
||||
fcntl(fd, F_SETFL, rc | O_NONBLOCK);
|
||||
#endif
|
||||
rc = fcntl(fd->ifd, F_GETFL, 0);
|
||||
if (rc != -1)
|
||||
fcntl(fd->ifd, F_SETFL, rc & ~O_NONBLOCK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a port description of the form <host>:<port>, open a TCP
|
||||
* connection to the specified destination, which is assumed to be a
|
||||
* terminal/console server with serial parameters configured
|
||||
* appropriately (e. g. 115200-8-N-1 for a STK500.)
|
||||
*/
|
||||
static void
|
||||
net_open(const char *port, union filedescriptor *fdp)
|
||||
{
|
||||
char *hstr, *pstr, *end;
|
||||
unsigned int pnum;
|
||||
int fd;
|
||||
struct sockaddr_in sockaddr;
|
||||
struct hostent *hp;
|
||||
|
||||
static int ser_open(char * port, long baud)
|
||||
if ((hstr = strdup(port)) == NULL) {
|
||||
fprintf(stderr, "%s: net_open(): Out of memory!\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (((pstr = strchr(hstr, ':')) == NULL) || (pstr == hstr)) {
|
||||
fprintf(stderr, "%s: net_open(): Mangled host:port string \"%s\"\n",
|
||||
progname, hstr);
|
||||
free(hstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate the host section of the description.
|
||||
*/
|
||||
*pstr++ = '\0';
|
||||
|
||||
pnum = strtoul(pstr, &end, 10);
|
||||
|
||||
if ((*pstr == '\0') || (*end != '\0') || (pnum == 0) || (pnum > 65535)) {
|
||||
fprintf(stderr, "%s: net_open(): Bad port number \"%s\"\n",
|
||||
progname, pstr);
|
||||
free(hstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((hp = gethostbyname(hstr)) == NULL) {
|
||||
fprintf(stderr, "%s: net_open(): unknown host \"%s\"\n",
|
||||
progname, hstr);
|
||||
free(hstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(hstr);
|
||||
|
||||
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
fprintf(stderr, "%s: net_open(): Cannot open socket: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&sockaddr, 0, sizeof(struct sockaddr_in));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_port = htons(pnum);
|
||||
memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
|
||||
fprintf(stderr, "%s: net_open(): Connect failed: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fdp->ifd = fd;
|
||||
}
|
||||
|
||||
static void ser_open(char * port, long baud, union filedescriptor *fdp)
|
||||
{
|
||||
int rc;
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* If the port is of the form "net:<host>:<port>", then
|
||||
* handle it as a TCP connection to a terminal server.
|
||||
*/
|
||||
if (strncmp(port, "net:", strlen("net:")) == 0) {
|
||||
net_open(port + strlen("net:"), fdp);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* open the serial port
|
||||
*/
|
||||
fd = open(port, O_RDWR | O_NOCTTY /*| O_NONBLOCK*/);
|
||||
fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "%s: ser_open(): can't open device \"%s\": %s\n",
|
||||
progname, port, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fdp->ifd = fd;
|
||||
|
||||
/*
|
||||
* set serial line attributes
|
||||
*/
|
||||
rc = ser_setspeed(fd, baud);
|
||||
rc = ser_setspeed(fdp, baud);
|
||||
if (rc) {
|
||||
fprintf(stderr,
|
||||
"%s: ser_open(): can't set attributes for device \"%s\"\n",
|
||||
progname, port);
|
||||
"%s: ser_open(): can't set attributes for device \"%s\": %s\n",
|
||||
progname, port, strerror(-rc));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
static void ser_close(int fd)
|
||||
static void ser_close(union filedescriptor *fd)
|
||||
{
|
||||
/* FIXME: Should really restore the terminal to original state here. */
|
||||
/*
|
||||
* restore original termios settings from ser_open
|
||||
*/
|
||||
if (saved_original_termios) {
|
||||
int rc = tcsetattr(fd->ifd, TCSANOW | TCSADRAIN, &original_termios);
|
||||
if (rc) {
|
||||
fprintf(stderr,
|
||||
"%s: ser_close(): can't reset attributes for device: %s\n",
|
||||
progname, strerror(errno));
|
||||
}
|
||||
saved_original_termios = 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
close(fd->ifd);
|
||||
}
|
||||
|
||||
|
||||
static int ser_send(int fd, unsigned char * buf, size_t buflen)
|
||||
static int ser_send(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
||||
{
|
||||
struct timeval timeout, to2;
|
||||
fd_set wfds;
|
||||
@@ -207,9 +310,9 @@ static int ser_send(int fd, unsigned char * buf, size_t buflen)
|
||||
while (len) {
|
||||
reselect:
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(fd, &wfds);
|
||||
FD_SET(fd->ifd, &wfds);
|
||||
|
||||
nfds = select(fd+1, NULL, &wfds, NULL, &to2);
|
||||
nfds = select(fd->ifd + 1, NULL, &wfds, NULL, &to2);
|
||||
if (nfds == 0) {
|
||||
if (verbose >= 1)
|
||||
fprintf(stderr,
|
||||
@@ -228,7 +331,7 @@ static int ser_send(int fd, unsigned char * buf, size_t buflen)
|
||||
}
|
||||
}
|
||||
|
||||
rc = write(fd, p, (len > 1024) ? 1024 : len);
|
||||
rc = write(fd->ifd, p, (len > 1024) ? 1024 : len);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_send(): write error: %s\n",
|
||||
progname, strerror(errno));
|
||||
@@ -242,7 +345,7 @@ static int ser_send(int fd, unsigned char * buf, size_t buflen)
|
||||
}
|
||||
|
||||
|
||||
static int ser_recv(int fd, unsigned char * buf, size_t buflen)
|
||||
static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
||||
{
|
||||
struct timeval timeout, to2;
|
||||
fd_set rfds;
|
||||
@@ -258,9 +361,9 @@ static int ser_recv(int fd, unsigned char * buf, size_t buflen)
|
||||
while (len < buflen) {
|
||||
reselect:
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
FD_SET(fd->ifd, &rfds);
|
||||
|
||||
nfds = select(fd+1, &rfds, NULL, NULL, &to2);
|
||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
||||
if (nfds == 0) {
|
||||
if (verbose > 1)
|
||||
fprintf(stderr,
|
||||
@@ -282,7 +385,7 @@ static int ser_recv(int fd, unsigned char * buf, size_t buflen)
|
||||
}
|
||||
}
|
||||
|
||||
rc = read(fd, p, (buflen - len > 1024) ? 1024 : buflen - len);
|
||||
rc = read(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_recv(): read error: %s\n",
|
||||
progname, strerror(errno));
|
||||
@@ -318,7 +421,7 @@ static int ser_recv(int fd, unsigned char * buf, size_t buflen)
|
||||
}
|
||||
|
||||
|
||||
static int ser_drain(int fd, int display)
|
||||
static int ser_drain(union filedescriptor *fd, int display)
|
||||
{
|
||||
struct timeval timeout;
|
||||
fd_set rfds;
|
||||
@@ -335,10 +438,10 @@ static int ser_drain(int fd, int display)
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
FD_SET(fd->ifd, &rfds);
|
||||
|
||||
reselect:
|
||||
nfds = select(fd+1, &rfds, NULL, NULL, &timeout);
|
||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
|
||||
if (nfds == 0) {
|
||||
if (display) {
|
||||
fprintf(stderr, "<drain\n");
|
||||
@@ -357,7 +460,7 @@ static int ser_drain(int fd, int display)
|
||||
}
|
||||
}
|
||||
|
||||
rc = read(fd, &buf, 1);
|
||||
rc = read(fd->ifd, &buf, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: ser_drain(): read error: %s\n",
|
||||
progname, strerror(errno));
|
||||
@@ -379,6 +482,7 @@ struct serial_device serial_serdev =
|
||||
.send = ser_send,
|
||||
.recv = ser_recv,
|
||||
.drain = ser_drain,
|
||||
.flags = SERDEV_FL_CANSETSPEED,
|
||||
};
|
||||
|
||||
struct serial_device *serdev = &serial_serdev;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003, 2004 Martin J. Thomas <mthomas@rhrk.uni-kl.de>
|
||||
* Copyright (C) 2006 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
|
||||
@@ -83,10 +84,10 @@ static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms
|
||||
return SetCommTimeouts(hComPort, &ctmo);
|
||||
}
|
||||
|
||||
static int ser_setspeed(int fd, long baud)
|
||||
static int ser_setspeed(union filedescriptor *fd, long baud)
|
||||
{
|
||||
DCB dcb;
|
||||
HANDLE hComPort = (HANDLE)fd;
|
||||
HANDLE hComPort = (HANDLE)fd->pfd;
|
||||
|
||||
ZeroMemory (&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
@@ -105,11 +106,25 @@ static int ser_setspeed(int fd, long baud)
|
||||
}
|
||||
|
||||
|
||||
static int ser_open(char * port, long baud)
|
||||
static void ser_open(char * port, long baud, union filedescriptor *fdp)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
HANDLE hComPort=INVALID_HANDLE_VALUE;
|
||||
|
||||
/*
|
||||
* If the port is of the form "net:<host>:<port>", then
|
||||
* handle it as a TCP connection to a terminal server.
|
||||
*
|
||||
* This is curently not implemented for Win32.
|
||||
*/
|
||||
if (strncmp(port, "net:", strlen("net:")) == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: ser_open(): network connects are currently not"
|
||||
"implemented for Win32 environments\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* if (hComPort!=INVALID_HANDLE_VALUE)
|
||||
fprintf(stderr, "%s: ser_open(): \"%s\" is already open\n",
|
||||
progname, port);
|
||||
@@ -143,8 +158,8 @@ static int ser_open(char * port, long baud)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (ser_setspeed((int)hComPort, baud) != 0)
|
||||
fdp->pfd = (void *)hComPort;
|
||||
if (ser_setspeed(fdp, baud) != 0)
|
||||
{
|
||||
CloseHandle(hComPort);
|
||||
fprintf(stderr, "%s: ser_open(): can't set com-state for \"%s\"\n",
|
||||
@@ -159,14 +174,12 @@ static int ser_open(char * port, long baud)
|
||||
progname, port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (int)hComPort;
|
||||
}
|
||||
|
||||
|
||||
static void ser_close(int fd)
|
||||
static void ser_close(union filedescriptor *fd)
|
||||
{
|
||||
HANDLE hComPort=(HANDLE)fd;
|
||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||
if (hComPort != INVALID_HANDLE_VALUE)
|
||||
CloseHandle (hComPort);
|
||||
|
||||
@@ -174,13 +187,14 @@ static void ser_close(int fd)
|
||||
}
|
||||
|
||||
|
||||
static int ser_send(int fd, char * buf, size_t buflen)
|
||||
static int ser_send(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
||||
{
|
||||
size_t len = buflen;
|
||||
unsigned char c='\0';
|
||||
DWORD written;
|
||||
unsigned char * b = buf;
|
||||
|
||||
HANDLE hComPort=(HANDLE)fd;
|
||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "%s: ser_send(): port not open\n",
|
||||
@@ -195,8 +209,8 @@ static int ser_send(int fd, char * buf, size_t buflen)
|
||||
{
|
||||
fprintf(stderr, "%s: Send: ", progname);
|
||||
|
||||
while (buflen) {
|
||||
c = *buf;
|
||||
while (len) {
|
||||
c = *b;
|
||||
if (isprint(c)) {
|
||||
fprintf(stderr, "%c ", c);
|
||||
}
|
||||
@@ -204,8 +218,8 @@ static int ser_send(int fd, char * buf, size_t buflen)
|
||||
fprintf(stderr, ". ");
|
||||
}
|
||||
fprintf(stderr, "[%02x] ", c);
|
||||
buf++;
|
||||
buflen--;
|
||||
b++;
|
||||
len--;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
@@ -228,14 +242,14 @@ static int ser_send(int fd, char * buf, size_t buflen)
|
||||
}
|
||||
|
||||
|
||||
static int ser_recv(int fd, char * buf, size_t buflen)
|
||||
static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
||||
{
|
||||
unsigned char c;
|
||||
char * p = buf;
|
||||
unsigned char * p = buf;
|
||||
size_t len = 0;
|
||||
DWORD read;
|
||||
|
||||
HANDLE hComPort=(HANDLE)fd;
|
||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "%s: ser_read(): port not open\n",
|
||||
@@ -288,14 +302,14 @@ static int ser_recv(int fd, char * buf, size_t buflen)
|
||||
}
|
||||
|
||||
|
||||
static int ser_drain(int fd, int display)
|
||||
static int ser_drain(union filedescriptor *fd, int display)
|
||||
{
|
||||
// int rc;
|
||||
unsigned char buf[10];
|
||||
BOOL readres;
|
||||
DWORD read;
|
||||
|
||||
HANDLE hComPort=(HANDLE)fd;
|
||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "%s: ser_drain(): port not open\n",
|
||||
@@ -348,6 +362,7 @@ struct serial_device serial_serdev =
|
||||
.send = ser_send,
|
||||
.recv = ser_recv,
|
||||
.drain = ser_drain,
|
||||
.flags = SERDEV_FL_CANSETSPEED,
|
||||
};
|
||||
|
||||
struct serial_device *serdev = &serial_serdev;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* 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>
|
||||
* Copyright (C) 2006 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
|
||||
@@ -50,25 +51,30 @@ struct termios oldmode;
|
||||
serial port/pin mapping
|
||||
|
||||
1 cd <-
|
||||
2 rxd <-
|
||||
2 (rxd) <-
|
||||
3 txd ->
|
||||
4 dtr ->
|
||||
5 dsr <-
|
||||
6 rts ->
|
||||
7 cts <-
|
||||
5 GND
|
||||
6 dsr <-
|
||||
7 rts ->
|
||||
8 cts <-
|
||||
9 ri <-
|
||||
*/
|
||||
|
||||
int serregbits[] =
|
||||
{ TIOCM_CD, 0, 0, TIOCM_DTR, TIOCM_DSR, TIOCM_RTS, TIOCM_CTS };
|
||||
#define DB9PINS 9
|
||||
|
||||
static int serregbits[DB9PINS + 1] =
|
||||
{ 0, TIOCM_CD, 0, 0, TIOCM_DTR, 0, TIOCM_DSR, TIOCM_RTS, TIOCM_CTS, TIOCM_RI };
|
||||
|
||||
#ifdef DEBUG
|
||||
char *serpins[7] =
|
||||
{ "CD", "RXD", "TXD ~RESET", "DTR MOSI", "DSR", "RTS SCK", "CTS MISO" };
|
||||
static char *serpins[DB9PINS + 1] =
|
||||
{ "NONE", "CD", "RXD", "TXD", "DTR", "GND", "DSR", "RTS", "CTS", "RI" };
|
||||
#endif
|
||||
|
||||
void serbb_setpin(int fd, int pin, int value)
|
||||
static int serbb_setpin(PROGRAMMER * pgm, int pin, int value)
|
||||
{
|
||||
unsigned int ctl;
|
||||
int r;
|
||||
|
||||
if (pin & PIN_INVERSE)
|
||||
{
|
||||
@@ -76,10 +82,8 @@ void serbb_setpin(int fd, int pin, int value)
|
||||
pin &= PIN_MASK;
|
||||
}
|
||||
|
||||
if ( pin < 1 || pin > 7 )
|
||||
return;
|
||||
|
||||
pin--;
|
||||
if ( pin < 1 || pin > DB9PINS )
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("%s to %d\n",serpins[pin],value);
|
||||
@@ -87,28 +91,42 @@ void serbb_setpin(int fd, int pin, int value)
|
||||
|
||||
switch ( pin )
|
||||
{
|
||||
case 2: /* txd */
|
||||
ioctl(fd, value ? TIOCSBRK : TIOCCBRK, 0);
|
||||
return;
|
||||
case 3: /* txd */
|
||||
r = ioctl(pgm->fd.ifd, value ? TIOCSBRK : TIOCCBRK, 0);
|
||||
if (r < 0) {
|
||||
perror("ioctl(\"TIOCxBRK\")");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 3: /* dtr, rts */
|
||||
case 5: ioctl(fd, TIOCMGET, &ctl);
|
||||
case 4: /* dtr */
|
||||
case 7: /* rts */
|
||||
r = ioctl(pgm->fd.ifd, TIOCMGET, &ctl);
|
||||
if (r < 0) {
|
||||
perror("ioctl(\"TIOCMGET\")");
|
||||
return -1;
|
||||
}
|
||||
if ( value )
|
||||
ctl |= serregbits[pin];
|
||||
else
|
||||
ctl &= ~(serregbits[pin]);
|
||||
ioctl(fd, TIOCMSET, &ctl);
|
||||
return;
|
||||
r = ioctl(pgm->fd.ifd, TIOCMSET, &ctl);
|
||||
if (r < 0) {
|
||||
perror("ioctl(\"TIOCMSET\")");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default: /* impossible */
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int serbb_getpin(int fd, int pin)
|
||||
static int serbb_getpin(PROGRAMMER * pgm, int pin)
|
||||
{
|
||||
unsigned int ctl;
|
||||
unsigned char invert;
|
||||
int r;
|
||||
|
||||
if (pin & PIN_INVERSE)
|
||||
{
|
||||
@@ -117,21 +135,23 @@ int serbb_getpin(int fd, int pin)
|
||||
} else
|
||||
invert = 0;
|
||||
|
||||
if ( pin < 1 || pin > 7 )
|
||||
if ( pin < 1 || pin > DB9PINS )
|
||||
return(-1);
|
||||
|
||||
pin --;
|
||||
|
||||
switch ( pin )
|
||||
{
|
||||
case 1: /* rxd, currently not implemented, FIXME */
|
||||
case 2: /* 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);
|
||||
case 1: /* cd */
|
||||
case 6: /* dsr */
|
||||
case 8: /* cts */
|
||||
case 9: /* ri */
|
||||
r = ioctl(pgm->fd.ifd, TIOCMGET, &ctl);
|
||||
if (r < 0) {
|
||||
perror("ioctl(\"TIOCMGET\")");
|
||||
return -1;
|
||||
}
|
||||
if ( !invert )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -152,95 +172,114 @@ int serbb_getpin(int fd, int pin)
|
||||
}
|
||||
}
|
||||
|
||||
int serbb_highpulsepin(int fd, int pin)
|
||||
static int serbb_highpulsepin(PROGRAMMER * pgm, int pin)
|
||||
{
|
||||
if (pin < 1 || pin > 7)
|
||||
if ( pin < 1 || pin > DB9PINS )
|
||||
return -1;
|
||||
|
||||
serbb_setpin(fd, pin, 1);
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
serbb_setpin(fd, pin, 0);
|
||||
serbb_setpin(pgm, pin, 1);
|
||||
if (pgm->ispdelay > 1)
|
||||
bitbang_delay(pgm->ispdelay);
|
||||
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
serbb_setpin(pgm, pin, 0);
|
||||
if (pgm->ispdelay > 1)
|
||||
bitbang_delay(pgm->ispdelay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void serbb_display(PROGRAMMER *pgm, char *p)
|
||||
static void serbb_display(PROGRAMMER *pgm, char *p)
|
||||
{
|
||||
/* MAYBE */
|
||||
}
|
||||
|
||||
void serbb_enable(PROGRAMMER *pgm)
|
||||
static void serbb_enable(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_disable(PROGRAMMER *pgm)
|
||||
static void serbb_disable(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_powerup(PROGRAMMER *pgm)
|
||||
static void serbb_powerup(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_powerdown(PROGRAMMER *pgm)
|
||||
static void serbb_powerdown(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
int serbb_open(PROGRAMMER *pgm, char *port)
|
||||
static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||
{
|
||||
struct termios mode;
|
||||
int flags;
|
||||
int r;
|
||||
|
||||
bitbang_check_prerequisites(pgm);
|
||||
|
||||
/* adapted from uisp code */
|
||||
|
||||
pgm->fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
pgm->fd.ifd = 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);
|
||||
}
|
||||
if (pgm->fd.ifd < 0) {
|
||||
perror(port);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
r = tcgetattr(pgm->fd.ifd, &mode);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "%s: ", port);
|
||||
perror("tcgetattr");
|
||||
return(-1);
|
||||
}
|
||||
oldmode = mode;
|
||||
|
||||
mode.c_iflag = IGNBRK | IGNPAR;
|
||||
mode.c_oflag = 0;
|
||||
mode.c_cflag = CLOCAL | CREAD | CS8 | B9600;
|
||||
mode.c_cc [VMIN] = 1;
|
||||
mode.c_cc [VTIME] = 0;
|
||||
|
||||
r = tcsetattr(pgm->fd.ifd, TCSANOW, &mode);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "%s: ", port);
|
||||
perror("tcsetattr");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Clear O_NONBLOCK flag. */
|
||||
flags = fcntl(pgm->fd.ifd, F_GETFL, 0);
|
||||
if (flags == -1)
|
||||
{
|
||||
fprintf(stderr, "%s: Can not get flags: %s\n",
|
||||
progname, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
flags &= ~O_NONBLOCK;
|
||||
if (fcntl(pgm->fd.ifd, F_SETFL, flags) == -1)
|
||||
{
|
||||
fprintf(stderr, "%s: Can not clear nonblock flag: %s\n",
|
||||
progname, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void serbb_close(PROGRAMMER *pgm)
|
||||
static void serbb_close(PROGRAMMER *pgm)
|
||||
{
|
||||
tcsetattr(pgm->fd, TCSADRAIN, &oldmode);
|
||||
if (pgm->fd.ifd != -1)
|
||||
{
|
||||
(void)tcsetattr(pgm->fd.ifd, TCSANOW, &oldmode);
|
||||
pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1);
|
||||
close(pgm->fd.ifd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -263,9 +302,11 @@ void serbb_initpgm(PROGRAMMER *pgm)
|
||||
pgm->cmd = bitbang_cmd;
|
||||
pgm->open = serbb_open;
|
||||
pgm->close = serbb_close;
|
||||
|
||||
/* this is a serial port bitbang device */
|
||||
pgm->flag = 1;
|
||||
pgm->setpin = serbb_setpin;
|
||||
pgm->getpin = serbb_getpin;
|
||||
pgm->highpulsepin = serbb_highpulsepin;
|
||||
pgm->read_byte = avr_read_byte_default;
|
||||
pgm->write_byte = avr_write_byte_default;
|
||||
}
|
||||
|
||||
#endif /* WIN32NATIVE */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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>
|
||||
* Copyright (C) 2005, 2006 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
|
||||
@@ -49,19 +49,21 @@ static int dtr, rts, txd;
|
||||
serial port/pin mapping
|
||||
|
||||
1 cd <-
|
||||
2 rxd <-
|
||||
2 (rxd) <-
|
||||
3 txd ->
|
||||
4 dtr ->
|
||||
5 dsr <-
|
||||
6 rts ->
|
||||
7 cts <-
|
||||
|
||||
Negative pin # means negated value.
|
||||
5 GND
|
||||
6 dsr <-
|
||||
7 rts ->
|
||||
8 cts <-
|
||||
9 ri <-
|
||||
*/
|
||||
|
||||
void serbb_setpin(int fd, int pin, int value)
|
||||
#define DB9PINS 9
|
||||
|
||||
static int serbb_setpin(PROGRAMMER * pgm, int pin, int value)
|
||||
{
|
||||
HANDLE hComPort = (HANDLE)fd;
|
||||
HANDLE hComPort = (HANDLE)pgm->fd.pfd;
|
||||
LPVOID lpMsgBuf;
|
||||
DWORD dwFunc;
|
||||
const char *name;
|
||||
@@ -72,26 +74,24 @@ void serbb_setpin(int fd, int pin, int value)
|
||||
pin &= PIN_MASK;
|
||||
}
|
||||
|
||||
if (pin < 1 || pin > 7)
|
||||
return;
|
||||
|
||||
pin--;
|
||||
if (pin < 1 || pin > DB9PINS)
|
||||
return -1;
|
||||
|
||||
switch (pin)
|
||||
{
|
||||
case 2: /* txd */
|
||||
case 3: /* txd */
|
||||
dwFunc = value? SETBREAK: CLRBREAK;
|
||||
name = value? "SETBREAK": "CLRBREAK";
|
||||
txd = value;
|
||||
break;
|
||||
|
||||
case 3: /* dtr */
|
||||
case 4: /* dtr */
|
||||
dwFunc = value? SETDTR: CLRDTR;
|
||||
name = value? "SETDTR": "CLRDTR";
|
||||
dtr = value;
|
||||
break;
|
||||
|
||||
case 5: /* rts */
|
||||
case 7: /* rts */
|
||||
dwFunc = value? SETRTS: CLRRTS;
|
||||
name = value? "SETRTS": "CLRRTS";
|
||||
break;
|
||||
@@ -101,7 +101,7 @@ void serbb_setpin(int fd, int pin, int value)
|
||||
fprintf(stderr,
|
||||
"%s: serbb_setpin(): unknown pin %d\n",
|
||||
progname, pin + 1);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
if (verbose > 4)
|
||||
fprintf(stderr,
|
||||
@@ -126,12 +126,12 @@ void serbb_setpin(int fd, int pin, int value)
|
||||
LocalFree(lpMsgBuf);
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serbb_getpin(int fd, int pin)
|
||||
static int serbb_getpin(PROGRAMMER * pgm, int pin)
|
||||
{
|
||||
HANDLE hComPort = (HANDLE)fd;
|
||||
HANDLE hComPort = (HANDLE)pgm->fd.pfd;
|
||||
LPVOID lpMsgBuf;
|
||||
int invert, rv;
|
||||
const char *name;
|
||||
@@ -144,12 +144,10 @@ int serbb_getpin(int fd, int pin)
|
||||
} else
|
||||
invert = 0;
|
||||
|
||||
if (pin < 1 || pin > 7)
|
||||
if (pin < 1 || pin > DB9PINS)
|
||||
return -1;
|
||||
|
||||
pin --;
|
||||
|
||||
if (pin == 0 /* cd */ || pin == 4 /* dsr */ || pin == 6 /* cts */)
|
||||
if (pin == 1 /* cd */ || pin == 6 /* dsr */ || pin == 8 /* cts */)
|
||||
{
|
||||
if (!GetCommModemStatus(hComPort, &modemstate))
|
||||
{
|
||||
@@ -176,13 +174,13 @@ int serbb_getpin(int fd, int pin)
|
||||
progname, modemstate);
|
||||
switch (pin)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
modemstate &= MS_RLSD_ON;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
modemstate &= MS_DSR_ON;
|
||||
break;
|
||||
case 6:
|
||||
case 8:
|
||||
modemstate &= MS_CTS_ON;
|
||||
break;
|
||||
}
|
||||
@@ -195,15 +193,15 @@ int serbb_getpin(int fd, int pin)
|
||||
|
||||
switch (pin)
|
||||
{
|
||||
case 2: /* txd */
|
||||
case 3: /* txd */
|
||||
rv = txd;
|
||||
name = "TXD";
|
||||
break;
|
||||
case 3: /* dtr */
|
||||
case 4: /* dtr */
|
||||
rv = dtr;
|
||||
name = "DTR";
|
||||
break;
|
||||
case 5: /* rts */
|
||||
case 7: /* rts */
|
||||
rv = rts;
|
||||
name = "RTS";
|
||||
break;
|
||||
@@ -224,56 +222,56 @@ int serbb_getpin(int fd, int pin)
|
||||
return rv;
|
||||
}
|
||||
|
||||
int serbb_highpulsepin(int fd, int pin)
|
||||
static int serbb_highpulsepin(PROGRAMMER * pgm, 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);
|
||||
serbb_setpin(pgm, pin, 1);
|
||||
if (pgm->ispdelay > 1)
|
||||
bitbang_delay(pgm->ispdelay);
|
||||
|
||||
#if SLOW_TOGGLE
|
||||
usleep(1000);
|
||||
#endif
|
||||
serbb_setpin(pgm, pin, 0);
|
||||
if (pgm->ispdelay > 1)
|
||||
bitbang_delay(pgm->ispdelay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void serbb_display(PROGRAMMER *pgm, char *p)
|
||||
static void serbb_display(PROGRAMMER *pgm, char *p)
|
||||
{
|
||||
/* MAYBE */
|
||||
}
|
||||
|
||||
void serbb_enable(PROGRAMMER *pgm)
|
||||
static void serbb_enable(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_disable(PROGRAMMER *pgm)
|
||||
static void serbb_disable(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_powerup(PROGRAMMER *pgm)
|
||||
static void serbb_powerup(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void serbb_powerdown(PROGRAMMER *pgm)
|
||||
static void serbb_powerdown(PROGRAMMER *pgm)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
int serbb_open(PROGRAMMER *pgm, char *port)
|
||||
static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||
{
|
||||
DCB dcb;
|
||||
LPVOID lpMsgBuf;
|
||||
HANDLE hComPort = INVALID_HANDLE_VALUE;
|
||||
|
||||
bitbang_check_prerequisites(pgm);
|
||||
|
||||
hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
@@ -325,18 +323,21 @@ int serbb_open(PROGRAMMER *pgm, char *port)
|
||||
"%s: ser_open(): opened comm port \"%s\", handle 0x%x\n",
|
||||
progname, port, (int)hComPort);
|
||||
|
||||
pgm->fd = (int)hComPort;
|
||||
pgm->fd.pfd = (void *)hComPort;
|
||||
|
||||
dtr = rts = txd = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serbb_close(PROGRAMMER *pgm)
|
||||
static void serbb_close(PROGRAMMER *pgm)
|
||||
{
|
||||
HANDLE hComPort=(HANDLE)pgm->fd;
|
||||
HANDLE hComPort=(HANDLE)pgm->fd.pfd;
|
||||
if (hComPort != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1);
|
||||
CloseHandle (hComPort);
|
||||
}
|
||||
if (verbose > 2)
|
||||
fprintf(stderr,
|
||||
"%s: ser_close(): closed comm port handle 0x%x\n",
|
||||
@@ -364,9 +365,11 @@ void serbb_initpgm(PROGRAMMER *pgm)
|
||||
pgm->cmd = bitbang_cmd;
|
||||
pgm->open = serbb_open;
|
||||
pgm->close = serbb_close;
|
||||
|
||||
/* this is a serial port bitbang device */
|
||||
pgm->flag = 1;
|
||||
pgm->setpin = serbb_setpin;
|
||||
pgm->getpin = serbb_getpin;
|
||||
pgm->highpulsepin = serbb_highpulsepin;
|
||||
pgm->read_byte = avr_read_byte_default;
|
||||
pgm->write_byte = avr_write_byte_default;
|
||||
}
|
||||
|
||||
#endif /* WIN32NATIVE */
|
||||
|
||||
@@ -31,20 +31,32 @@
|
||||
#define __serial_h__
|
||||
|
||||
extern long serial_recv_timeout;
|
||||
union filedescriptor
|
||||
{
|
||||
int ifd;
|
||||
void *pfd;
|
||||
};
|
||||
|
||||
struct serial_device
|
||||
{
|
||||
int (*open)(char * port, long baud);
|
||||
int (*setspeed)(int fd, long baud);
|
||||
void (*close)(int fd);
|
||||
void (*open)(char * port, long baud, union filedescriptor *fd);
|
||||
int (*setspeed)(union filedescriptor *fd, long baud);
|
||||
void (*close)(union filedescriptor *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);
|
||||
int (*send)(union filedescriptor *fd, unsigned char * buf, size_t buflen);
|
||||
int (*recv)(union filedescriptor *fd, unsigned char * buf, size_t buflen);
|
||||
int (*drain)(union filedescriptor *fd, int display);
|
||||
|
||||
int flags;
|
||||
#define SERDEV_FL_NONE 0x0000 /* no flags */
|
||||
#define SERDEV_FL_CANSETSPEED 0x0001 /* device can change speed */
|
||||
};
|
||||
|
||||
extern struct serial_device *serdev;
|
||||
extern struct serial_device serial_serdev, usb_serdev;
|
||||
extern struct serial_device serial_serdev;
|
||||
extern struct serial_device usb_serdev;
|
||||
extern struct serial_device usb_serdev_frame;
|
||||
extern struct serial_device avrdoper_serdev;
|
||||
|
||||
#define serial_open (serdev->open)
|
||||
#define serial_setspeed (serdev->setspeed)
|
||||
|
||||
51
avrdude/solaris_ecpp.h
Normal file
51
avrdude/solaris_ecpp.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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$ */
|
||||
|
||||
#ifndef solaris_ecpp_h
|
||||
#define solaris_ecpp_h
|
||||
|
||||
#include <sys/ecppio.h>
|
||||
|
||||
#define ppi_claim(fd) \
|
||||
do { \
|
||||
struct ecpp_transfer_parms p; \
|
||||
(void)ioctl(fd, ECPPIOC_GETPARMS, &p); \
|
||||
p.mode = ECPP_DIAG_MODE; \
|
||||
(void)ioctl(fd, ECPPIOC_SETPARMS, &p); \
|
||||
} while(0);
|
||||
|
||||
#define ppi_release(fd)
|
||||
|
||||
#define DO_PPI_READ(fd, reg, valp) \
|
||||
do { struct ecpp_regs r; \
|
||||
if ((reg) == PPIDATA) { (void)ioctl(fd, ECPPIOC_GETDATA, valp); } \
|
||||
else { (void)ioctl(fd, ECPPIOC_GETREGS, &r); \
|
||||
*(valp) = ((reg) == PPICTRL)? r.dcr: r.dsr; } \
|
||||
} while(0)
|
||||
#define DO_PPI_WRITE(fd, reg, valp) \
|
||||
do { struct ecpp_regs r; \
|
||||
if ((reg) == PPIDATA) { (void)ioctl(fd, ECPPIOC_SETDATA, valp); } \
|
||||
else { if ((reg) == PPICTRL) r.dcr = *(valp); else r.dsr = *(valp); \
|
||||
(void)ioctl(fd, ECPPIOC_SETREGS, &r); } \
|
||||
} while(0)
|
||||
|
||||
|
||||
#endif /* solaris_ecpp_h */
|
||||
174
avrdude/stk500.c
174
avrdude/stk500.c
@@ -57,7 +57,7 @@ static int stk500_is_page_empty(unsigned int address, int page_size,
|
||||
|
||||
static int stk500_send(PROGRAMMER * pgm, unsigned char * buf, size_t len)
|
||||
{
|
||||
return serial_send(pgm->fd, buf, len);
|
||||
return serial_send(&pgm->fd, buf, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,12 +65,12 @@ static int stk500_recv(PROGRAMMER * pgm, unsigned char * buf, size_t len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = serial_recv(pgm->fd, buf, len);
|
||||
rv = serial_recv(&pgm->fd, buf, len);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500_recv(): programmer is not responding\n",
|
||||
progname);
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ static int stk500_recv(PROGRAMMER * pgm, unsigned char * buf, size_t len)
|
||||
|
||||
static int stk500_drain(PROGRAMMER * pgm, int display)
|
||||
{
|
||||
return serial_drain(pgm->fd, display);
|
||||
return serial_drain(&pgm->fd, display);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,23 +90,35 @@ static int stk500_getsync(PROGRAMMER * pgm)
|
||||
* get in sync */
|
||||
buf[0] = Cmnd_STK_GET_SYNC;
|
||||
buf[1] = Sync_CRC_EOP;
|
||||
|
||||
/*
|
||||
* First send and drain a few times to get rid of line noise
|
||||
*/
|
||||
|
||||
stk500_send(pgm, buf, 2);
|
||||
stk500_recv(pgm, resp, 1);
|
||||
stk500_drain(pgm, 0);
|
||||
stk500_send(pgm, buf, 2);
|
||||
stk500_drain(pgm, 0);
|
||||
|
||||
stk500_send(pgm, buf, 2);
|
||||
if (stk500_recv(pgm, resp, 1) < 0)
|
||||
return -1;
|
||||
if (resp[0] != Resp_STK_INSYNC) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500_getsync(): not in sync: resp=0x%02x\n",
|
||||
progname, resp[0]);
|
||||
stk500_drain(pgm, 0);
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, resp, 1);
|
||||
if (stk500_recv(pgm, resp, 1) < 0)
|
||||
return -1;
|
||||
if (resp[0] != Resp_STK_OK) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500_getsync(): can't communicate with device: "
|
||||
"resp=0x%02x\n",
|
||||
progname, resp[0]);
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -131,7 +143,8 @@ static int stk500_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
|
||||
stk500_send(pgm, buf, 6);
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] != Resp_STK_INSYNC) {
|
||||
fprintf(stderr, "%s: stk500_cmd(): programmer is out of sync\n", progname);
|
||||
exit(1);
|
||||
@@ -140,9 +153,11 @@ static int stk500_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
res[0] = cmd[1];
|
||||
res[1] = cmd[2];
|
||||
res[2] = cmd[3];
|
||||
stk500_recv(pgm, &res[3], 1);
|
||||
if (stk500_recv(pgm, &res[3], 1) < 0)
|
||||
exit(1);
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] != Resp_STK_OK) {
|
||||
fprintf(stderr, "%s: stk500_cmd(): protocol error\n", progname);
|
||||
exit(1);
|
||||
@@ -161,6 +176,14 @@ static int stk500_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: Error: %s programmer uses stk500_chip_erase() but does not\n"
|
||||
"provide a cmd() method.\n",
|
||||
progname, pgm->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
|
||||
fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
|
||||
p->desc);
|
||||
@@ -197,14 +220,16 @@ static int stk500_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
buf[1] = Sync_CRC_EOP;
|
||||
|
||||
stk500_send(pgm, buf, 2);
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr, "%s: stk500_program_enable(): can't get into sync\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
stk500_getsync(pgm);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
@@ -215,7 +240,8 @@ static int stk500_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
return -1;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_OK) {
|
||||
return 0;
|
||||
}
|
||||
@@ -261,14 +287,16 @@ static int stk500_set_extended_parms(PROGRAMMER * pgm, int n,
|
||||
buf[i] = Sync_CRC_EOP;
|
||||
|
||||
stk500_send(pgm, buf, i+1);
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr, "%s: stk500_set_extended_parms(): can't get into sync\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
stk500_getsync(pgm);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
@@ -279,7 +307,8 @@ static int stk500_set_extended_parms(PROGRAMMER * pgm, int n,
|
||||
return -1;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_OK) {
|
||||
return 0;
|
||||
}
|
||||
@@ -426,14 +455,16 @@ static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
buf[21] = Sync_CRC_EOP;
|
||||
|
||||
stk500_send(pgm, buf, 22);
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500_initialize(): programmer not in sync, resp=0x%02x\n",
|
||||
progname, buf[0]);
|
||||
if (tries > 33)
|
||||
return -1;
|
||||
stk500_getsync(pgm);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
return -1;
|
||||
}
|
||||
@@ -445,7 +476,8 @@ static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
return -1;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] != Resp_STK_OK) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500_initialize(): (b) protocol error, "
|
||||
@@ -507,14 +539,16 @@ static void stk500_disable(PROGRAMMER * pgm)
|
||||
buf[1] = Sync_CRC_EOP;
|
||||
|
||||
stk500_send(pgm, buf, 2);
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr, "%s: stk500_disable(): can't get into sync\n",
|
||||
progname);
|
||||
return;
|
||||
}
|
||||
stk500_getsync(pgm);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
@@ -525,7 +559,8 @@ static void stk500_disable(PROGRAMMER * pgm)
|
||||
return;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_OK) {
|
||||
return;
|
||||
}
|
||||
@@ -550,19 +585,15 @@ static void stk500_enable(PROGRAMMER * pgm)
|
||||
static int 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);
|
||||
serial_open(port, pgm->baudrate? pgm->baudrate: 115200, &pgm->fd);
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
stk500_drain(pgm, 0);
|
||||
|
||||
stk500_getsync(pgm);
|
||||
|
||||
stk500_drain(pgm, 0);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -570,8 +601,8 @@ static int stk500_open(PROGRAMMER * pgm, char * port)
|
||||
|
||||
static void stk500_close(PROGRAMMER * pgm)
|
||||
{
|
||||
serial_close(pgm->fd);
|
||||
pgm->fd = -1;
|
||||
serial_close(&pgm->fd);
|
||||
pgm->fd.ifd = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -590,14 +621,16 @@ static int stk500_loadaddr(PROGRAMMER * pgm, unsigned int addr)
|
||||
|
||||
stk500_send(pgm, buf, 4);
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr, "%s: stk500_loadaddr(): can't get into sync\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
stk500_getsync(pgm);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
@@ -608,7 +641,8 @@ static int stk500_loadaddr(PROGRAMMER * pgm, unsigned int addr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_OK) {
|
||||
return 0;
|
||||
}
|
||||
@@ -625,13 +659,14 @@ static int stk500_loadaddr(PROGRAMMER * pgm, unsigned int addr)
|
||||
static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
unsigned char buf[16];
|
||||
unsigned char buf[page_size + 16];
|
||||
int memtype;
|
||||
unsigned int addr;
|
||||
int a_div;
|
||||
int block_size;
|
||||
int tries;
|
||||
unsigned int n;
|
||||
unsigned int i;
|
||||
int flash;
|
||||
|
||||
if (page_size == 0) {
|
||||
@@ -697,25 +732,29 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
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[3] = memtype;
|
||||
stk500_send(pgm, buf, 4);
|
||||
|
||||
stk500_send(pgm, &m->buf[addr], block_size);
|
||||
/* build command block and avoid multiple send commands as it leads to a crash
|
||||
of the silabs usb serial driver on mac os x */
|
||||
i = 0;
|
||||
buf[i++] = Cmnd_STK_PROG_PAGE;
|
||||
buf[i++] = (block_size >> 8) & 0xff;
|
||||
buf[i++] = block_size & 0xff;
|
||||
buf[i++] = memtype;
|
||||
memcpy(&buf[i], &m->buf[addr], block_size);
|
||||
i += block_size;
|
||||
buf[i++] = Sync_CRC_EOP;
|
||||
stk500_send( pgm, buf, i);
|
||||
|
||||
buf[0] = Sync_CRC_EOP;
|
||||
stk500_send(pgm, buf, 1);
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr, "\n%s: stk500_paged_write(): can't get into sync\n",
|
||||
progname);
|
||||
return -3;
|
||||
}
|
||||
stk500_getsync(pgm);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
@@ -726,7 +765,8 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
return -4;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] != Resp_STK_OK) {
|
||||
fprintf(stderr,
|
||||
"\n%s: stk500_paged_write(): (a) protocol error, "
|
||||
@@ -814,14 +854,16 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
buf[4] = Sync_CRC_EOP;
|
||||
stk500_send(pgm, buf, 5);
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr, "\n%s: stk500_paged_load(): can't get into sync\n",
|
||||
progname);
|
||||
return -3;
|
||||
}
|
||||
stk500_getsync(pgm);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
@@ -832,9 +874,11 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
return -4;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, &m->buf[addr], block_size);
|
||||
if (stk500_recv(pgm, &m->buf[addr], block_size) < 0)
|
||||
exit(1);
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] != Resp_STK_OK) {
|
||||
fprintf(stderr,
|
||||
"\n%s: stk500_paged_load(): (a) protocol error, "
|
||||
@@ -993,14 +1037,16 @@ static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value)
|
||||
|
||||
stk500_send(pgm, buf, 3);
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr, "\n%s: stk500_getparm(): can't get into sync\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
stk500_getsync(pgm);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
@@ -1011,10 +1057,12 @@ static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value)
|
||||
return -2;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
v = buf[0];
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_FAILED) {
|
||||
fprintf(stderr,
|
||||
"\n%s: stk500_getparm(): parameter 0x%02x failed\n",
|
||||
@@ -1049,14 +1097,16 @@ static int stk500_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value)
|
||||
|
||||
stk500_send(pgm, buf, 4);
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_NOSYNC) {
|
||||
if (tries > 33) {
|
||||
fprintf(stderr, "\n%s: stk500_setparm(): can't get into sync\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
stk500_getsync(pgm);
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
return -1;
|
||||
goto retry;
|
||||
}
|
||||
else if (buf[0] != Resp_STK_INSYNC) {
|
||||
@@ -1067,12 +1117,14 @@ static int stk500_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value)
|
||||
return -2;
|
||||
}
|
||||
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_OK)
|
||||
return 0;
|
||||
|
||||
parm = buf[0]; /* if not STK_OK, we've been echoed parm here */
|
||||
stk500_recv(pgm, buf, 1);
|
||||
if (stk500_recv(pgm, buf, 1) < 0)
|
||||
exit(1);
|
||||
if (buf[0] == Resp_STK_FAILED) {
|
||||
fprintf(stderr,
|
||||
"\n%s: stk500_setparm(): parameter 0x%02x failed\n",
|
||||
@@ -1189,6 +1241,8 @@ void stk500_initpgm(PROGRAMMER * pgm)
|
||||
pgm->cmd = stk500_cmd;
|
||||
pgm->open = stk500_open;
|
||||
pgm->close = stk500_close;
|
||||
pgm->read_byte = avr_read_byte_default;
|
||||
pgm->write_byte = avr_write_byte_default;
|
||||
|
||||
/*
|
||||
* optional functions
|
||||
|
||||
72
avrdude/stk500generic.c
Normal file
72
avrdude/stk500generic.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2006 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 Atmel STK500 programmer
|
||||
*
|
||||
* This is a wrapper around the STK500[v1] and STK500v2 programmers.
|
||||
* Try to select the programmer type that actually responds, and
|
||||
* divert to the actual programmer implementation if successful.
|
||||
*/
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pgm.h"
|
||||
#include "stk500.h"
|
||||
#include "stk500v2.h"
|
||||
|
||||
extern char *progname;
|
||||
|
||||
static int stk500generic_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
stk500_initpgm(pgm);
|
||||
if (pgm->open(pgm, port) >= 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: successfully opened stk500v1 device -- please use -c stk500v1\n",
|
||||
progname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
stk500v2_initpgm(pgm);
|
||||
if (pgm->open(pgm, port) >= 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: successfully opened stk500v2 device -- please use -c stk500v2\n",
|
||||
progname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"%s: cannot open either stk500v1 or stk500v2 programmer\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void stk500generic_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
strcpy(pgm->type, "STK500GENERIC");
|
||||
|
||||
pgm->open = stk500generic_open;
|
||||
}
|
||||
29
avrdude/stk500generic.h
Normal file
29
avrdude/stk500generic.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2006 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$ */
|
||||
|
||||
#ifndef stk500generic_h__
|
||||
#define stk500generic_h__
|
||||
|
||||
void stk500generic_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
1754
avrdude/stk500v2.c
1754
avrdude/stk500v2.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2005 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2006 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
|
||||
@@ -23,6 +24,12 @@
|
||||
#define stk500v2_h__
|
||||
|
||||
void stk500v2_initpgm (PROGRAMMER * pgm);
|
||||
void stk500hvsp_initpgm (PROGRAMMER * pgm);
|
||||
void stk500pp_initpgm (PROGRAMMER * pgm);
|
||||
void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm);
|
||||
void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm);
|
||||
void stk500v2_dragon_isp_initpgm(PROGRAMMER * pgm);
|
||||
void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -292,7 +292,7 @@ int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
|
||||
}
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
rc = avr_read_byte(pgm, p, mem, addr+i, &buf[i]);
|
||||
rc = pgm->read_byte(pgm, p, mem, addr+i, &buf[i]);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "error reading %s address 0x%05lx of part %s\n",
|
||||
mem->desc, addr+i, p->desc);
|
||||
@@ -399,7 +399,7 @@ int cmd_write(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
|
||||
werror = 1;
|
||||
}
|
||||
|
||||
rc = avr_read_byte(pgm, p, mem, addr+i, &b);
|
||||
rc = pgm->read_byte(pgm, p, mem, addr+i, &b);
|
||||
if (b != buf[i]) {
|
||||
fprintf(stderr,
|
||||
"%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n",
|
||||
@@ -427,6 +427,13 @@ int cmd_send(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
|
||||
int i;
|
||||
int len;
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
fprintf(stderr,
|
||||
"The %s programmer does not support direct ISP commands.\n",
|
||||
pgm->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc != 5) {
|
||||
fprintf(stderr, "Usage: send <byte1> <byte2> <byte3> <byte4>\n");
|
||||
return -1;
|
||||
|
||||
155
avrdude/tools/get-dw-params.xsl
Normal file
155
avrdude/tools/get-dw-params.xsl
Normal file
@@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding='ISO-8859-1' ?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<!--
|
||||
* Copyright (c) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
*
|
||||
* $Id$
|
||||
-->
|
||||
<!--
|
||||
* Extract the debugWire parameters
|
||||
* from the XML, and format it the way src/devdescr.cc needs it.
|
||||
*
|
||||
* Run this file together with the respective AVR's XML file through
|
||||
* an XSLT processor (xsltproc, saxon), and capture the output for
|
||||
* inclusion into avrdude.conf.in.
|
||||
-->
|
||||
<xsl:output method="text"/>
|
||||
<xsl:template match="/">
|
||||
<!-- Extract everything we need out of the XML. -->
|
||||
<xsl:variable name="devname_orig"
|
||||
select="/AVRPART/ADMIN/PART_NAME" />
|
||||
<xsl:variable name="devname"
|
||||
select="translate(/AVRPART/ADMIN/PART_NAME,
|
||||
'abcdefghijklmnopqrstuvwxyz',
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
|
||||
<xsl:variable name="devname_lower"
|
||||
select="translate(/AVRPART/ADMIN/PART_NAME,
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'abcdefghijklmnopqrstuvwxyz')" />
|
||||
<xsl:variable name="ucEepromInst"
|
||||
select="//AVRPART/ICE_SETTINGS/JTAGICEmkII/ucEepromInst" />
|
||||
<xsl:variable name="ucFlashInst"
|
||||
select="//AVRPART/ICE_SETTINGS/JTAGICEmkII/ucFlashInst" />
|
||||
|
||||
<!-- If there's a JTAGICEmkII node indicating debugWire, emit the entry. -->
|
||||
<xsl:if test='//AVRPART/ICE_SETTINGS/JTAGICEmkII/Interface="DebugWire"'>
|
||||
|
||||
<!-- start of new entry -->
|
||||
<xsl:text>#------------------------------------------------------------
</xsl:text>
|
||||
<xsl:text># </xsl:text>
|
||||
<xsl:value-of select="$devname_orig" />
|
||||
<xsl:text>
</xsl:text>
|
||||
<xsl:text>#------------------------------------------------------------
</xsl:text>
|
||||
<xsl:text>part
 desc = "</xsl:text>
|
||||
<xsl:value-of select="$devname_orig" />
|
||||
<xsl:text>";
 has_debugwire = yes;
</xsl:text>
|
||||
|
||||
<xsl:text> flash_instr = </xsl:text>
|
||||
<xsl:call-template name="format-hex">
|
||||
<xsl:with-param name="arg" select="$ucFlashInst" />
|
||||
<xsl:with-param name="count" select="0" />
|
||||
</xsl:call-template>
|
||||
<xsl:text>;
</xsl:text>
|
||||
|
||||
<xsl:text> eeprom_instr = </xsl:text>
|
||||
<xsl:call-template name="format-hex">
|
||||
<xsl:with-param name="arg" select="$ucEepromInst" />
|
||||
<xsl:with-param name="count" select="0" />
|
||||
</xsl:call-template>
|
||||
<xsl:text>;
</xsl:text>
|
||||
|
||||
</xsl:if> <!-- JTAGICEmkII uses debugWire -->
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="toupper">
|
||||
</xsl:template>
|
||||
|
||||
<!-- return argument $arg if non-empty, 0 otherwise -->
|
||||
<xsl:template name="maybezero">
|
||||
<xsl:param name="arg" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length($arg) = 0"><xsl:text>0</xsl:text></xsl:when>
|
||||
<xsl:otherwise><xsl:value-of select="$arg" /></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template> <!-- maybezero -->
|
||||
|
||||
<!-- convert $XX hex number in $arg (if any) into 0xXX; -->
|
||||
<!-- return 0 if $arg is empty -->
|
||||
<xsl:template name="dollar-to-0x">
|
||||
<xsl:param name="arg" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length($arg) = 0">
|
||||
<xsl:text>0</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="substring($arg, 1, 1) = '$'">
|
||||
<xsl:text>0x</xsl:text>
|
||||
<xsl:value-of select="substring($arg, 2)" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$arg" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template> <!-- dollar-to-0x -->
|
||||
|
||||
<!-- Format a string of 0xXX numbers: start a new line -->
|
||||
<!-- after each 8 hex numbers -->
|
||||
<!-- call with parameter $count = 0, calls itself -->
|
||||
<!-- recursively then until everything has been done -->
|
||||
<xsl:template name="format-hex">
|
||||
<xsl:param name="arg" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length($arg) <= 4">
|
||||
<!-- Last element, print it, and leave template. -->
|
||||
<xsl:value-of select="$arg" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<!--
|
||||
* More arguments follow, print first value,
|
||||
* followed by a comma, decide whether a space
|
||||
* or a newline needs to be emitted, and recurse
|
||||
* with the remaining part of $arg.
|
||||
-->
|
||||
<xsl:value-of select="substring($arg, 1, 4)" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="$count mod 8 = 7">
|
||||
<xsl:text>,
	 </xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:text>, </xsl:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:variable name="newarg">
|
||||
<!-- see whether there is a space after comma -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="substring($arg, 6, 1) = ' '">
|
||||
<xsl:value-of select="substring($arg, 7)" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring($arg, 6)" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:call-template name="format-hex">
|
||||
<xsl:with-param name="arg" select="$newarg" />
|
||||
<xsl:with-param name="count" select="$count + 1" />
|
||||
</xsl:call-template>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
254
avrdude/tools/get-hv-params.xsl
Normal file
254
avrdude/tools/get-hv-params.xsl
Normal file
@@ -0,0 +1,254 @@
|
||||
<?xml version="1.0" encoding='ISO-8859-1' ?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<!--
|
||||
* Copyright (c) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
*
|
||||
* $Id$
|
||||
-->
|
||||
<!--
|
||||
* Extract high-voltage (parallel and serial) programming parameters
|
||||
* out of the Atmel XML files, and convert them into avrdude.conf
|
||||
* snippets.
|
||||
*
|
||||
* Run this file together with the respective AVR's XML file through
|
||||
* an XSLT processor (xsltproc, saxon), and capture the output for
|
||||
* inclusion into avrdude.conf.in.
|
||||
-->
|
||||
<xsl:output method="text"/>
|
||||
<xsl:template match="/">
|
||||
<xsl:for-each select="//*">
|
||||
<xsl:if test='name() = "STK500_2"'>
|
||||
|
||||
<!--
|
||||
* High-voltage parallel programming parameters.
|
||||
-->
|
||||
<xsl:for-each
|
||||
select="*[starts-with(translate(name(),
|
||||
'abcdefghijklmnopqrstuvwxyz',
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
|
||||
'PP')]">
|
||||
<xsl:if test="self::node()[name() = 'PPControlStack']"
|
||||
> pp_controlstack =
|
||||
<xsl:call-template name="format_cstack">
|
||||
<xsl:with-param name="stack" select="." />
|
||||
<xsl:with-param name="count" select="0" />
|
||||
</xsl:call-template>;
|
||||
</xsl:if> <!-- PPControlStack -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'PpEnterProgMode']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'stabDelay']"
|
||||
> hventerstabdelay = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'progModeDelay']"
|
||||
> progmodedelay = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'latchCycles']"
|
||||
> latchcycles = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'toggleVtg']"
|
||||
> togglevtg = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'powerOffDelay']"
|
||||
> poweroffdelay = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'resetDelayMs']"
|
||||
> resetdelayms = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'resetDelayUs']"
|
||||
> resetdelayus = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- PpEnterProgMode -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'PpLeaveProgMode']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'stabDelay']"
|
||||
> hvleavestabdelay = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- PpLeaveProgMode -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'PpChipErase']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'pulseWidth']"
|
||||
> chiperasepulsewidth = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'pollTimeout']"
|
||||
> chiperasepolltimeout = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- PpChipErase -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'PpProgramFuse']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'pulseWidth']"
|
||||
> programfusepulsewidth = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'pollTimeout']"
|
||||
> programfusepolltimeout = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- PpProgramFuse -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'PpProgramLock']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'pulseWidth']"
|
||||
> programlockpulsewidth = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'pollTimeout']"
|
||||
> programlockpolltimeout = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- PpProgramLock -->
|
||||
|
||||
</xsl:for-each> <!-- PP parameters -->
|
||||
|
||||
<!--
|
||||
* High-voltage serial programming parameters.
|
||||
-->
|
||||
<xsl:for-each
|
||||
select="*[starts-with(translate(name(),
|
||||
'abcdefghijklmnopqrstuvwxyz',
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
|
||||
'HVSP')]">
|
||||
|
||||
<xsl:if test="self::node()[name() = 'HvspControlStack']"
|
||||
> hvsp_controlstack =
|
||||
<xsl:call-template name="format_cstack">
|
||||
<xsl:with-param name="stack" select="." />
|
||||
<xsl:with-param name="count" select="0" />
|
||||
</xsl:call-template>;
|
||||
</xsl:if> <!-- HvspControlStack -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'HvspEnterProgMode']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'stabDelay']"
|
||||
> hventerstabdelay = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'cmdexeDelay']"
|
||||
> hvspcmdexedelay = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'synchCycles']"
|
||||
> synchcycles = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'latchCycles']"
|
||||
> latchcycles = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'toggleVtg']"
|
||||
> togglevtg = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'powoffDelay']"
|
||||
> poweroffdelay = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'resetDelay1']"
|
||||
> resetdelayms = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'resetDelay2']"
|
||||
> resetdelayus = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- HvspEnterProgMode -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'HvspLeaveProgMode']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'stabDelay']"
|
||||
> hvleavestabdelay = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'resetDelay']"
|
||||
> resetdelay = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- HvspLeaveProgMode -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'HvspChipErase']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'pollTimeout']"
|
||||
> chiperasepolltimeout = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
<xsl:if test="self::node()[name() = 'eraseTime']"
|
||||
> chiperasetime = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- HvspChipErase -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'HvspProgramFuse']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'pollTimeout']"
|
||||
> programfusepolltimeout = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- HvspProgramFuse -->
|
||||
|
||||
<xsl:if test="self::node()[name() = 'HvspProgramLock']">
|
||||
<xsl:for-each select="*">
|
||||
<xsl:if test="self::node()[name() = 'pollTimeout']"
|
||||
> programlockpolltimeout = <xsl:value-of select="." />;
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:if> <!-- HvspProgramLock -->
|
||||
|
||||
</xsl:for-each> <!-- HVSP parameters -->
|
||||
|
||||
</xsl:if> <!-- STK500_2 parameters -->
|
||||
</xsl:for-each> <!-- All nodes -->
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
* Format the control stack argument: replace space-separated
|
||||
* list by a list separated with commas, followed by either
|
||||
* a space or a newline, dependend on the current argument
|
||||
* count.
|
||||
* This template calls itself recursively, until the entire
|
||||
* argument $stack has been processed.
|
||||
-->
|
||||
<xsl:template name="format_cstack">
|
||||
<xsl:param name="stack" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length($stack) <= 4">
|
||||
<!-- Last element, print it, and leave template. -->
|
||||
<xsl:value-of select="$stack" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<!--
|
||||
* More arguments follow, print first value,
|
||||
* followed by a comma, decide whether a space
|
||||
* or a newline needs to be emitted, and recurse
|
||||
* with the remaining part of $stack.
|
||||
-->
|
||||
<xsl:value-of select="substring($stack, 1, 4)" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="$count mod 8 = 7">
|
||||
<!-- comma, newline, 8 spaces indentation -->
|
||||
<xsl:text>,
|
||||
</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<!-- comma, space -->
|
||||
<xsl:text>, </xsl:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:call-template name="format_cstack">
|
||||
<xsl:with-param name="stack" select="substring($stack, 6)"
|
||||
/>
|
||||
<xsl:with-param name="count" select="$count + 1" />
|
||||
</xsl:call-template>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2005 Joerg Wunsch
|
||||
* Copyright (C) 2005,2006 Joerg Wunsch
|
||||
* Copyright (C) 2006 David Moore
|
||||
*
|
||||
* 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
|
||||
@@ -38,25 +39,24 @@
|
||||
#include <usb.h>
|
||||
|
||||
#include "serial.h"
|
||||
#include "usbdevs.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 char usbbuf[USBDEV_MAX_XFER];
|
||||
static int buflen = -1, bufptr;
|
||||
|
||||
static int usbdev_open(char * port, long baud)
|
||||
static int usb_interface;
|
||||
|
||||
/*
|
||||
* The "baud" parameter is meaningless for USB devices, so we reuse it
|
||||
* to pass the desired USB device ID.
|
||||
*/
|
||||
static void usbdev_open(char * port, long baud, union filedescriptor *fd)
|
||||
{
|
||||
char string[256];
|
||||
char product[256];
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *udev;
|
||||
@@ -99,7 +99,7 @@ static int usbdev_open(char * port, long baud)
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
for (bus = usb_busses; bus; bus = bus->next)
|
||||
for (bus = usb_get_busses(); bus; bus = bus->next)
|
||||
{
|
||||
for (dev = bus->devices; dev; dev = dev->next)
|
||||
{
|
||||
@@ -107,7 +107,7 @@ static int usbdev_open(char * port, long baud)
|
||||
if (udev)
|
||||
{
|
||||
if (dev->descriptor.idVendor == USB_VENDOR_ATMEL &&
|
||||
dev->descriptor.idProduct == USB_DEVICE_JTAGICEMKII)
|
||||
dev->descriptor.idProduct == (unsigned short)baud)
|
||||
{
|
||||
/* yeah, we found something */
|
||||
if (usb_get_string_simple(udev,
|
||||
@@ -130,10 +130,20 @@ static int usbdev_open(char * port, long baud)
|
||||
strcpy(string, "[unknown]");
|
||||
}
|
||||
|
||||
if (usb_get_string_simple(udev,
|
||||
dev->descriptor.iProduct,
|
||||
product, sizeof(product)) < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usb_open(): cannot read product name \"%s\"\n",
|
||||
progname, usb_strerror());
|
||||
strcpy(product, "[unnamed product]");
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
"%s: usb_open(): Found JTAG ICE, serno: %s\n",
|
||||
progname, string);
|
||||
"%s: usbdev_open(): Found %s, serno: %s\n",
|
||||
progname, product, string);
|
||||
if (serno != NULL)
|
||||
{
|
||||
/*
|
||||
@@ -153,8 +163,36 @@ static int usbdev_open(char * port, long baud)
|
||||
}
|
||||
}
|
||||
|
||||
return (int)udev;
|
||||
if (dev->config == NULL)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): USB device has no configuration\n",
|
||||
progname);
|
||||
goto trynext;
|
||||
}
|
||||
|
||||
if (usb_set_configuration(udev, dev->config[0].bConfigurationValue))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): error setting configuration %d: %s\n",
|
||||
progname, dev->config[0].bConfigurationValue,
|
||||
usb_strerror());
|
||||
goto trynext;
|
||||
}
|
||||
|
||||
usb_interface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber;
|
||||
if (usb_claim_interface(udev, usb_interface))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): error claiming interface %d: %s\n",
|
||||
progname, usb_interface, usb_strerror());
|
||||
goto trynext;
|
||||
}
|
||||
|
||||
fd->pfd = udev;
|
||||
return;
|
||||
}
|
||||
trynext:
|
||||
usb_close(udev);
|
||||
}
|
||||
}
|
||||
@@ -165,24 +203,70 @@ static int usbdev_open(char * port, long baud)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int usbdev_setspeed(int fd, long baud)
|
||||
static void usbdev_close(union filedescriptor *fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
|
||||
|
||||
static void usbdev_close(int fd)
|
||||
{
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd;
|
||||
(void)usb_release_interface(udev, usb_interface);
|
||||
|
||||
/*
|
||||
* Without this reset, the AVRISP mkII seems to stall the second
|
||||
* time we try to connect to it.
|
||||
*/
|
||||
usb_reset(udev);
|
||||
|
||||
usb_close(udev);
|
||||
}
|
||||
|
||||
|
||||
static int usbdev_send(int fd, unsigned char *bp, size_t mlen)
|
||||
static int usbdev_send(union filedescriptor *fd, unsigned char *bp, size_t mlen)
|
||||
{
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd;
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
|
||||
int rv;
|
||||
int i = mlen;
|
||||
unsigned char * p = bp;
|
||||
int tx_size;
|
||||
|
||||
return usb_bulk_write(udev, JTAGICE_BULK_EP, (char *)bp, mlen, 5000) != mlen;
|
||||
/*
|
||||
* Split the frame into multiple packets. It's important to make
|
||||
* sure we finish with a short packet, or else the device won't know
|
||||
* the frame is finished. For example, if we need to send 64 bytes,
|
||||
* we must send a packet of length 64 followed by a packet of length
|
||||
* 0.
|
||||
*/
|
||||
do {
|
||||
tx_size = (mlen < USBDEV_MAX_XFER)? mlen: USBDEV_MAX_XFER;
|
||||
rv = usb_bulk_write(udev, USBDEV_BULK_EP_WRITE, (char *)bp, tx_size, 5000);
|
||||
if (rv != tx_size)
|
||||
{
|
||||
fprintf(stderr, "%s: usbdev_send(): wrote %d out of %d bytes, err = %s\n",
|
||||
progname, rv, tx_size, usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
bp += tx_size;
|
||||
mlen -= tx_size;
|
||||
} while (tx_size == USBDEV_MAX_XFER);
|
||||
|
||||
if (verbose > 3)
|
||||
{
|
||||
fprintf(stderr, "%s: Sent: ", 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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -198,7 +282,7 @@ usb_fill_buf(usb_dev_handle *udev)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = usb_bulk_read(udev, JTAGICE_BULK_EP, usbbuf, JTAGICE_MAX_XFER, 5000);
|
||||
rv = usb_bulk_read(udev, USBDEV_BULK_EP_READ, usbbuf, USBDEV_MAX_XFER, 5000);
|
||||
if (rv < 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
@@ -213,9 +297,9 @@ usb_fill_buf(usb_dev_handle *udev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbdev_recv(int fd, unsigned char *buf, size_t nbytes)
|
||||
static int usbdev_recv(union filedescriptor *fd, unsigned char *buf, size_t nbytes)
|
||||
{
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd;
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
|
||||
int i, amnt;
|
||||
unsigned char * p = buf;
|
||||
|
||||
@@ -256,14 +340,79 @@ static int usbdev_recv(int fd, unsigned char *buf, size_t nbytes)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int usbdev_drain(int fd, int display)
|
||||
/*
|
||||
* This version of recv keeps reading packets until we receive a short
|
||||
* packet. Then, the entire frame is assembled and returned to the
|
||||
* user. The length will be unknown in advance, so we return the
|
||||
* length as the return value of this function, or -1 in case of an
|
||||
* error.
|
||||
*
|
||||
* This is used for the AVRISP mkII device.
|
||||
*/
|
||||
static int usbdev_recv_frame(union filedescriptor *fd, unsigned char *buf, size_t nbytes)
|
||||
{
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd;
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
|
||||
int rv, n;
|
||||
int i;
|
||||
unsigned char * p = buf;
|
||||
|
||||
n = 0;
|
||||
do
|
||||
{
|
||||
rv = usb_bulk_read(udev, USBDEV_BULK_EP_READ, usbbuf,
|
||||
USBDEV_MAX_XFER, 10000);
|
||||
if (rv < 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
fprintf(stderr, "%s: usbdev_recv_frame(): usb_bulk_read(): %s\n",
|
||||
progname, usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rv <= nbytes)
|
||||
{
|
||||
memcpy (buf, usbbuf, rv);
|
||||
buf += rv;
|
||||
}
|
||||
|
||||
n += rv;
|
||||
nbytes -= rv;
|
||||
}
|
||||
while (rv == USBDEV_MAX_XFER);
|
||||
|
||||
if (nbytes < 0)
|
||||
return -1;
|
||||
|
||||
if (verbose > 3)
|
||||
{
|
||||
i = n;
|
||||
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 n;
|
||||
}
|
||||
|
||||
static int usbdev_drain(union filedescriptor *fd, int display)
|
||||
{
|
||||
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
|
||||
int rv;
|
||||
|
||||
do {
|
||||
rv = usb_bulk_read(udev, JTAGICE_BULK_EP, usbbuf, JTAGICE_MAX_XFER, 100);
|
||||
rv = usb_bulk_read(udev, USBDEV_BULK_EP_READ, usbbuf, USBDEV_MAX_XFER, 100);
|
||||
if (rv > 0 && verbose >= 4)
|
||||
fprintf(stderr, "%s: usbdev_drain(): flushed %d characters\n",
|
||||
progname, rv);
|
||||
@@ -272,14 +421,30 @@ static int usbdev_drain(int fd, int display)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device descriptor for the JTAG ICE mkII.
|
||||
*/
|
||||
struct serial_device usb_serdev =
|
||||
{
|
||||
.open = usbdev_open,
|
||||
.setspeed = usbdev_setspeed,
|
||||
.close = usbdev_close,
|
||||
.send = usbdev_send,
|
||||
.recv = usbdev_recv,
|
||||
.drain = usbdev_drain,
|
||||
.flags = SERDEV_FL_NONE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Device descriptor for the AVRISP mkII.
|
||||
*/
|
||||
struct serial_device usb_serdev_frame =
|
||||
{
|
||||
.open = usbdev_open,
|
||||
.close = usbdev_close,
|
||||
.send = usbdev_send,
|
||||
.recv = usbdev_recv_frame,
|
||||
.drain = usbdev_drain,
|
||||
.flags = SERDEV_FL_NONE,
|
||||
};
|
||||
|
||||
#endif /* HAVE_LIBUSB */
|
||||
|
||||
446
avrdude/usbasp.c
Normal file
446
avrdude/usbasp.c
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2006 Thomas Fischl
|
||||
*
|
||||
* 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$ */
|
||||
|
||||
/*
|
||||
* Interface to the USBasp programmer.
|
||||
*
|
||||
* See http://www.fischl.de/usbasp/
|
||||
*/
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "avr.h"
|
||||
#include "pgm.h"
|
||||
#include "usbasp.h"
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
#include <usb.h>
|
||||
|
||||
extern int verbose;
|
||||
extern char * progname;
|
||||
extern int do_cycles;
|
||||
|
||||
static usb_dev_handle *usbhandle;
|
||||
|
||||
/*
|
||||
* wrapper for usb_control_msg call
|
||||
*/
|
||||
static int usbasp_transmit(unsigned char receive, unsigned char functionid,
|
||||
unsigned char send[4], unsigned char * buffer, int buffersize)
|
||||
{
|
||||
int nbytes;
|
||||
nbytes = usb_control_msg(usbhandle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE | (receive << 7),
|
||||
functionid,
|
||||
(send[1] << 8) | send[0],
|
||||
(send[3] << 8) | send[2],
|
||||
buffer, buffersize,
|
||||
5000);
|
||||
if(nbytes < 0){
|
||||
fprintf(stderr, "%s: error: usbasp_transmit: %s\n", progname, usb_strerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to open USB device with given VID, PID, vendor and product name
|
||||
* Parts of this function were taken from an example code by OBJECTIVE
|
||||
* DEVELOPMENT Software GmbH (www.obdev.at) to meet conditions for
|
||||
* shared VID/PID
|
||||
*/
|
||||
static int usbOpenDevice(usb_dev_handle **device, int vendor,
|
||||
char *vendorName, int product, char *productName)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *handle = NULL;
|
||||
int errorCode = USB_ERROR_NOTFOUND;
|
||||
static int didUsbInit = 0;
|
||||
|
||||
if(!didUsbInit){
|
||||
didUsbInit = 1;
|
||||
usb_init();
|
||||
}
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
for(bus=usb_get_busses(); bus; bus=bus->next){
|
||||
for(dev=bus->devices; dev; dev=dev->next){
|
||||
if(dev->descriptor.idVendor == vendor &&
|
||||
dev->descriptor.idProduct == product){
|
||||
char string[256];
|
||||
int len;
|
||||
/* we need to open the device in order to query strings */
|
||||
handle = usb_open(dev);
|
||||
if(!handle){
|
||||
errorCode = USB_ERROR_ACCESS;
|
||||
fprintf(stderr,
|
||||
"%s: Warning: cannot open USB device: %s\n",
|
||||
progname, usb_strerror());
|
||||
continue;
|
||||
}
|
||||
if(vendorName == NULL && productName == NULL){
|
||||
/* name does not matter */
|
||||
break;
|
||||
}
|
||||
/* now check whether the names match: */
|
||||
len = usb_get_string_simple(handle, dev->descriptor.iManufacturer,
|
||||
string, sizeof(string));
|
||||
if(len < 0){
|
||||
errorCode = USB_ERROR_IO;
|
||||
fprintf(stderr,
|
||||
"%s: Warning: cannot query manufacturer for device: %s\n",
|
||||
progname, usb_strerror());
|
||||
}else{
|
||||
errorCode = USB_ERROR_NOTFOUND;
|
||||
if (verbose > 1)
|
||||
fprintf(stderr,
|
||||
"%s: seen device from vendor ->%s<-\n",
|
||||
progname, string);
|
||||
if(strcmp(string, vendorName) == 0){
|
||||
len = usb_get_string_simple(handle, dev->descriptor.iProduct,
|
||||
string, sizeof(string));
|
||||
if(len < 0){
|
||||
errorCode = USB_ERROR_IO;
|
||||
fprintf(stderr,
|
||||
"%s: Warning: cannot query product for device: %s\n",
|
||||
progname, usb_strerror());
|
||||
}else{
|
||||
errorCode = USB_ERROR_NOTFOUND;
|
||||
if (verbose > 1)
|
||||
fprintf(stderr,
|
||||
"%s: seen product ->%s<-\n",
|
||||
progname, string);
|
||||
if(strcmp(string, productName) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
usb_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
if(handle)
|
||||
break;
|
||||
}
|
||||
if(handle != NULL){
|
||||
errorCode = 0;
|
||||
*device = handle;
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
usb_init();
|
||||
|
||||
if (usbOpenDevice(&usbhandle, USBASP_SHARED_VID, "www.fischl.de",
|
||||
USBASP_SHARED_PID, "USBasp") != 0) {
|
||||
|
||||
/* check if device with old VID/PID is available */
|
||||
if (usbOpenDevice(&usbhandle, USBASP_OLD_VID, "www.fischl.de",
|
||||
USBASP_OLD_PID, "USBasp") != 0) {
|
||||
|
||||
/* no USBasp found */
|
||||
fprintf(stderr,
|
||||
"%s: error: could not find USB device "
|
||||
"\"USBasp\" with vid=0x%x pid=0x%x\n",
|
||||
progname, USBASP_SHARED_VID, USBASP_SHARED_PID);
|
||||
exit(1);
|
||||
|
||||
} else {
|
||||
|
||||
/* found USBasp with old IDs */
|
||||
fprintf(stderr,
|
||||
"%s: Warning: Found USB device \"USBasp\" with "
|
||||
"old VID/PID! Please update firmware of USBasp!\n",
|
||||
progname);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void usbasp_close(PROGRAMMER * pgm)
|
||||
{
|
||||
unsigned char temp[4];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
usbasp_transmit(1, USBASP_FUNC_DISCONNECT, temp, temp, sizeof(temp));
|
||||
|
||||
usb_close(usbhandle);
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
|
||||
unsigned char temp[4];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
usbasp_transmit(1, USBASP_FUNC_CONNECT, temp, temp, sizeof(temp));
|
||||
|
||||
usleep(100000);
|
||||
|
||||
pgm->program_enable(pgm, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usbasp_disable(PROGRAMMER * pgm)
|
||||
{
|
||||
/* Do nothing. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void usbasp_enable(PROGRAMMER * pgm)
|
||||
{
|
||||
/* Do nothing. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void usbasp_display(PROGRAMMER * pgm, char * p)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
int nbytes =
|
||||
usbasp_transmit(1, USBASP_FUNC_TRANSMIT, cmd, res, sizeof(res));
|
||||
|
||||
if(nbytes != 4){
|
||||
fprintf(stderr, "%s: error: wrong responds size\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char res[4];
|
||||
unsigned char cmd[4];
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
memset(res, 0, sizeof(res));
|
||||
|
||||
cmd[0] = 0;
|
||||
|
||||
int nbytes =
|
||||
usbasp_transmit(1, USBASP_FUNC_ENABLEPROG, cmd, res, sizeof(res));
|
||||
|
||||
if ((nbytes != 1) | (res[0] != 0)) {
|
||||
fprintf(stderr, "%s: error: programm enable: target doesn't answer. %x \n",
|
||||
progname, res[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
int n;
|
||||
unsigned char cmd[4];
|
||||
int address = 0;
|
||||
int wbytes = n_bytes;
|
||||
int blocksize;
|
||||
unsigned char * buffer = m->buf;
|
||||
int function;
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
function = USBASP_FUNC_READFLASH;
|
||||
} else if (strcmp(m->desc, "eeprom") == 0) {
|
||||
function = USBASP_FUNC_READEEPROM;
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
|
||||
while (wbytes) {
|
||||
if (wbytes > USBASP_READBLOCKSIZE) {
|
||||
blocksize = USBASP_READBLOCKSIZE;
|
||||
wbytes -= USBASP_READBLOCKSIZE;
|
||||
} else {
|
||||
blocksize = wbytes;
|
||||
wbytes = 0;
|
||||
}
|
||||
|
||||
cmd[0] = address & 0xFF;
|
||||
cmd[1] = address >> 8;
|
||||
|
||||
n = usbasp_transmit(1, function, cmd, buffer, blocksize);
|
||||
|
||||
if (n != blocksize) {
|
||||
fprintf(stderr, "%s: error: wrong reading bytes %x\n",
|
||||
progname, n);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buffer += blocksize;
|
||||
address += blocksize;
|
||||
|
||||
report_progress (address, n_bytes, NULL);
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
int n;
|
||||
unsigned char cmd[4];
|
||||
int address = 0;
|
||||
int wbytes = n_bytes;
|
||||
int blocksize;
|
||||
unsigned char * buffer = m->buf;
|
||||
unsigned char blockflags = USBASP_BLOCKFLAG_FIRST;
|
||||
int function;
|
||||
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
function = USBASP_FUNC_WRITEFLASH;
|
||||
} else if (strcmp(m->desc, "eeprom") == 0) {
|
||||
function = USBASP_FUNC_WRITEEEPROM;
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
|
||||
while (wbytes) {
|
||||
if (wbytes > USBASP_WRITEBLOCKSIZE) {
|
||||
blocksize = USBASP_WRITEBLOCKSIZE;
|
||||
wbytes -= USBASP_WRITEBLOCKSIZE;
|
||||
} else {
|
||||
blocksize = wbytes;
|
||||
wbytes = 0;
|
||||
blockflags |= USBASP_BLOCKFLAG_LAST;
|
||||
}
|
||||
|
||||
cmd[0] = address & 0xFF;
|
||||
cmd[1] = address >> 8;
|
||||
cmd[2] = page_size & 0xFF;
|
||||
cmd[3] = (blockflags & 0x0F) + ((page_size & 0xF00) >> 4); //TP: Mega128 fix
|
||||
blockflags = 0;
|
||||
|
||||
n = usbasp_transmit(0, function, cmd, buffer, blocksize);
|
||||
|
||||
if (n != blocksize) {
|
||||
fprintf(stderr, "%s: error: wrong count at writing %x\n",
|
||||
progname, n);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
buffer += blocksize;
|
||||
address += blocksize;
|
||||
|
||||
report_progress (address, n_bytes, NULL);
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
void usbasp_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
strcpy(pgm->type, "usbasp");
|
||||
|
||||
/*
|
||||
* mandatory functions
|
||||
*/
|
||||
|
||||
pgm->initialize = usbasp_initialize;
|
||||
pgm->display = usbasp_display;
|
||||
pgm->enable = usbasp_enable;
|
||||
pgm->disable = usbasp_disable;
|
||||
pgm->program_enable = usbasp_program_enable;
|
||||
pgm->chip_erase = usbasp_chip_erase;
|
||||
pgm->cmd = usbasp_cmd;
|
||||
pgm->open = usbasp_open;
|
||||
pgm->close = usbasp_close;
|
||||
pgm->read_byte = avr_read_byte_default;
|
||||
pgm->write_byte = avr_write_byte_default;
|
||||
|
||||
/*
|
||||
* optional functions
|
||||
*/
|
||||
|
||||
pgm->paged_write = usbasp_paged_write;
|
||||
pgm->paged_load = usbasp_paged_load;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#else /* HAVE_LIBUSB */
|
||||
|
||||
extern char * progname;
|
||||
|
||||
static int usbasp_nousb_open (struct programmer_t *pgm, char * name)
|
||||
{
|
||||
fprintf(stderr, "%s: error: no usb support. please compile again with libusb installed.\n",
|
||||
progname);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void usbasp_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
strcpy(pgm->type, "usbasp");
|
||||
|
||||
pgm->open = usbasp_nousb_open;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBUSB */
|
||||
55
avrdude/usbasp.h
Normal file
55
avrdude/usbasp.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2006 Thomas Fischl
|
||||
*
|
||||
* 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 usbasp_h
|
||||
#define usbasp_h
|
||||
|
||||
#include "avrpart.h"
|
||||
|
||||
|
||||
#define USBASP_SHARED_VID 0x16C0 /* VOTI */
|
||||
#define USBASP_SHARED_PID 0x05DC /* Obdev's free shared PID */
|
||||
|
||||
#define USBASP_OLD_VID 0x03EB /* ATMEL */
|
||||
#define USBASP_OLD_PID 0xC7B4 /* (unoffical) USBasp */
|
||||
|
||||
#define USBASP_FUNC_CONNECT 1
|
||||
#define USBASP_FUNC_DISCONNECT 2
|
||||
#define USBASP_FUNC_TRANSMIT 3
|
||||
#define USBASP_FUNC_READFLASH 4
|
||||
#define USBASP_FUNC_ENABLEPROG 5
|
||||
#define USBASP_FUNC_WRITEFLASH 6
|
||||
#define USBASP_FUNC_READEEPROM 7
|
||||
#define USBASP_FUNC_WRITEEEPROM 8
|
||||
|
||||
#define USBASP_BLOCKFLAG_FIRST 1
|
||||
#define USBASP_BLOCKFLAG_LAST 2
|
||||
|
||||
#define USBASP_READBLOCKSIZE 200
|
||||
#define USBASP_WRITEBLOCKSIZE 200
|
||||
|
||||
#define USB_ERROR_NOTFOUND 1
|
||||
#define USB_ERROR_ACCESS 2
|
||||
#define USB_ERROR_IO 3
|
||||
|
||||
void usbasp_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif /* usbasp_h */
|
||||
42
avrdude/usbdevs.h
Normal file
42
avrdude/usbdevs.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2006 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$ */
|
||||
|
||||
/*
|
||||
* defines for the USB interface
|
||||
*/
|
||||
|
||||
#ifndef usbdevs_h
|
||||
#define usbdevs_h
|
||||
|
||||
#define USB_VENDOR_ATMEL 1003
|
||||
#define USB_DEVICE_JTAGICEMKII 0x2103
|
||||
#define USB_DEVICE_AVRISPMKII 0x2104
|
||||
#define USB_DEVICE_AVRDRAGON 0x2107
|
||||
|
||||
/*
|
||||
* Should we query the endpoint number and max transfer size from USB?
|
||||
* After all, the JTAG ICE mkII docs document these values.
|
||||
*/
|
||||
#define USBDEV_BULK_EP_WRITE 0x02
|
||||
#define USBDEV_BULK_EP_READ 0x82
|
||||
#define USBDEV_MAX_XFER 64
|
||||
|
||||
#endif /* usbdevs_h */
|
||||
4
avrdude/windows/.cvsignore
Normal file
4
avrdude/windows/.cvsignore
Normal file
@@ -0,0 +1,4 @@
|
||||
.cvsignore
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
Reference in New Issue
Block a user