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

@ -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)
{
int rc;
const char * readline;
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));
if (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 */
;
} 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)
{
}
@ -293,8 +299,9 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
const char *extended_param;
char reset[10];
char *preset = reset; /* for strtok() */
int spifreq;
int cpufreq;
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");
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");
@ -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;
}
@ -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);
@ -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,13 +542,35 @@ 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);
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");
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,9 +778,10 @@ 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,9 +823,7 @@ 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))
/* Powerdown in BinMode is handled in binary mode init */
return;
} else {
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);
}
}
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;

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.