Added support for the BusPirate programmer.
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@842 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
852c53d4ac
commit
bcce066a1c
|
@ -1,3 +1,9 @@
|
|||
2009-10-08 Michal Ludvig <mludvig@logix.net.nz>
|
||||
|
||||
* buspirate.c, buspirate.h: Support for the BusPirate programmer
|
||||
* config_gram.y, avrdude.conf.in, main.c, lexer.l, Makefile.am:
|
||||
Glue for BusPirate.
|
||||
|
||||
2009-08-17 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||
|
||||
* usb_libusb.c (usbdev_close): Repair the logic around the
|
||||
|
|
|
@ -88,6 +88,8 @@ libavrdude_a_SOURCES = \
|
|||
avrpart.h \
|
||||
bitbang.c \
|
||||
bitbang.h \
|
||||
buspirate.c \
|
||||
buspirate.h \
|
||||
butterfly.c \
|
||||
butterfly.h \
|
||||
config.c \
|
||||
|
|
|
@ -340,6 +340,12 @@ programmer
|
|||
type = stk500v2;
|
||||
;
|
||||
|
||||
programmer
|
||||
id = "buspirate";
|
||||
desc = "The Bus Pirate";
|
||||
type = buspirate;
|
||||
;
|
||||
|
||||
# This is supposed to be the "default" STK500 entry.
|
||||
# Attempts to select the correct firmware version
|
||||
# by probing for it. Better use one of the entries
|
||||
|
|
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
*
|
||||
* avrdude support for The Bus Pirate - universal serial interface
|
||||
*
|
||||
* Copyright (C) 2009 Michal Ludvig <mludvig@logix.net.nz>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* BusPirate AVR Chip
|
||||
* --------- --------
|
||||
* GND <-> GND
|
||||
* +5V <-> Vcc
|
||||
* CS <-> RESET
|
||||
* MOSI <-> MOSI
|
||||
* MISO <-> MISO
|
||||
* SCL/CLK <-> SCK
|
||||
*
|
||||
* Tested with BusPirate PTH, firmware version 2.1 programming ATmega328P
|
||||
*/
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "avr.h"
|
||||
#include "pgm.h"
|
||||
#include "serial.h"
|
||||
|
||||
/* ====== Serial talker functions ====== */
|
||||
|
||||
static int buspirate_getc(struct programmer_t *pgm)
|
||||
{
|
||||
int rc;
|
||||
unsigned char ch = 0;
|
||||
|
||||
rc = serial_recv(&pgm->fd, &ch, 1);
|
||||
if (rc < 0)
|
||||
return EOF;
|
||||
return ch;
|
||||
}
|
||||
|
||||
static char *buspirate_readline(struct programmer_t *pgm, char *buf, size_t len)
|
||||
{
|
||||
char *buf_p;
|
||||
long orig_serial_recv_timeout = serial_recv_timeout;
|
||||
|
||||
/* Static local buffer - this may come handy at times */
|
||||
static char buf_local[100];
|
||||
|
||||
if (buf == NULL) {
|
||||
buf = buf_local;
|
||||
len = sizeof(buf_local);
|
||||
}
|
||||
buf_p = buf;
|
||||
memset(buf, 0, len);
|
||||
while (buf_p < (buf + len - 1)) { /* keep the very last byte == 0 */
|
||||
*buf_p = buspirate_getc(pgm);
|
||||
if (*buf_p == '\r')
|
||||
continue;
|
||||
if (*buf_p == '\n')
|
||||
break;
|
||||
if (*buf_p == EOF) {
|
||||
*buf_p = '\0';
|
||||
break;
|
||||
}
|
||||
buf_p++;
|
||||
serial_recv_timeout = 100;
|
||||
}
|
||||
serial_recv_timeout = orig_serial_recv_timeout;
|
||||
if (verbose)
|
||||
fprintf(stderr, "%s: buspirate_readline(): %s%s",
|
||||
progname, buf,
|
||||
buf[strlen(buf) - 1] == '\n' ? "" : "\n");
|
||||
if (! buf[0]) {
|
||||
fprintf(stderr,
|
||||
"%s: buspirate_readline(): programmer is not responding\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int buspirate_send(struct programmer_t *pgm, char *str)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "%s: buspirate_send(): %s", progname, str);
|
||||
|
||||
rc = serial_send(&pgm->fd, (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 */
|
||||
;
|
||||
/* by now we should be in sync */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int buspirate_is_prompt(char *str)
|
||||
{
|
||||
/* Prompt ends with '>' all other input probably ends with '\n' */
|
||||
return (str[strlen(str) - 1] == '>');
|
||||
}
|
||||
|
||||
static int buspirate_expect(struct programmer_t *pgm, char *send,
|
||||
char *expect, int wait_for_prompt)
|
||||
{
|
||||
int got_it = 0;
|
||||
size_t expect_len = strlen(expect);
|
||||
char *rcvd;
|
||||
|
||||
buspirate_send(pgm, send);
|
||||
while (1) {
|
||||
rcvd = buspirate_readline(pgm, NULL, 0);
|
||||
|
||||
if (strncmp(rcvd, expect, expect_len) == 0)
|
||||
got_it = 1;
|
||||
|
||||
if (buspirate_is_prompt(rcvd))
|
||||
break;
|
||||
}
|
||||
return got_it;
|
||||
}
|
||||
|
||||
/* ====== Do-nothing functions ====== */
|
||||
static void buspirate_dummy_6(struct programmer_t *pgm,
|
||||
const char *p)
|
||||
{
|
||||
}
|
||||
|
||||
/* ====== Programmer methods ======= */
|
||||
static int buspirate_open(struct programmer_t *pgm, char * port)
|
||||
{
|
||||
/* BusPirate runs at 115200 by default */
|
||||
if(pgm->baudrate == 0)
|
||||
pgm->baudrate = 115200;
|
||||
|
||||
strcpy(pgm->port, port);
|
||||
serial_open(port, pgm->baudrate, &pgm->fd);
|
||||
|
||||
/* drain any extraneous input */
|
||||
serial_drain(&pgm->fd, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void buspirate_close(struct programmer_t *pgm)
|
||||
{
|
||||
serial_close(&pgm->fd);
|
||||
pgm->fd.ifd = -1;
|
||||
}
|
||||
|
||||
static int buspirate_start_spi_mode(struct programmer_t *pgm)
|
||||
{
|
||||
int spi_cmd = -1;
|
||||
int cmd;
|
||||
char *rcvd, *mode, buf[5];
|
||||
|
||||
buspirate_send(pgm, "M\n");
|
||||
while(1) {
|
||||
rcvd = buspirate_readline(pgm, NULL, 0);
|
||||
if (spi_cmd == -1 && sscanf(rcvd, "%d. %as", &cmd, &mode)) {
|
||||
if (strcmp(mode, "SPI") == 0)
|
||||
spi_cmd = cmd;
|
||||
}
|
||||
if (buspirate_is_prompt(rcvd))
|
||||
break;
|
||||
}
|
||||
if (spi_cmd == -1) {
|
||||
fprintf(stderr,
|
||||
"%s: SPI mode number not found. Does your BusPirate support SPI?\n",
|
||||
progname);
|
||||
fprintf(stderr, "%s: Try powercycling your BusPirate and try again.\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%d\n", spi_cmd);
|
||||
buspirate_send(pgm, buf);
|
||||
buf[0] = '\0';
|
||||
while (1) {
|
||||
rcvd = buspirate_readline(pgm, NULL, 0);
|
||||
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
|
||||
* resistors. Select 3.3V output mode instead. */
|
||||
sscanf(rcvd, " %d.", &cmd);
|
||||
snprintf(buf, sizeof(buf), "%d\n", cmd);
|
||||
}
|
||||
if (buspirate_is_prompt(rcvd)) {
|
||||
if (strncmp(rcvd, "SPI>", 4) == 0) {
|
||||
printf("BusPirate is now configured for SPI\n");
|
||||
break;
|
||||
}
|
||||
/* Not yet 'SPI>' prompt */
|
||||
if (buf[0]) {
|
||||
buspirate_send(pgm, buf);
|
||||
buf[0] = '\0';
|
||||
} else
|
||||
buspirate_send(pgm, "\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void buspirate_enable(struct programmer_t *pgm)
|
||||
{
|
||||
char *rcvd;
|
||||
|
||||
printf("Detecting BusPirate...\n");
|
||||
buspirate_send(pgm, "#\n");
|
||||
while(1) {
|
||||
rcvd = buspirate_readline(pgm, NULL, 0);
|
||||
if (strncmp(rcvd, "RESET", 5) == 0)
|
||||
continue;
|
||||
if (buspirate_is_prompt(rcvd)) {
|
||||
puts("**");
|
||||
break;
|
||||
}
|
||||
printf("** %s", rcvd);
|
||||
}
|
||||
|
||||
if (buspirate_start_spi_mode(pgm) < 0)
|
||||
fprintf(stderr, "%s: Failed to start SPI mode\n", progname);
|
||||
}
|
||||
|
||||
static void buspirate_disable(struct programmer_t *pgm)
|
||||
{
|
||||
buspirate_expect(pgm, "#\n", "RESET", 1);
|
||||
}
|
||||
|
||||
static int buspirate_initialize(struct programmer_t *pgm, AVRPART * p)
|
||||
{
|
||||
pgm->powerup(pgm);
|
||||
|
||||
return pgm->program_enable(pgm, p);
|
||||
}
|
||||
|
||||
static void buspirate_powerup(struct programmer_t *pgm)
|
||||
{
|
||||
if (!buspirate_expect(pgm, "W\n", "POWER SUPPLIES ON", 1)) {
|
||||
fprintf(stderr, "%s: warning: did not get a response to PowerUp command.\n", progname);
|
||||
fprintf(stderr, "%s: warning: Trying to continue anyway...\n", progname);
|
||||
}
|
||||
}
|
||||
|
||||
static void buspirate_powerdown(struct programmer_t *pgm)
|
||||
{
|
||||
if (!buspirate_expect(pgm, "w\n", "POWER SUPPLIES OFF", 1))
|
||||
fprintf(stderr, "%s: warning: did not get a response to PowerDown command.\n", progname);
|
||||
}
|
||||
|
||||
static int buspirate_cmd(struct programmer_t *pgm,
|
||||
unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
char buf[25];
|
||||
char *rcvd;
|
||||
int spi_write, spi_read, i = 0;
|
||||
|
||||
snprintf(buf, sizeof(buf), "0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
buspirate_send(pgm, buf);
|
||||
while (1) {
|
||||
rcvd = buspirate_readline(pgm, NULL, 0);
|
||||
/* WRITE: 0xAC READ: 0x04 */
|
||||
if (sscanf(rcvd, "WRITE: 0x%x READ: 0x%x", &spi_write, &spi_read) == 2) {
|
||||
res[i++] = spi_read;
|
||||
}
|
||||
if (buspirate_is_prompt(rcvd))
|
||||
break;
|
||||
}
|
||||
if (i != 4) {
|
||||
fprintf(stderr, "%s: error: SPI has not read 4 bytes back\n", progname);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int buspirate_program_enable(struct programmer_t *pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
|
||||
buspirate_expect(pgm, "{\n", "CS ENABLED", 1);
|
||||
|
||||
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
|
||||
fprintf(stderr,
|
||||
"program enable instruction not defined for part \"%s\"\n",
|
||||
p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd);
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
|
||||
if (res[2] != cmd[1])
|
||||
return -2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int buspirate_chip_erase(struct programmer_t *pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
|
||||
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
|
||||
fprintf(stderr,
|
||||
"chip erase instruction not defined for part \"%s\"\n",
|
||||
p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pgm->pgm_led(pgm, ON);
|
||||
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
|
||||
avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
usleep(p->chip_erase_delay);
|
||||
pgm->initialize(pgm, p);
|
||||
|
||||
pgm->pgm_led(pgm, OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void buspirate_initpgm(struct programmer_t *pgm)
|
||||
{
|
||||
strcpy(pgm->type, "BusPirate");
|
||||
|
||||
pgm->display = buspirate_dummy_6;
|
||||
|
||||
/* BusPirate itself related methods */
|
||||
pgm->open = buspirate_open;
|
||||
pgm->close = buspirate_close;
|
||||
pgm->enable = buspirate_enable;
|
||||
pgm->disable = buspirate_disable;
|
||||
pgm->initialize = buspirate_initialize;
|
||||
|
||||
/* Chip related methods */
|
||||
pgm->powerup = buspirate_powerup;
|
||||
pgm->powerdown = buspirate_powerdown;
|
||||
pgm->program_enable = buspirate_program_enable;
|
||||
pgm->chip_erase = buspirate_chip_erase;
|
||||
pgm->cmd = buspirate_cmd;
|
||||
pgm->read_byte = avr_read_byte_default;
|
||||
pgm->write_byte = avr_write_byte_default;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
*
|
||||
* avrdude support for The Bus Pirate - universal serial interface
|
||||
*
|
||||
* Copyright (C) 2009 Michal Ludvig <mludvig@logix.net.nz>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef buspirate_h
|
||||
#define buspirate_h
|
||||
|
||||
void buspirate_initpgm (struct programmer_t *pgm);
|
||||
|
||||
#endif
|
|
@ -38,6 +38,7 @@
|
|||
#include "pgm.h"
|
||||
#include "stk500.h"
|
||||
#include "arduino.h"
|
||||
#include "buspirate.h"
|
||||
#include "stk500v2.h"
|
||||
#include "stk500generic.h"
|
||||
#include "avr910.h"
|
||||
|
@ -84,6 +85,7 @@ static int parse_cmdbits(OPCODE * op);
|
|||
%token K_BAUDRATE
|
||||
%token K_BS2
|
||||
%token K_BUFF
|
||||
%token K_BUSPIRATE
|
||||
%token K_CHIP_ERASE_DELAY
|
||||
%token K_DEDICATED
|
||||
%token K_DEFAULT_PARALLEL
|
||||
|
@ -425,6 +427,12 @@ prog_parm :
|
|||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_BUSPIRATE {
|
||||
{
|
||||
buspirate_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_STK600 {
|
||||
{
|
||||
stk600_initpgm(current_prog);
|
||||
|
|
1
lexer.l
1
lexer.l
|
@ -127,6 +127,7 @@ banked { yylval=NULL; return K_PAGED; }
|
|||
baudrate { yylval=NULL; return K_BAUDRATE; }
|
||||
bs2 { yylval=NULL; return K_BS2; }
|
||||
buff { yylval=NULL; return K_BUFF; }
|
||||
buspirate { yylval=NULL; return K_BUSPIRATE; }
|
||||
butterfly { yylval=NULL; return K_BUTTERFLY; }
|
||||
chip_erase_delay { yylval=NULL; return K_CHIP_ERASE_DELAY; }
|
||||
desc { yylval=NULL; return K_DESC; }
|
||||
|
|
1
main.c
1
main.c
|
@ -679,6 +679,7 @@ int main(int argc, char * argv [])
|
|||
|
||||
if ((strcmp(pgm->type, "STK500") == 0) ||
|
||||
(strcmp(pgm->type, "avr910") == 0) ||
|
||||
(strcmp(pgm->type, "buspirate") == 0) ||
|
||||
(strcmp(pgm->type, "STK500V2") == 0) ||
|
||||
(strcmp(pgm->type, "JTAGMKII") == 0)) {
|
||||
if (port == default_parallel) {
|
||||
|
|
Loading…
Reference in New Issue