Package: avrdude Version: 5.11.1-1 Severity: normal Dear Maintainer,
Pick a non-bit bang avr programmer, enter terminal mode, then give the "spi" command to enter direct SPI mdoe. avrdude crashes. Direct SPI mode allows sending and receiving data over SPI while the chip is running. This patch adds a check to avoid the crash and implements what is required for USBtiny (not a bit bang device) to do direct SPI mode, provided slave select is held low. Attached are patches for 5 and 6. Here's the upstream bug report. https://savannah.nongnu.org/bugs/index.php?43912 avrdude 5.x fix ------------------------------- >From 5eb948ba4fe6b8694ce52c842efd2a00c81c2cf5 Mon Sep 17 00:00:00 2001 From: David Fries <[email protected]> Date: Wed, 31 Dec 2014 20:55:57 -0600 Subject: [PATCH 1/3] fix NULL pointer crash entering direct spi mode If setpin isn't defined entering direct spi mode will crash, check before entering that mode. --- term.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/term.c b/term.c index 9df8c49..be0afa3 100644 --- a/term.c +++ b/term.c @@ -747,6 +747,11 @@ static int cmd_help(PROGRAMMER * pgm, struct avrpart * p, static int cmd_spi(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { + if(!pgm->setpin || !pgm->pinno[PIN_AVR_RESET]) { + fprintf(stdout, "The %s programmer does not support direct SPI mode.\n", + pgm->type); + return -1; + } pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1); spi_mode = 1; return 0; @@ -755,6 +760,9 @@ static int cmd_spi(PROGRAMMER * pgm, struct avrpart * p, static int cmd_pgm(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { + if(!pgm->setpin || !pgm->pinno[PIN_AVR_RESET]) { + return -1; + } pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0); spi_mode = 0; pgm->initialize(pgm, p); -- 1.7.10.4 >From 417b8405319937570cce07f2faea4deb0eb7e1dc Mon Sep 17 00:00:00 2001 From: David Fries <[email protected]> Date: Thu, 1 Jan 2015 18:12:29 -0600 Subject: [PATCH 2/3] set back to pgm mode in quit Otherwise it can't read the fuses and the safe fuse code complains. --- term.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/term.c b/term.c index be0afa3..1ea3784 100644 --- a/term.c +++ b/term.c @@ -554,6 +554,10 @@ static int cmd_sig(PROGRAMMER * pgm, struct avrpart * p, static int cmd_quit(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { + /* FUSE bit verify will fail if left in SPI mode */ + if(spi_mode == 1) { + cmd_pgm(pgm, p, 0, NULL); + } return 1; } -- 1.7.10.4 >From 9c989ef324b82dc8f77ac1f460f08cccbbb50d18 Mon Sep 17 00:00:00 2001 From: David Fries <[email protected]> Date: Wed, 31 Dec 2014 21:18:53 -0600 Subject: [PATCH 3/3] add direct spi mode to USBtiny --- usbtiny.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/usbtiny.c b/usbtiny.c index 5646757..886c53e 100644 --- a/usbtiny.c +++ b/usbtiny.c @@ -353,6 +353,20 @@ static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p ) return 0; } +static int usbtiny_setpin(struct programmer_t * pgm, int pin, int value) +{ + /* USBtiny is not a bit bang device, but it can set RESET */ + if(pin == PIN_AVR_RESET) { + if (usb_control(pgm, USBTINY_POWERUP, + PDATA(pgm)->sck_period, value ? RESET_HIGH : RESET_LOW) < 0) { + return -1; + } + usleep(50000); + return 0; + } + return -1; +} + /* Tell the USBtiny to release the output pins, etc */ static void usbtiny_powerdown(PROGRAMMER * pgm) { @@ -388,6 +402,26 @@ static int usbtiny_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res res[2] == cmd[1]); // AVR's do a delayed-echo thing } +static int usbtiny_spi(struct programmer_t * pgm, unsigned char cmd[], unsigned char res[], int count) +{ + int i; + + // Make sure its empty so we don't read previous calls if it fails + memset(res, '\0', count); + + if(count % 4) { + fprintf(stderr, "direct SPI write must be a multiple of 4 bytes for %s\n", + pgm->type); + return -1; + } + for(i=0; i<count; i+=4) { + if(usbtiny_cmd(pgm, cmd+i, res+i) < 0) { + return -1; + } + } + return 0; +} + /* Send the chip-erase command */ static int usbtiny_chip_erase(PROGRAMMER * pgm, AVRPART * p) { @@ -537,6 +571,9 @@ extern void usbtiny_initpgm ( PROGRAMMER* pgm ) { strcpy(pgm->type, "USBtiny"); + /* Just need to identify reset pin is requested */ + pgm->pinno[PIN_AVR_RESET] = PIN_AVR_RESET; + /* Mandatory Functions */ pgm->initialize = usbtiny_initialize; pgm->enable = usbtiny_enable; @@ -557,6 +594,8 @@ extern void usbtiny_initpgm ( PROGRAMMER* pgm ) pgm->set_sck_period = usbtiny_set_sck_period; pgm->setup = usbtiny_setup; pgm->teardown = usbtiny_teardown; + pgm->setpin = usbtiny_setpin; + pgm->spi = usbtiny_spi; } #else /* !HAVE_LIBUSB */ -- 1.7.10.4 avrdude 6 fix ------------------- >From a68a0d190fc3acdc85600d41ca94f133fcb5eb75 Mon Sep 17 00:00:00 2001 From: David Fries <[email protected]> Date: Thu, 1 Jan 2015 19:06:55 -0600 Subject: [PATCH 1/4] fix NULL pointer crash entering direct spi mode If setpin isn't defined entering direct spi mode will crash, check before entering that mode. --- avrdude/term.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/avrdude/term.c b/avrdude/term.c index 012f6f1..c8b1547 100644 --- a/avrdude/term.c +++ b/avrdude/term.c @@ -733,6 +733,11 @@ static int cmd_help(PROGRAMMER * pgm, struct avrpart * p, static int cmd_spi(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { + if(!pgm->setpin) { + fprintf(stdout, "The %s programmer does not support direct SPI mode.\n", + pgm->type); + return -1; + } pgm->setpin(pgm, PIN_AVR_RESET, 1); spi_mode = 1; return 0; @@ -741,6 +746,9 @@ static int cmd_spi(PROGRAMMER * pgm, struct avrpart * p, static int cmd_pgm(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { + if(!pgm->setpin) { + return -1; + } pgm->setpin(pgm, PIN_AVR_RESET, 0); spi_mode = 0; pgm->initialize(pgm, p); -- 1.7.10.4 >From 4815ad44ca2dec7275413cca02f759acbe0f120b Mon Sep 17 00:00:00 2001 From: David Fries <[email protected]> Date: Thu, 1 Jan 2015 19:08:14 -0600 Subject: [PATCH 2/4] set back to pgm mode in quit Otherwise it can't read the fuses and the safe fuse code complains. --- avrdude/term.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/avrdude/term.c b/avrdude/term.c index c8b1547..2489ac3 100644 --- a/avrdude/term.c +++ b/avrdude/term.c @@ -543,6 +543,10 @@ static int cmd_sig(PROGRAMMER * pgm, struct avrpart * p, static int cmd_quit(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { + /* FUSE bit verify will fail if left in SPI mode */ + if(spi_mode == 1) { + cmd_pgm(pgm, p, 0, NULL); + } return 1; } -- 1.7.10.4 >From c1aa8efd907d5e2d1930c278559129a3d2a5aed3 Mon Sep 17 00:00:00 2001 From: David Fries <[email protected]> Date: Thu, 1 Jan 2015 19:16:47 -0600 Subject: [PATCH 3/4] add direct spi mode to USBtiny It is limited to exactly sending (and receiving) 4 bytes, and unlike programming mode where slave select isn't required, SS must be held low for SPI to work. The USBtiny programmer I have doesn't have a wire for SS. --- avrdude/usbtiny.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/avrdude/usbtiny.c b/avrdude/usbtiny.c index b6bc7cc..1e1ce33 100644 --- a/avrdude/usbtiny.c +++ b/avrdude/usbtiny.c @@ -370,6 +370,20 @@ static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p ) return 0; } +static int usbtiny_setpin(struct programmer_t * pgm, int pinfunc, int value) +{ + /* USBtiny is not a bit bang device, but it can set RESET */ + if(pinfunc == PIN_AVR_RESET) { + if (usb_control(pgm, USBTINY_POWERUP, + PDATA(pgm)->sck_period, value ? RESET_HIGH : RESET_LOW) < 0) { + return -1; + } + usleep(50000); + return 0; + } + return -1; +} + /* Tell the USBtiny to release the output pins, etc */ static void usbtiny_powerdown(PROGRAMMER * pgm) { @@ -403,6 +417,26 @@ static int usbtiny_cmd(PROGRAMMER * pgm, const unsigned char *cmd, unsigned char res[2] == cmd[1]); // AVR's do a delayed-echo thing } +static int usbtiny_spi(struct programmer_t * pgm, const unsigned char *cmd, unsigned char *res, int count) +{ + int i; + + // Make sure its empty so we don't read previous calls if it fails + memset(res, '\0', count); + + if(count % 4) { + fprintf(stderr, "direct SPI write must be a multiple of 4 bytes for %s\n", + pgm->type); + return -1; + } + for(i=0; i<count; i+=4) { + if(usbtiny_cmd(pgm, cmd+i, res+i) < 0) { + return -1; + } + } + return 0; +} + /* Send the chip-erase command */ static int usbtiny_chip_erase(PROGRAMMER * pgm, AVRPART * p) { @@ -562,6 +596,8 @@ void usbtiny_initpgm ( PROGRAMMER* pgm ) pgm->set_sck_period = usbtiny_set_sck_period; pgm->setup = usbtiny_setup; pgm->teardown = usbtiny_teardown; + pgm->setpin = usbtiny_setpin; + pgm->spi = usbtiny_spi; } #else /* !HAVE_LIBUSB */ -- 1.7.10.4 >From 39b557f2dffb62e235b5012575d1f9843aa9ca23 Mon Sep 17 00:00:00 2001 From: David Fries <[email protected]> Date: Thu, 1 Jan 2015 19:58:23 -0600 Subject: [PATCH 4/4] man page updates for USBtiny and direct SPI --- avrdude/avrdude.1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/avrdude/avrdude.1 b/avrdude/avrdude.1 index a5e98ef..8028a41 100644 --- a/avrdude/avrdude.1 +++ b/avrdude/avrdude.1 @@ -739,7 +739,7 @@ Display the device signature bytes. Enter direct SPI mode. The .Em pgmled pin acts as slave select. -.Em Only supported on parallel bitbang programmers. +.Em Only supported on parallel bitbang programmers, and partially by USBtiny. .It Ar part Display the current part settings and parameters. Includes chip specific information including all memory types supported by the @@ -1118,7 +1118,8 @@ This also applies to the STK500 and STK600 in parallel programming mode. .Pp The USBasp and USBtinyISP drivers do not offer any option to distinguish multiple devices connected simultaneously, so effectively only a single device -is supported. +is supported. Slave Select must be externally held low for direct SPI when +using USBtinyISP, and send must be a multiple of four bytes. .Pp The avrftdi driver allows one to select specific devices using any combination of vid,pid serial number (usbsn) vendor description (usbvendoror part description (usbproduct) -- 1.7.10.4 -- System Information: Debian Release: 7.7 APT prefers stable APT policy: (500, 'stable') Architecture: amd64 (x86_64) Kernel: Linux 3.16.0-rc7+ (SMP w/2 CPU cores) Locale: LANG=C, LC_CTYPE=en_US.ISO-8859-15 (charmap=ISO-8859-15) Shell: /bin/sh linked to /bin/dash Versions of packages avrdude depends on: ii libc6 2.13-38+deb7u6 ii libftdi1 0.20-1+b1 ii libncurses5 5.9-10 ii libreadline6 6.2+dfsg-0.1 ii libtinfo5 5.9-10 ii libusb-0.1-4 2:0.1.12-20+nmu1 avrdude recommends no packages. Versions of packages avrdude suggests: ii avrdude-doc 5.11.1-1 -- no debconf information -- To UNSUBSCRIBE, email to [email protected] with a subject of "unsubscribe". Trouble? Contact [email protected]

