diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog index 1e8c2476..501ad2fb 100644 --- a/avrdude/ChangeLog +++ b/avrdude/ChangeLog @@ -1,3 +1,16 @@ +2009-02-17 Joerg Wunsch + + Submitted by Andrew O. Shadoura: + bug #25156: add direct SPI transfer mode + * bitbang.c: Implement direct SPI transfers. + * bitbang.h: (Ditto.) + * par.c: (Ditto.) + * pgm.c: (Ditto.) + * pgm.h: (Ditto.) + * term.c: Add the "spi" and "pgm" commands. + * avrdude.1: Document the changes. + * doc/avrdude.texi: (Ditto.) + 2009-02-17 Joerg Wunsch Submitted by Limor ("Lady Ada"): diff --git a/avrdude/NEWS b/avrdude/NEWS index fb792035..ad2c87b7 100644 --- a/avrdude/NEWS +++ b/avrdude/NEWS @@ -49,6 +49,8 @@ Current: * Add preliminary support for ATxmega128A1 for the JTAG ICE mkII using JTAG. + * Add support for direct SPI transfers (bug #25156). + * Bugfixes. Version 5.5: diff --git a/avrdude/avrdude.1 b/avrdude/avrdude.1 index 1333a5fe..a44814cc 100644 --- a/avrdude/avrdude.1 +++ b/avrdude/avrdude.1 @@ -1,6 +1,6 @@ .\" .\" avrdude - A Downloader/Uploader for AVR device programmers -.\" Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007, 2008 Joerg Wunsch +.\" Copyright (C) 2001, 2002, 2003, 2005 - 2009 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 @@ -679,13 +679,21 @@ feature of an AVR part that is not directly supported by .Nm , this command allows you to use it, even though .Nm -does not implement the command. +does not implement the command. When using direct SPI mode, up to 3 bytes +can be omitted. .It Ar sig Display the device signature bytes. +.It Ar spi +Enter direct SPI mode. The +.Em pgmled +pin acts as slave select. +.Em Only supported on parallel bitbang programmers. .It Ar part Display the current part settings and parameters. Includes chip specific information including all memory types supported by the device, read/write timing, etc. +.It Ar pgm +Return to programming mode (from direct SPI mode). .It Ar vtarg voltage Set the target's supply voltage to .Ar voltage diff --git a/avrdude/bitbang.c b/avrdude/bitbang.c index c532065f..b52517eb 100644 --- a/avrdude/bitbang.c +++ b/avrdude/bitbang.c @@ -225,6 +225,39 @@ int bitbang_cmd(PROGRAMMER * pgm, unsigned char cmd[4], return 0; } +/* + * transmit bytes via SPI and return the results; 'cmd' and + * 'res' must point to data buffers + */ +int bitbang_spi(PROGRAMMER * pgm, unsigned char cmd[], + unsigned char res[], int count) +{ + int i; + + pgm->setpin(pgm, pgm->pinno[PIN_LED_PGM], 0); + + for (i=0; isetpin(pgm, pgm->pinno[PIN_LED_PGM], 1); + + if(verbose >= 2) + { + fprintf(stderr, "bitbang_cmd(): [ "); + for(i = 0; i < count; i++) + fprintf(stderr, "%02X ", cmd[i]); + fprintf(stderr, "] [ "); + for(i = 0; i < count; i++) + { + fprintf(stderr, "%02X ", res[i]); + } + fprintf(stderr, "]\n"); + } + + return 0; +} + /* * issue the 'chip erase' command to the AVR device diff --git a/avrdude/bitbang.h b/avrdude/bitbang.h index 71aecb52..eb959c7d 100644 --- a/avrdude/bitbang.h +++ b/avrdude/bitbang.h @@ -39,6 +39,8 @@ int bitbang_pgm_led (PROGRAMMER * pgm, int value); int bitbang_vfy_led (PROGRAMMER * pgm, int value); int bitbang_cmd (PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]); +int bitbang_spi (PROGRAMMER * pgm, unsigned char cmd[], + unsigned char res[], int count); int bitbang_chip_erase (PROGRAMMER * pgm, AVRPART * p); int bitbang_program_enable (PROGRAMMER * pgm, AVRPART * p); void bitbang_powerup (PROGRAMMER * pgm); diff --git a/avrdude/doc/avrdude.texi b/avrdude/doc/avrdude.texi index 9570ae15..dd232634 100644 --- a/avrdude/doc/avrdude.texi +++ b/avrdude/doc/avrdude.texi @@ -30,7 +30,7 @@ For avrdude version @value{VERSION}, @value{UPDATED}. Copyright @copyright{} 2003, 2005 Brian Dean -Copyright @copyright{} 2006 - 2008 J@"org Wunsch +Copyright @copyright{} 2006 - 2009 J@"org Wunsch Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -1066,16 +1066,24 @@ Perform a chip erase. Send raw instruction codes to the AVR device. If you need access to a feature of an AVR part that is not directly supported by AVRDUDE, this command allows you to use it, even though AVRDUDE does not implement the -command. +command. When using direct SPI mode, up to 3 bytes +can be omitted. @item sig Display the device signature bytes. +@item spi +Enter direct SPI mode. The @emph{pgmled} pin acts as slave select. +@emph{Only supported on parallel bitbang programmers.} + @item part Display the current part settings and parameters. Includes chip specific information including all memory types supported by the device, read/write timing, etc. +@item pgm +Return to programming mode (from direct SPI mode). + @item ? @itemx help Give a short on-line summary of the available commands. diff --git a/avrdude/par.c b/avrdude/par.c index ea3a5037..caf0ee9a 100644 --- a/avrdude/par.c +++ b/avrdude/par.c @@ -416,6 +416,7 @@ void par_initpgm(PROGRAMMER * pgm) pgm->program_enable = bitbang_program_enable; pgm->chip_erase = bitbang_chip_erase; pgm->cmd = bitbang_cmd; + pgm->spi = bitbang_spi; pgm->open = par_open; pgm->close = par_close; pgm->setpin = par_setpin; diff --git a/avrdude/pgm.c b/avrdude/pgm.c index a9502721..07fa34cf 100644 --- a/avrdude/pgm.c +++ b/avrdude/pgm.c @@ -118,6 +118,7 @@ PROGRAMMER * pgm_new(void) * assigned before they are called */ pgm->cmd = NULL; + pgm->spi = NULL; pgm->paged_write = NULL; pgm->paged_load = NULL; pgm->write_setup = NULL; diff --git a/avrdude/pgm.h b/avrdude/pgm.h index 8ec81afe..2bd125be 100644 --- a/avrdude/pgm.h +++ b/avrdude/pgm.h @@ -78,6 +78,8 @@ typedef struct programmer_t { int (*chip_erase) (struct programmer_t * pgm, AVRPART * p); int (*cmd) (struct programmer_t * pgm, unsigned char cmd[4], unsigned char res[4]); + int (*spi) (struct programmer_t * pgm, unsigned char cmd[], + unsigned char res[], int count); int (*open) (struct programmer_t * pgm, char * port); void (*close) (struct programmer_t * pgm); int (*paged_write) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m, diff --git a/avrdude/term.c b/avrdude/term.c index e0e60e0a..2edd857d 100644 --- a/avrdude/term.c +++ b/avrdude/term.c @@ -88,6 +88,11 @@ static int cmd_fosc (PROGRAMMER * pgm, struct avrpart * p, static int cmd_sck (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); +static int cmd_spi (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); + +static int cmd_pgm (PROGRAMMER * pgm, struct avrpart * p, + int argc, char *argv[]); struct command cmd[] = { { "dump", cmd_dump, "dump memory : %s " }, @@ -102,6 +107,8 @@ struct command cmd[] = { { "varef", cmd_varef, "set (STK500 only)" }, { "fosc", cmd_fosc, "set (STK500 only)" }, { "sck", cmd_sck, "set (STK500 only)" }, + { "spi", cmd_spi, "enter direct SPI mode" }, + { "pgm", cmd_pgm, "return to programming mode" }, { "help", cmd_help, "help" }, { "?", cmd_help, "help" }, { "quit", cmd_quit, "quit" } @@ -111,7 +118,7 @@ struct command cmd[] = { - +static int spi_mode = 0; static int nexttok(char * buf, char ** tok, char ** next) { @@ -445,8 +452,18 @@ static int cmd_send(PROGRAMMER * pgm, struct avrpart * p, return -1; } - if (argc != 5) { - fprintf(stderr, "Usage: send \n"); + if (spi_mode && (pgm->spi == NULL)) { + fprintf(stderr, + "The %s programmer does not support direct SPI transfers.\n", + pgm->type); + return -1; + } + + + if ((argc > 5) || ((argc < 5) && (!spi_mode))) { + fprintf(stderr, spi_mode? + "Usage: send [ [ []]]\n": + "Usage: send \n"); return -1; } @@ -465,7 +482,10 @@ static int cmd_send(PROGRAMMER * pgm, struct avrpart * p, pgm->err_led(pgm, OFF); - pgm->cmd(pgm, cmd, res); + if (spi_mode) + pgm->spi(pgm, cmd, res, argc-1); + else + pgm->cmd(pgm, cmd, res); /* * display results @@ -724,6 +744,22 @@ static int cmd_help(PROGRAMMER * pgm, struct avrpart * p, return 0; } +static int cmd_spi(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 1); + spi_mode = 1; + return 0; +} + +static int cmd_pgm(PROGRAMMER * pgm, struct avrpart * p, + int argc, char * argv[]) +{ + pgm->setpin(pgm, pgm->pinno[PIN_AVR_RESET], 0); + spi_mode = 0; + pgm->initialize(pgm, p); + return 0; +} static int tokenize(char * s, char *** argv) {