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:
Rene Liebscher 2014-11-13 13:53:47 +00:00
parent 83ff6d306d
commit 58f509cb54
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> 2014-10-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #37441: lockbits in ATxmega + avrdude = problem 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 kHz. Connecting
the AUX pin to the XTAL1 pin of your MCU, you can provide it a clock, 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. 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 Make sure the CPU frequency is at least four times the SPI frequency.
the CPU frequency is at least for four times the SPI frequency which is in
ASCII mode 30kHz.)
.It Ar serial_recv_timeout=<1...> .It Ar serial_recv_timeout=<1...>
This sets the serial receive timeout to the given value. This sets the serial receive timeout to the given value.
The timeout happens every time avrdude waits for the BusPirate prompt. The timeout happens every time avrdude waits for the BusPirate prompt.

View File

@ -227,6 +227,7 @@ static char *buspirate_readline(struct programmer_t *pgm, char *buf, size_t len)
static int buspirate_send(struct programmer_t *pgm, const char *str) static int buspirate_send(struct programmer_t *pgm, const char *str)
{ {
int rc; 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);
@ -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)); rc = serial_send(&pgm->fd, (const unsigned char*)str, strlen(str));
if (rc) if (rc)
return rc; return rc;
while (strcmp(buspirate_readline(pgm, NULL, 0), str) != 0) do {
readline = buspirate_readline(pgm, NULL, 0);
if (readline == NULL)
return -1;
/* keep reading until we get what we sent there */ /* keep reading until we get what we sent there */
; } while (strcmp(readline, str) != 0);
/* by now we should be in sync */ /* by now we should be in sync */
return 0; return 0;
} }
@ -263,7 +268,9 @@ static int buspirate_expect(struct programmer_t *pgm, char *send,
buspirate_send(pgm, send); buspirate_send(pgm, send);
while (1) { while (1) {
rcvd = buspirate_readline(pgm, NULL, 0); rcvd = buspirate_readline(pgm, NULL, 0);
if (rcvd == NULL) {
return -1;
}
if (strncmp(rcvd, expect, expect_len) == 0) { if (strncmp(rcvd, expect, expect_len) == 0) {
if (! wait_for_prompt) { if (! wait_for_prompt) {
serial_drain(&pgm->fd, 0); serial_drain(&pgm->fd, 0);
@ -280,8 +287,7 @@ static int buspirate_expect(struct programmer_t *pgm, char *send,
} }
/* ====== Do-nothing functions ====== */ /* ====== Do-nothing functions ====== */
static void buspirate_dummy_6(struct programmer_t *pgm, static void buspirate_dummy_6(struct programmer_t *pgm, const char *p)
const char *p)
{ {
} }
@ -293,8 +299,9 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
const char *extended_param; const char *extended_param;
char reset[10]; char reset[10];
char *preset = reset; /* for strtok() */ char *preset = reset; /* for strtok() */
int spifreq; unsigned int spifreq;
int cpufreq; unsigned int rawfreq;
unsigned int cpufreq;
int serial_recv_timeout; int serial_recv_timeout;
for (ln = lfirst(extparms); ln; ln = lnext(ln)) { 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; pgm->flag |= BP_FLAG_XPARM_FORCE_ASCII;
continue; continue;
} }
if (sscanf(extended_param, "spifreq=%d", &spifreq) == 1) {
if (sscanf(extended_param, "spifreq=%u", &spifreq) == 1) {
if (spifreq & (~0x07)) { if (spifreq & (~0x07)) {
avrdude_message(MSG_INFO, "BusPirate: spifreq must be between 0 and 7.\n"); avrdude_message(MSG_INFO, "BusPirate: spifreq must be between 0 and 7.\n");
avrdude_message(MSG_INFO, "BusPirate: see BusPirate manual for details.\n"); avrdude_message(MSG_INFO, "BusPirate: see BusPirate manual for details.\n");
return -1; return -1;
} }
pgm->flag = (pgm->flag & ~BP_FLAG_XPARM_RAWFREQ) | if (pgm->flag & BP_FLAG_XPARM_RAWFREQ) {
BP_FLAG_XPARM_SPIFREQ; avrdude_message(MSG_INFO, "BusPirate: set either spifreq or rawfreq\n");
return -1;
}
pgm->flag |= BP_FLAG_XPARM_SPIFREQ;
PDATA(pgm)->spifreq = spifreq; PDATA(pgm)->spifreq = spifreq;
continue; continue;
} }
unsigned rawfreq;
if (sscanf(extended_param, "rawfreq=%u", &rawfreq) == 1) { if (sscanf(extended_param, "rawfreq=%u", &rawfreq) == 1) {
if (rawfreq >= 4) { if (rawfreq >= 4) {
avrdude_message(MSG_INFO, "BusPirate: rawfreq must be " avrdude_message(MSG_INFO, "BusPirate: rawfreq must be "
"between 0 and 3.\n"); "between 0 and 3.\n");
return -1; return -1;
} }
pgm->flag = (pgm->flag & ~BP_FLAG_XPARM_SPIFREQ) | if (pgm->flag & BP_FLAG_XPARM_SPIFREQ) {
BP_FLAG_XPARM_RAWFREQ; avrdude_message(MSG_INFO, "BusPirate: set either spifreq or rawfreq\n");
return -1;
}
pgm->flag |= BP_FLAG_XPARM_RAWFREQ;
PDATA(pgm)->spifreq = rawfreq; PDATA(pgm)->spifreq = rawfreq;
continue; 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. */ /* lower limit comes from 'cpufreq > 4 * spifreq', spifreq in ascii mode is 30kHz. */
if (cpufreq < 125 || cpufreq > 4000) { if (cpufreq < 125 || cpufreq > 4000) {
avrdude_message(MSG_INFO, "BusPirate: cpufreq must be between 125 and 4000 kHz.\n"); avrdude_message(MSG_INFO, "BusPirate: cpufreq must be between 125 and 4000 kHz.\n");
@ -368,6 +381,7 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
pgm->flag |= BP_FLAG_NOPAGEDREAD; pgm->flag |= BP_FLAG_NOPAGEDREAD;
continue; continue;
} }
if (sscanf(extended_param, "serial_recv_timeout=%d", &serial_recv_timeout) == 1) { if (sscanf(extended_param, "serial_recv_timeout=%d", &serial_recv_timeout) == 1) {
if (serial_recv_timeout < 1) { if (serial_recv_timeout < 1) {
avrdude_message(MSG_INFO, "BusPirate: serial_recv_timeout must be greater 0.\n"); 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; PDATA(pgm)->serial_recv_timeout = serial_recv_timeout;
continue; continue;
} }
avrdude_message(MSG_INFO, "BusPirate: do not understand extended param '%s'.\n", extended_param);
return -1;
} }
return 0; return 0;
@ -393,17 +410,12 @@ buspirate_verifyconfig(struct programmer_t *pgm)
return -1; return -1;
} }
if (( (pgm->flag & BP_FLAG_XPARM_SPIFREQ) || if ( ((pgm->flag & BP_FLAG_XPARM_SPIFREQ) || (pgm->flag & BP_FLAG_XPARM_RAWFREQ))
(pgm->flag & BP_FLAG_XPARM_RAWFREQ) ) && buspirate_uses_ascii(pgm)) { && buspirate_uses_ascii(pgm)) {
avrdude_message(MSG_INFO, "BusPirate: SPI speed selection is not supported in ASCII mode\n"); avrdude_message(MSG_INFO, "BusPirate: SPI speed selection is not supported in ASCII mode\n");
return -1; 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; return 0;
} }
@ -437,8 +449,21 @@ static void buspirate_reset_from_binmode(struct programmer_t *pgm)
{ {
unsigned char buf[10]; 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_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 */ buf[0] = 0x0F; /* BinMode: reset */
buspirate_send_bin(pgm, buf, 1); buspirate_send_bin(pgm, buf, 1);
@ -474,6 +499,7 @@ static int buspirate_start_mode_bin(struct programmer_t *pgm)
const char *entered_format; /* Response, for "scanf" */ const char *entered_format; /* Response, for "scanf" */
char config; /* Command to setup submode parameters */ char config; /* Command to setup submode parameters */
} *submode; } *submode;
if (pgm->flag & BP_FLAG_XPARM_RAWFREQ) { if (pgm->flag & BP_FLAG_XPARM_RAWFREQ) {
submode = &(const struct submode){ submode = &(const struct submode){
.name = "Raw-wire", .name = "Raw-wire",
@ -516,13 +542,35 @@ static int buspirate_start_mode_bin(struct programmer_t *pgm)
pgm->flag |= BP_FLAG_IN_BINMODE; 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 == */ /* == Set protocol sub-mode of binary mode == */
buf[0] = submode->enter; buf[0] = submode->enter;
buspirate_send_bin(pgm, buf, 1); buspirate_send_bin(pgm, buf, 1);
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
buspirate_recv_bin(pgm, buf, 4); buspirate_recv_bin(pgm, buf, 4);
if (sscanf((const char*)buf, submode->entered_format, if (sscanf((const char*)buf, submode->entered_format, &PDATA(pgm)->submode_version) != 1) {
&PDATA(pgm)->submode_version) != 1) {
avrdude_message(MSG_INFO, "%s mode not confirmed: '%s'\n", avrdude_message(MSG_INFO, "%s mode not confirmed: '%s'\n",
submode->name, buf); submode->name, buf);
buspirate_reset_from_binmode(pgm); buspirate_reset_from_binmode(pgm);
@ -609,6 +657,9 @@ static int buspirate_start_spi_mode_ascii(struct programmer_t *pgm)
buspirate_send(pgm, "m\n"); buspirate_send(pgm, "m\n");
while(1) { while(1) {
rcvd = buspirate_readline(pgm, NULL, 0); rcvd = buspirate_readline(pgm, NULL, 0);
if (rcvd == NULL) {
return -1;
}
if (spi_cmd == -1 && sscanf(rcvd, "%2d. %10s", &cmd, mode)) { if (spi_cmd == -1 && sscanf(rcvd, "%2d. %10s", &cmd, mode)) {
if (strcmp(mode, "SPI") == 0) if (strcmp(mode, "SPI") == 0)
spi_cmd = cmd; spi_cmd = cmd;
@ -628,6 +679,9 @@ static int buspirate_start_spi_mode_ascii(struct programmer_t *pgm)
buf[0] = '\0'; buf[0] = '\0';
while (1) { while (1) {
rcvd = buspirate_readline(pgm, NULL, 0); rcvd = buspirate_readline(pgm, NULL, 0);
if (rcvd == NULL) {
return -1;
}
if (strstr(rcvd, "Normal (H=3.3V, L=GND)")) { if (strstr(rcvd, "Normal (H=3.3V, L=GND)")) {
/* BP firmware 2.1 defaults to Open-drain output. /* BP firmware 2.1 defaults to Open-drain output.
* That doesn't work on my board, even with pull-up * That doesn't work on my board, even with pull-up
@ -724,9 +778,10 @@ static void buspirate_disable(struct programmer_t *pgm)
if (pgm->flag & BP_FLAG_IN_BINMODE) { if (pgm->flag & BP_FLAG_IN_BINMODE) {
serial_recv_timeout = 100; serial_recv_timeout = 100;
buspirate_reset_from_binmode(pgm); buspirate_reset_from_binmode(pgm);
} else } else {
buspirate_expect(pgm, "#\n", "RESET", 1); buspirate_expect(pgm, "#\n", "RESET", 1);
} }
}
static int buspirate_initialize(struct programmer_t *pgm, AVRPART * p) 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 */ /* Powerup in BinMode is handled in binary mode init */
return; return;
} else { } 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) { if (pgm->flag & BP_FLAG_XPARM_CPUFREQ) {
char buf[25]; char buf[25];
int ok = 0; int ok = 0;
@ -768,9 +823,7 @@ static void buspirate_powerup(struct programmer_t *pgm)
static void buspirate_powerdown(struct programmer_t *pgm) static void buspirate_powerdown(struct programmer_t *pgm)
{ {
if (pgm->flag & BP_FLAG_IN_BINMODE) { if (pgm->flag & BP_FLAG_IN_BINMODE) {
/* 0b0100wxyz - Configure peripherals w=power, x=pull-ups, y=AUX, z=CS /* Powerdown in BinMode is handled in binary mode init */
* we want everything off -- 0b01000000 = 0x40 */
if (buspirate_expect_bin_byte(pgm, 0x40, 0x01))
return; return;
} else { } else {
if (pgm->flag & BP_FLAG_XPARM_CPUFREQ) { if (pgm->flag & BP_FLAG_XPARM_CPUFREQ) {
@ -778,7 +831,7 @@ static void buspirate_powerdown(struct programmer_t *pgm)
avrdude_message(MSG_INFO, "%s: warning: did not get a response to stop PWM command.\n", progname); 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; return;
} }
@ -816,6 +869,9 @@ static int buspirate_cmd_ascii(struct programmer_t *pgm,
buspirate_send(pgm, buf); buspirate_send(pgm, buf);
while (i < 4) { while (i < 4) {
rcvd = buspirate_readline(pgm, NULL, 0); rcvd = buspirate_readline(pgm, NULL, 0);
if (rcvd == NULL) {
return -1;
}
/* WRITE: 0xAC READ: 0x04 */ /* WRITE: 0xAC READ: 0x04 */
if (sscanf(rcvd, "WRITE: 0x%2x READ: 0x%2x", &spi_write, &spi_read) == 2) { if (sscanf(rcvd, "WRITE: 0x%2x READ: 0x%2x", &spi_write, &spi_read) == 2) {
res[i++] = spi_read; res[i++] = spi_read;

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 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, 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. 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 Make sure the CPU frequency is at least four times the SPI frequency.
the CPU frequency is at least for four times the SPI frequency which is in
ASCII mode 30kHz.)
@item @samp{serial_recv_timeout=@var{1...}} @item @samp{serial_recv_timeout=@var{1...}}
This sets the serial receive timeout to the given value. This sets the serial receive timeout to the given value.