patch #8504 buspirate: Also support "cpufreq" extended parameter in binary mode

* buspirate.c: applied patch + switch off at disable (even when
a reset follows) + some general whitespace/tab cleanup

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1339 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
rliebscher 2014-11-13 13:53:47 +00:00
parent 7248d0ad5e
commit e88899e0a2
4 changed files with 128 additions and 69 deletions

View File

@ -1,3 +1,10 @@
2014-11-13 Rene Liebscher <R.Liebscher@gmx.de>
patch #8504 buspirate: Also support "cpufreq" extended parameter
in binary mode
* buspirate.c: applied patch + switch off at disable (even when
a reset follows) + some general whitespace/tab cleanup
2014-10-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #37441: lockbits in ATxmega + avrdude = problem

View File

@ -1001,9 +1001,7 @@ This sets the AUX pin to output a frequency of
kHz. Connecting
the AUX pin to the XTAL1 pin of your MCU, you can provide it a clock,
for example when it needs an external clock because of wrong fuses settings.
This setting is only available in ASCII mode. (The lower limit was chosen so
the CPU frequency is at least for four times the SPI frequency which is in
ASCII mode 30kHz.)
Make sure the CPU frequency is at least four times the SPI frequency.
.It Ar serial_recv_timeout=<1...>
This sets the serial receive timeout to the given value.
The timeout happens every time avrdude waits for the BusPirate prompt.

View File

@ -74,7 +74,7 @@ struct pdata
int current_peripherals_config;
int spifreq; /* For "set speed" commands */
int cpufreq; /* (125)..4000 kHz - see buspirate manual */
int serial_recv_timeout; /* timeout in ms, default 100 */
int serial_recv_timeout; /* timeout in ms, default 100 */
int reset; /* See BP_RESET_* above */
unsigned char pin_dir; /* Last written pin direction for bitbang mode */
unsigned char pin_val; /* Last written pin values for bitbang mode */
@ -204,8 +204,8 @@ static char *buspirate_readline_noexit(struct programmer_t *pgm, char *buf, size
}
serial_recv_timeout = orig_serial_recv_timeout;
avrdude_message(MSG_DEBUG, "%s: buspirate_readline(): %s%s",
progname, buf,
buf[strlen(buf) - 1] == '\n' ? "" : "\n");
progname, buf,
buf[strlen(buf) - 1] == '\n' ? "" : "\n");
if (! buf[0])
return NULL;
@ -227,8 +227,9 @@ static char *buspirate_readline(struct programmer_t *pgm, char *buf, size_t len)
static int buspirate_send(struct programmer_t *pgm, const char *str)
{
int rc;
const char * readline;
avrdude_message(MSG_DEBUG, "%s: buspirate_send(): %s", progname, str);
avrdude_message(MSG_DEBUG, "%s: buspirate_send(): %s", progname, str);
if (pgm->flag & BP_FLAG_IN_BINMODE) {
avrdude_message(MSG_INFO, "BusPirate: Internal error: buspirate_send() called from binmode\n");
@ -238,9 +239,13 @@ static int buspirate_send(struct programmer_t *pgm, const char *str)
rc = serial_send(&pgm->fd, (const unsigned char*)str, strlen(str));
if (rc)
return rc;
while (strcmp(buspirate_readline(pgm, NULL, 0), str) != 0)
/* keep reading until we get what we sent there */
;
do {
readline = buspirate_readline(pgm, NULL, 0);
if (readline == NULL)
return -1;
/* keep reading until we get what we sent there */
} while (strcmp(readline, str) != 0);
/* by now we should be in sync */
return 0;
}
@ -263,7 +268,9 @@ static int buspirate_expect(struct programmer_t *pgm, char *send,
buspirate_send(pgm, send);
while (1) {
rcvd = buspirate_readline(pgm, NULL, 0);
if (rcvd == NULL) {
return -1;
}
if (strncmp(rcvd, expect, expect_len) == 0) {
if (! wait_for_prompt) {
serial_drain(&pgm->fd, 0);
@ -280,8 +287,7 @@ static int buspirate_expect(struct programmer_t *pgm, char *send,
}
/* ====== Do-nothing functions ====== */
static void buspirate_dummy_6(struct programmer_t *pgm,
const char *p)
static void buspirate_dummy_6(struct programmer_t *pgm, const char *p)
{
}
@ -292,9 +298,10 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
LNODEID ln;
const char *extended_param;
char reset[10];
char *preset = reset; /* for strtok() */
int spifreq;
int cpufreq;
char *preset = reset; /* for strtok() */
unsigned int spifreq;
unsigned int rawfreq;
unsigned int cpufreq;
int serial_recv_timeout;
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
@ -303,32 +310,38 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
pgm->flag |= BP_FLAG_XPARM_FORCE_ASCII;
continue;
}
if (sscanf(extended_param, "spifreq=%d", &spifreq) == 1) {
if (sscanf(extended_param, "spifreq=%u", &spifreq) == 1) {
if (spifreq & (~0x07)) {
avrdude_message(MSG_INFO, "BusPirate: spifreq must be between 0 and 7.\n");
avrdude_message(MSG_INFO, "BusPirate: see BusPirate manual for details.\n");
return -1;
}
pgm->flag = (pgm->flag & ~BP_FLAG_XPARM_RAWFREQ) |
BP_FLAG_XPARM_SPIFREQ;
if (pgm->flag & BP_FLAG_XPARM_RAWFREQ) {
avrdude_message(MSG_INFO, "BusPirate: set either spifreq or rawfreq\n");
return -1;
}
pgm->flag |= BP_FLAG_XPARM_SPIFREQ;
PDATA(pgm)->spifreq = spifreq;
continue;
}
unsigned rawfreq;
if (sscanf(extended_param, "rawfreq=%u", &rawfreq) == 1) {
if (rawfreq >= 4) {
avrdude_message(MSG_INFO, "BusPirate: rawfreq must be "
"between 0 and 3.\n");
"between 0 and 3.\n");
return -1;
}
pgm->flag = (pgm->flag & ~BP_FLAG_XPARM_SPIFREQ) |
BP_FLAG_XPARM_RAWFREQ;
if (pgm->flag & BP_FLAG_XPARM_SPIFREQ) {
avrdude_message(MSG_INFO, "BusPirate: set either spifreq or rawfreq\n");
return -1;
}
pgm->flag |= BP_FLAG_XPARM_RAWFREQ;
PDATA(pgm)->spifreq = rawfreq;
continue;
}
if (sscanf(extended_param, "cpufreq=%d", &cpufreq) == 1) {
if (sscanf(extended_param, "cpufreq=%u", &cpufreq) == 1) {
/* lower limit comes from 'cpufreq > 4 * spifreq', spifreq in ascii mode is 30kHz. */
if (cpufreq < 125 || cpufreq > 4000) {
avrdude_message(MSG_INFO, "BusPirate: cpufreq must be between 125 and 4000 kHz.\n");
@ -343,7 +356,7 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
if (sscanf(extended_param, "reset=%9s", reset) == 1) {
char *resetpin;
while ((resetpin = strtok(preset, ","))) {
preset = NULL; /* for subsequent strtok() calls */
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)
@ -368,6 +381,7 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
pgm->flag |= BP_FLAG_NOPAGEDREAD;
continue;
}
if (sscanf(extended_param, "serial_recv_timeout=%d", &serial_recv_timeout) == 1) {
if (serial_recv_timeout < 1) {
avrdude_message(MSG_INFO, "BusPirate: serial_recv_timeout must be greater 0.\n");
@ -376,6 +390,9 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
PDATA(pgm)->serial_recv_timeout = serial_recv_timeout;
continue;
}
avrdude_message(MSG_INFO, "BusPirate: do not understand extended param '%s'.\n", extended_param);
return -1;
}
return 0;
@ -393,17 +410,12 @@ buspirate_verifyconfig(struct programmer_t *pgm)
return -1;
}
if (( (pgm->flag & BP_FLAG_XPARM_SPIFREQ) ||
(pgm->flag & BP_FLAG_XPARM_RAWFREQ) ) && buspirate_uses_ascii(pgm)) {
if ( ((pgm->flag & BP_FLAG_XPARM_SPIFREQ) || (pgm->flag & BP_FLAG_XPARM_RAWFREQ))
&& buspirate_uses_ascii(pgm)) {
avrdude_message(MSG_INFO, "BusPirate: SPI speed selection is not supported in ASCII mode\n");
return -1;
}
if ((pgm->flag & BP_FLAG_XPARM_CPUFREQ) && !buspirate_uses_ascii(pgm)) {
avrdude_message(MSG_INFO, "BusPirate: Setting cpufreq is only supported in ASCII mode\n");
return -1;
}
return 0;
}
@ -418,7 +430,7 @@ static int buspirate_open(struct programmer_t *pgm, char * port)
pinfo.baud = pgm->baudrate;
strcpy(pgm->port, port);
if (serial_open(port, pinfo, &pgm->fd)==-1) {
return -1;
return -1;
}
/* drain any extraneous input */
@ -437,8 +449,21 @@ static void buspirate_reset_from_binmode(struct programmer_t *pgm)
{
unsigned char buf[10];
buf[0] = 0x00; /* BinMode: revert to HiZ */
buf[0] = 0x00; /* BinMode: revert to raw bitbang mode */
buspirate_send_bin(pgm, buf, 1);
buspirate_recv_bin(pgm, buf, 5);
if (pgm->flag & BP_FLAG_XPARM_CPUFREQ) {
/* disable pwm */
if (buspirate_expect_bin_byte(pgm, 0x13, 0x01) != 1) {
avrdude_message(MSG_INFO, "%s: warning: did not get a response to stop PWM command.\n", progname);
}
}
/* 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, 0x00) == 1) {
avrdude_message(MSG_INFO, "%s: warning: did not get a response to power off command.\n", progname);
}
buf[0] = 0x0F; /* BinMode: reset */
buspirate_send_bin(pgm, buf, 1);
@ -463,7 +488,7 @@ static void buspirate_reset_from_binmode(struct programmer_t *pgm)
return;
}
avrdude_message(MSG_NOTICE, "BusPirate is back in the text mode\n");
avrdude_message(MSG_NOTICE, "BusPirate is back in the text mode\n");
}
static int buspirate_start_mode_bin(struct programmer_t *pgm)
@ -474,6 +499,7 @@ static int buspirate_start_mode_bin(struct programmer_t *pgm)
const char *entered_format; /* Response, for "scanf" */
char config; /* Command to setup submode parameters */
} *submode;
if (pgm->flag & BP_FLAG_XPARM_RAWFREQ) {
submode = &(const struct submode){
.name = "Raw-wire",
@ -516,20 +542,42 @@ static int buspirate_start_mode_bin(struct programmer_t *pgm)
pgm->flag |= BP_FLAG_IN_BINMODE;
if (pgm->flag & BP_FLAG_XPARM_CPUFREQ) {
unsigned short pwm_duty;
unsigned short pwm_period;
pwm_period = 16000/(PDATA(pgm)->cpufreq) - 1; // oscillator runs at 32MHz, we don't use a prescaler
pwm_duty = pwm_period/2; // 50% duty cycle
avrdude_message(MSG_NOTICE, "Setting up PWM for cpufreq\n");
avrdude_message(MSG_DEBUG, "PWM settings: Prescaler=1, Duty Cycle=%hd, Period=%hd\n", pwm_duty, pwm_period);
buf[0] = 0x12; // pwm setup
buf[1] = 0; // prescaler 1
buf[2] = (char) ((pwm_duty >> 8) & 0xff); // duty cycle register, high byte
buf[3] = (char) pwm_duty & 0xff; // duty cycle register, low byte
buf[4] = (char) ((pwm_period >> 8) & 0xff); // period register, high byte
buf[5] = (char) pwm_period & 0xff; // period register, low byte
buspirate_send_bin(pgm, buf, 6);
buspirate_recv_bin(pgm, buf, 1);
if (buf[0] != 0x01)
avrdude_message(MSG_INFO, "cpufreq (PWM) setup failed\n");
}
/* == Set protocol sub-mode of binary mode == */
buf[0] = submode->enter;
buspirate_send_bin(pgm, buf, 1);
memset(buf, 0, sizeof(buf));
buspirate_recv_bin(pgm, buf, 4);
if (sscanf((const char*)buf, submode->entered_format,
&PDATA(pgm)->submode_version) != 1) {
if (sscanf((const char*)buf, submode->entered_format, &PDATA(pgm)->submode_version) != 1) {
avrdude_message(MSG_INFO, "%s mode not confirmed: '%s'\n",
submode->name, buf);
submode->name, buf);
buspirate_reset_from_binmode(pgm);
return -1;
}
avrdude_message(MSG_NOTICE, "BusPirate %s version: %d\n",
submode->name, PDATA(pgm)->submode_version);
submode->name, PDATA(pgm)->submode_version);
if (pgm->flag & BP_FLAG_NOPAGEDWRITE) {
avrdude_message(MSG_NOTICE, "%s: Paged flash write disabled.\n", progname);
@ -549,12 +597,12 @@ static int buspirate_start_mode_bin(struct programmer_t *pgm)
buf[0] = 0x1;
buspirate_send_bin(pgm, buf, 1);
avrdude_message(MSG_NOTICE, "%s: Disabling paged flash write. (Need BusPirate firmware >=v5.10.)\n", progname);
avrdude_message(MSG_NOTICE, "%s: Disabling paged flash write. (Need BusPirate firmware >=v5.10.)\n", progname);
/* Flush serial buffer: */
serial_drain(&pgm->fd, 0);
} else {
avrdude_message(MSG_INFO, "%s: Paged flash write enabled.\n", progname);
avrdude_message(MSG_INFO, "%s: Paged flash write enabled.\n", progname);
}
}
@ -563,7 +611,7 @@ static int buspirate_start_mode_bin(struct programmer_t *pgm)
PDATA(pgm)->current_peripherals_config = 0x48 | PDATA(pgm)->reset;
if (buspirate_expect_bin_byte(pgm, PDATA(pgm)->current_peripherals_config, 0x01) < 0)
return -1;
usleep(50000); // sleep for 50ms after power up
usleep(50000); // sleep for 50ms after power up
/* 01100xxx - Set speed */
if (buspirate_expect_bin_byte(pgm, 0x60 | PDATA(pgm)->spifreq, 0x01) < 0)
@ -609,6 +657,9 @@ static int buspirate_start_spi_mode_ascii(struct programmer_t *pgm)
buspirate_send(pgm, "m\n");
while(1) {
rcvd = buspirate_readline(pgm, NULL, 0);
if (rcvd == NULL) {
return -1;
}
if (spi_cmd == -1 && sscanf(rcvd, "%2d. %10s", &cmd, mode)) {
if (strcmp(mode, "SPI") == 0)
spi_cmd = cmd;
@ -628,6 +679,9 @@ static int buspirate_start_spi_mode_ascii(struct programmer_t *pgm)
buf[0] = '\0';
while (1) {
rcvd = buspirate_readline(pgm, NULL, 0);
if (rcvd == NULL) {
return -1;
}
if (strstr(rcvd, "Normal (H=3.3V, L=GND)")) {
/* BP firmware 2.1 defaults to Open-drain output.
* That doesn't work on my board, even with pull-up
@ -724,8 +778,9 @@ static void buspirate_disable(struct programmer_t *pgm)
if (pgm->flag & BP_FLAG_IN_BINMODE) {
serial_recv_timeout = 100;
buspirate_reset_from_binmode(pgm);
} else
} else {
buspirate_expect(pgm, "#\n", "RESET", 1);
}
}
static int buspirate_initialize(struct programmer_t *pgm, AVRPART * p)
@ -741,7 +796,7 @@ static void buspirate_powerup(struct programmer_t *pgm)
/* Powerup in BinMode is handled in binary mode init */
return;
} else {
if (buspirate_expect(pgm, "W\n", "Power supplies ON", 1)) {
if (buspirate_expect(pgm, "W\n", "POWER SUPPLIES ON", 1)) {
if (pgm->flag & BP_FLAG_XPARM_CPUFREQ) {
char buf[25];
int ok = 0;
@ -768,17 +823,15 @@ static void buspirate_powerup(struct programmer_t *pgm)
static void buspirate_powerdown(struct programmer_t *pgm)
{
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))
return;
/* Powerdown in BinMode is handled in binary mode init */
return;
} else {
if (pgm->flag & BP_FLAG_XPARM_CPUFREQ) {
if (!buspirate_expect(pgm, "g\n", "PWM disabled", 1)) {
avrdude_message(MSG_INFO, "%s: warning: did not get a response to stop PWM command.\n", progname);
}
}
if (buspirate_expect(pgm, "w\n", "Power supplies OFF", 1))
if (buspirate_expect(pgm, "w\n", "POWER SUPPLIES OFF", 1))
return;
}
@ -816,6 +869,9 @@ static int buspirate_cmd_ascii(struct programmer_t *pgm,
buspirate_send(pgm, buf);
while (i < 4) {
rcvd = buspirate_readline(pgm, NULL, 0);
if (rcvd == NULL) {
return -1;
}
/* WRITE: 0xAC READ: 0x04 */
if (sscanf(rcvd, "WRITE: 0x%2x READ: 0x%2x", &spi_write, &spi_read) == 2) {
res[i++] = spi_read;
@ -941,12 +997,12 @@ static int buspirate_paged_write(struct programmer_t *pgm,
/* pre-check opcodes */
if (m->op[AVR_OP_LOADPAGE_LO] == NULL) {
avrdude_message(MSG_INFO, "%s failure: %s command not defined for %s\n",
progname, "AVR_OP_LOADPAGE_LO", p->desc);
progname, "AVR_OP_LOADPAGE_LO", p->desc);
return -1;
}
if (m->op[AVR_OP_LOADPAGE_HI] == NULL) {
avrdude_message(MSG_INFO, "%s failure: %s command not defined for %s\n",
progname, "AVR_OP_LOADPAGE_HI", p->desc);
progname, "AVR_OP_LOADPAGE_HI", p->desc);
return -1;
}
@ -1038,7 +1094,7 @@ static int buspirate_program_enable(struct programmer_t *pgm, AVRPART * p)
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
avrdude_message(MSG_INFO, "program enable instruction not defined for part \"%s\"\n",
p->desc);
p->desc);
return -1;
}
@ -1059,7 +1115,7 @@ static int buspirate_chip_erase(struct programmer_t *pgm, AVRPART * p)
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
avrdude_message(MSG_INFO, "chip erase instruction not defined for part \"%s\"\n",
p->desc);
p->desc);
return -1;
}
@ -1083,7 +1139,7 @@ static void buspirate_setup(struct programmer_t *pgm)
/* Allocate private data */
if ((pgm->cookie = calloc(1, sizeof(struct pdata))) == 0) {
avrdude_message(MSG_INFO, "%s: buspirate_initpgm(): Out of memory allocating private data\n",
progname);
progname);
exit(1);
}
PDATA(pgm)->serial_recv_timeout = 100;
@ -1134,7 +1190,7 @@ static void buspirate_bb_enable(struct programmer_t *pgm)
unsigned char buf[20] = { '\0' };
if (bitbang_check_prerequisites(pgm) < 0)
return; /* XXX should treat as error */
return; /* XXX should treat as error */
avrdude_message(MSG_INFO, "Attempting to initiate BusPirate bitbang binary mode...\n");
@ -1156,7 +1212,7 @@ static void buspirate_bb_enable(struct programmer_t *pgm)
return;
}
avrdude_message(MSG_INFO, "BusPirate binmode version: %d\n",
PDATA(pgm)->binmode_version);
PDATA(pgm)->binmode_version);
pgm->flag |= BP_FLAG_IN_BINMODE;

View File

@ -858,9 +858,7 @@ reason, this option disables it.
This sets the @emph{AUX} pin to output a frequency of @var{n} kHz. Connecting
the @emph{AUX} pin to the XTAL1 pin of your MCU, you can provide it a clock,
for example when it needs an external clock because of wrong fuses settings.
This setting is only available in ASCII mode. (The lower limit was chosen so
the CPU frequency is at least for four times the SPI frequency which is in
ASCII mode 30kHz.)
Make sure the CPU frequency is at least four times the SPI frequency.
@item @samp{serial_recv_timeout=@var{1...}}
This sets the serial receive timeout to the given value.