* buspirate.c: Implemented reset= and speed= extended parameters.
* avrdude.1: Document the change. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@879 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
01f1430e8b
commit
d64741e5a2
|
@ -1,3 +1,8 @@
|
|||
2009-11-09 Michal Ludvig <mludvig@logix.net.nz>
|
||||
|
||||
* buspirate.c: Implemented reset= and speed= extended parameters.
|
||||
* avrdude.1: Document the change.
|
||||
|
||||
2009-11-04 Michal Ludvig <mludvig@logix.net.nz>
|
||||
|
||||
* configure.ac, Makefile.am: Test if GCC accepts -Wno-pointer-sign
|
||||
|
|
45
avrdude.1
45
avrdude.1
|
@ -111,10 +111,10 @@ The Arduino (which is very similar to the STK500 1.x) is supported via
|
|||
its own programmer type specification ``arduino''.
|
||||
.Pp
|
||||
The BusPirate is a versatile tool that can also be used as an AVR programmer.
|
||||
Older BusPirate firmwares are supported in ASCII mode, for newer
|
||||
firmwares (2.7+) avrdude automatically selects binary mode. Should there
|
||||
be a problem with the binary mode use '-x ascii' to prefer ascii
|
||||
mode with newer firmwares.
|
||||
A single BusPirate can be connected to up to 3 independent AVRs. See
|
||||
the section on
|
||||
.Em extended parameters
|
||||
below for details.
|
||||
.Pp
|
||||
Atmel's STK600 programmer is supported in ISP and high-voltage
|
||||
programming modes, and connects through the USB.
|
||||
|
@ -851,10 +851,45 @@ programmer creates errors during initial sequence.
|
|||
.El
|
||||
.It Ar buspirate
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar reset={cs,aux,aux2}
|
||||
The default setup assumes the BusPirate's CS output pin connected to
|
||||
the RESET pin on AVR side. It is however possible to have multiple AVRs
|
||||
connected to the same BP with MISO, MOSI and SCK lines common for all of them.
|
||||
In such a case one AVR should have its RESET connected to BusPirate's
|
||||
.Pa CS
|
||||
pin, second AVR's RESET connected to BusPirate's
|
||||
.Pa AUX
|
||||
pin and if your BusPirate has an
|
||||
.Pa AUX2
|
||||
pin (only available on BusPirate version v1a with firmware 3.0 or newer)
|
||||
use that to activate RESET on the third AVR.
|
||||
.Pp
|
||||
It may be a good idea to decouple the BusPirate and the AVR's SPI buses from
|
||||
each other using a 3-state bus buffer. For example 74HC125 or 74HC244 are some
|
||||
good candidates with the latches driven by the appropriate reset pin (cs,
|
||||
aux or aux2). Otherwise the SPI traffic in one active circuit may interfere
|
||||
with programming the AVR in the other design.
|
||||
.It Ar speed=<0..7>
|
||||
BusPirate to AVR SPI speed:
|
||||
.Bd -literal
|
||||
0 .. 30 kHz (default)
|
||||
1 .. 125 kHz
|
||||
2 .. 250 kHz
|
||||
3 .. 1 MHz
|
||||
4 .. 2 MHz
|
||||
5 .. 2.6 MHz
|
||||
6 .. 4 MHz
|
||||
7 .. 8 MHz
|
||||
.Ed
|
||||
.It Ar ascii
|
||||
Use ASCII mode even when the firmware supports BinMode (binary mode).
|
||||
BinMode is supported in firmware 2.7 and newer, older FW's either don't
|
||||
have BinMode or their BinMode is buggy.
|
||||
have BinMode or their BinMode is buggy. ASCII mode is slower and makes
|
||||
the above
|
||||
.Ar reset=
|
||||
and
|
||||
.Ar speed=
|
||||
parameters unavailable.
|
||||
.El
|
||||
.El
|
||||
.Sh FILES
|
||||
|
|
171
buspirate.c
171
buspirate.c
|
@ -46,20 +46,47 @@
|
|||
#include "serial.h"
|
||||
|
||||
/* ====== Private data structure ====== */
|
||||
/* CS and AUX pin bitmasks in
|
||||
* 0100wxyz – Configure peripherals command */
|
||||
#define BP_RESET_CS 0x01
|
||||
#define BP_RESET_AUX 0x02
|
||||
#define BP_RESET_AUX2 0x04
|
||||
|
||||
#define BP_FLAG_IN_BINMODE (1<<0)
|
||||
#define BP_FLAG_XPARM_FORCE_ASCII (1<<1)
|
||||
#define BP_FLAG_XPARM_RESET (1<<2)
|
||||
#define BP_FLAG_XPARM_SPIFREQ (1<<3)
|
||||
|
||||
struct pdata
|
||||
{
|
||||
char hw_version[10];
|
||||
int fw_version; /* = 100*fw_major + fw_minor */
|
||||
int binmode_version;
|
||||
int bin_spi_version;
|
||||
int in_binmode;
|
||||
int force_ascii;
|
||||
int current_peripherals_config;
|
||||
int spifreq; /* 0..7 - see buspirate manual for what freq each value means */
|
||||
int reset; /* See BP_RESET_* above */
|
||||
};
|
||||
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
|
||||
|
||||
/* Binary mode is available from firmware v2.7 on */
|
||||
#define FW_BINMODE_VER 207
|
||||
|
||||
/* ====== Feature checks ====== */
|
||||
static inline int
|
||||
buspirate_has_aux2(struct programmer_t *pgm)
|
||||
{
|
||||
return ((PDATA(pgm)->fw_version >= 300) &&
|
||||
strcmp(PDATA(pgm)->hw_version, "v1a") == 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
buspirate_uses_ascii(struct programmer_t *pgm)
|
||||
{
|
||||
return (pgm->flag & BP_FLAG_XPARM_FORCE_ASCII) ||
|
||||
(PDATA(pgm)->fw_version < FW_BINMODE_VER);
|
||||
}
|
||||
|
||||
/* ====== Serial talker functions - binmode ====== */
|
||||
|
||||
static void dump_mem(unsigned char *buf, size_t len)
|
||||
|
@ -113,7 +140,7 @@ static int buspirate_expect_bin(struct programmer_t *pgm,
|
|||
char *expect_data, size_t expect_len)
|
||||
{
|
||||
char *recv_buf = alloca(expect_len);
|
||||
if (!PDATA(pgm)->in_binmode) {
|
||||
if (!pgm->flag & BP_FLAG_IN_BINMODE) {
|
||||
fprintf(stderr, "BusPirate: Internal error: buspirate_send_bin() called from ascii mode");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -138,7 +165,7 @@ static int buspirate_getc(struct programmer_t *pgm)
|
|||
int rc;
|
||||
unsigned char ch = 0;
|
||||
|
||||
if (PDATA(pgm)->in_binmode) {
|
||||
if (pgm->flag & BP_FLAG_IN_BINMODE) {
|
||||
fprintf(stderr, "BusPirate: Internal error: buspirate_getc() called from binmode");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -197,7 +224,7 @@ static int buspirate_send(struct programmer_t *pgm, char *str)
|
|||
if (verbose)
|
||||
fprintf(stderr, "%s: buspirate_send(): %s", progname, str);
|
||||
|
||||
if (PDATA(pgm)->in_binmode) {
|
||||
if (pgm->flag & BP_FLAG_IN_BINMODE) {
|
||||
fprintf(stderr, "BusPirate: Internal error: buspirate_send() called from binmode");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -244,6 +271,85 @@ static void buspirate_dummy_6(struct programmer_t *pgm,
|
|||
{
|
||||
}
|
||||
|
||||
/* ====== Config / parameters handling functions ====== */
|
||||
static int
|
||||
buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
|
||||
{
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
char reset[10];
|
||||
char *preset = reset; /* for strtok() */
|
||||
int spifreq;
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
if (strcmp(extended_param, "ascii") == 0) {
|
||||
pgm->flag |= BP_FLAG_XPARM_FORCE_ASCII;
|
||||
continue;
|
||||
}
|
||||
if (sscanf(extended_param, "spifreq=%d", &spifreq) == 1) {
|
||||
if (spifreq & (~0x07)) {
|
||||
fprintf(stderr, "BusPirate: spifreq must be between 0 and 7.\n");
|
||||
fprintf(stderr, "BusPirate: see BusPirate manual for details.\n");
|
||||
return -1;
|
||||
}
|
||||
PDATA(pgm)->spifreq = spifreq;
|
||||
pgm->flag |= BP_FLAG_XPARM_SPIFREQ;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sscanf(extended_param, "reset=%s", reset) == 1) {
|
||||
char *resetpin;
|
||||
while ((resetpin = strtok(preset, ","))) {
|
||||
preset = NULL; /* for subsequent strtok() calls */
|
||||
if (strcasecmp(resetpin, "cs") == 0)
|
||||
PDATA(pgm)->reset |= BP_RESET_CS;
|
||||
else if (strcasecmp(resetpin, "aux") == 0 || strcasecmp(reset, "aux1") == 0)
|
||||
PDATA(pgm)->reset |= BP_RESET_AUX;
|
||||
else if (strcasecmp(resetpin, "aux2") == 0)
|
||||
PDATA(pgm)->reset |= BP_RESET_AUX2;
|
||||
else {
|
||||
fprintf(stderr, "BusPirate: reset must be either CS or AUX.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
pgm->flag |= BP_FLAG_XPARM_RESET;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
buspirate_verifyconfig(struct programmer_t *pgm)
|
||||
{
|
||||
/* Default reset pin is CS */
|
||||
if (PDATA(pgm)->reset == 0x00)
|
||||
PDATA(pgm)->reset |= BP_RESET_CS;
|
||||
|
||||
/* reset=AUX2 is only available on HW=v1a and FW>=3.0 */
|
||||
if ((PDATA(pgm)->reset & BP_RESET_AUX2) && !buspirate_has_aux2(pgm)) {
|
||||
fprintf(stderr, "BusPirate: Pin AUX2 is only available in binary mode\n");
|
||||
fprintf(stderr, "BusPirate: with hardware==v1a && firmware>=3.0\n");
|
||||
fprintf(stderr, "BusPirate: Your hardware==%s and firmware==%d.%d\n",
|
||||
PDATA(pgm)->hw_version, PDATA(pgm)->fw_version/100, PDATA(pgm)->fw_version%100);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((PDATA(pgm)->reset != BP_RESET_CS) && buspirate_uses_ascii(pgm)) {
|
||||
fprintf(stderr, "BusPirate: RESET pin other than CS is not supported in ASCII mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((pgm->flag & BP_FLAG_XPARM_SPIFREQ) && buspirate_uses_ascii(pgm)) {
|
||||
fprintf(stderr, "BusPirate: SPI speed selection is not supported in ASCII mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ====== Programmer methods ======= */
|
||||
static int buspirate_open(struct programmer_t *pgm, char * port)
|
||||
{
|
||||
|
@ -276,7 +382,7 @@ static void buspirate_reset_from_binmode(struct programmer_t *pgm)
|
|||
buf[0] = 0x0F; /* BinMode: reset */
|
||||
buspirate_send_bin(pgm, buf, 1);
|
||||
|
||||
PDATA(pgm)->in_binmode = 0;
|
||||
pgm->flag &= ~BP_FLAG_IN_BINMODE;
|
||||
while(1) {
|
||||
buspirate_readline(pgm, buf, sizeof(buf) - 1);
|
||||
if (buspirate_is_prompt(buf))
|
||||
|
@ -304,7 +410,7 @@ static int buspirate_start_spi_mode_bin(struct programmer_t *pgm)
|
|||
if (verbose)
|
||||
printf("BusPirate binmode version: %d\n", PDATA(pgm)->binmode_version);
|
||||
|
||||
PDATA(pgm)->in_binmode = 1;
|
||||
pgm->flag |= BP_FLAG_IN_BINMODE;
|
||||
|
||||
/* == Enter SPI mode == */
|
||||
buf[0] = 0x01; /* Enter raw SPI mode */
|
||||
|
@ -319,16 +425,21 @@ static int buspirate_start_spi_mode_bin(struct programmer_t *pgm)
|
|||
if (verbose)
|
||||
printf("BusPirate SPI version: %d\n", PDATA(pgm)->bin_spi_version);
|
||||
|
||||
/* 0b0100wxyz – Configure peripherals w=power, x=pull-ups, y=AUX, z=CS
|
||||
* we want power and CS -- 0b01001001 = 0x49 */
|
||||
buspirate_expect_bin_byte(pgm, 0x49, 0x01);
|
||||
/* 0b0100wxyz – Configure peripherals w=power, x=pull-ups/aux2, y=AUX, z=CS
|
||||
* we want power (0x48) and all reset pins high. */
|
||||
PDATA(pgm)->current_peripherals_config = 0x48;
|
||||
PDATA(pgm)->current_peripherals_config |= BP_RESET_CS;
|
||||
PDATA(pgm)->current_peripherals_config |= BP_RESET_AUX;
|
||||
if (buspirate_has_aux2(pgm))
|
||||
PDATA(pgm)->current_peripherals_config |= BP_RESET_AUX2;
|
||||
buspirate_expect_bin_byte(pgm, PDATA(pgm)->current_peripherals_config, 0x01);
|
||||
usleep(50000); // sleep for 50ms after power up
|
||||
|
||||
/* 01100xxx - SPI speed
|
||||
* xxx = 000=30kHz, 001=125kHz, 010=250kHz, 011=1MHz,
|
||||
* 100=2MHz, 101=2.6MHz, 110=4MHz, 111=8MHz
|
||||
* use 30kHz = 0x60 */
|
||||
buspirate_expect_bin_byte(pgm, 0x60, 0x01);
|
||||
buspirate_expect_bin_byte(pgm, 0x60 | PDATA(pgm)->spifreq, 0x01);
|
||||
|
||||
/* 1000wxyz – SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample
|
||||
* we want: 3.3V(1), idle low(0), data change on trailing edge (1),
|
||||
|
@ -417,14 +528,15 @@ static void buspirate_enable(struct programmer_t *pgm)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
printf("BusPirate: firmware %d.%d\n", fw_v1, fw_v2);
|
||||
if (buspirate_verifyconfig(pgm) < 0)
|
||||
exit(1);
|
||||
|
||||
if (PDATA(pgm)->fw_version >= FW_BINMODE_VER && !PDATA(pgm)->force_ascii) {
|
||||
if (PDATA(pgm)->fw_version >= FW_BINMODE_VER && !(pgm->flag & BP_FLAG_XPARM_FORCE_ASCII)) {
|
||||
printf("BusPirate: using BINARY mode\n");
|
||||
if (buspirate_start_spi_mode_bin(pgm) < 0)
|
||||
fprintf(stderr, "%s: Failed to start binary SPI mode\n", progname);
|
||||
}
|
||||
if (! PDATA(pgm)->in_binmode) {
|
||||
if (!pgm->flag & BP_FLAG_IN_BINMODE) {
|
||||
printf("BusPirate: using ASCII mode\n");
|
||||
if (buspirate_start_spi_mode_ascii(pgm) < 0) {
|
||||
fprintf(stderr, "%s: Failed to start ascii SPI mode\n", progname);
|
||||
|
@ -435,7 +547,7 @@ static void buspirate_enable(struct programmer_t *pgm)
|
|||
|
||||
static void buspirate_disable(struct programmer_t *pgm)
|
||||
{
|
||||
if (PDATA(pgm)->in_binmode)
|
||||
if (pgm->flag & BP_FLAG_IN_BINMODE)
|
||||
buspirate_reset_from_binmode(pgm);
|
||||
else
|
||||
buspirate_expect(pgm, "#\n", "RESET", 1);
|
||||
|
@ -450,7 +562,7 @@ static int buspirate_initialize(struct programmer_t *pgm, AVRPART * p)
|
|||
|
||||
static void buspirate_powerup(struct programmer_t *pgm)
|
||||
{
|
||||
if (PDATA(pgm)->in_binmode) {
|
||||
if (pgm->flag & BP_FLAG_IN_BINMODE) {
|
||||
/* Powerup in BinMode is handled in SPI init */
|
||||
return;
|
||||
} else
|
||||
|
@ -463,7 +575,7 @@ static void buspirate_powerup(struct programmer_t *pgm)
|
|||
|
||||
static void buspirate_powerdown(struct programmer_t *pgm)
|
||||
{
|
||||
if (PDATA(pgm)->in_binmode) {
|
||||
if (pgm->flag & BP_FLAG_IN_BINMODE) {
|
||||
/* 0b0100wxyz – Configure peripherals w=power, x=pull-ups, y=AUX, z=CS
|
||||
* we want everything off -- 0b01000000 = 0x40 */
|
||||
if (buspirate_expect_bin_byte(pgm, 0x40, 0x01))
|
||||
|
@ -527,7 +639,7 @@ static int buspirate_cmd(struct programmer_t *pgm,
|
|||
unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
if (PDATA(pgm)->in_binmode)
|
||||
if (pgm->flag & BP_FLAG_IN_BINMODE)
|
||||
return buspirate_cmd_bin(pgm, cmd, res);
|
||||
else
|
||||
return buspirate_cmd_ascii(pgm, cmd, res);
|
||||
|
@ -538,10 +650,11 @@ static int buspirate_program_enable(struct programmer_t *pgm, AVRPART * p)
|
|||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
|
||||
if (PDATA(pgm)->in_binmode)
|
||||
/* 0000001x – CS high (1) or low (0)
|
||||
* we want CS low -> 0x02 */
|
||||
buspirate_expect_bin_byte(pgm, 0x02, 0x01);
|
||||
if (pgm->flag & BP_FLAG_IN_BINMODE) {
|
||||
/* Clear configured reset pin(s): CS and/or AUX and/or AUX2 */
|
||||
PDATA(pgm)->current_peripherals_config &= ~PDATA(pgm)->reset;
|
||||
buspirate_expect_bin_byte(pgm, PDATA(pgm)->current_peripherals_config, 0x01);
|
||||
}
|
||||
else
|
||||
buspirate_expect(pgm, "{\n", "CS ENABLED", 1);
|
||||
|
||||
|
@ -588,20 +701,6 @@ static int buspirate_chip_erase(struct programmer_t *pgm, AVRPART * p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
|
||||
{
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
if (strcmp(extended_param, "ascii") == 0)
|
||||
PDATA(pgm)->force_ascii = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void buspirate_initpgm(struct programmer_t *pgm)
|
||||
{
|
||||
strcpy(pgm->type, "BusPirate");
|
||||
|
|
Loading…
Reference in New Issue