Index: msp430toolbox.c =================================================================== --- msp430toolbox.c (revision 0) +++ msp430toolbox.c (revision 0) @@ -0,0 +1,370 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * + * avrdude support for MSP430Toolbox. Loosely based on the bus pirate support + * Copyright (C) 2011 Paul Fleischer + * + * 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 + */ + +/* + * Launchpad AVR Chip + * --------- -------- + * GND <-> GND + * +3.3V <-> Vcc + * P1.4 <-> RESET + * MOSI (P1.6) <-> MOSI + * MISO (P1.7) <-> MISO + * SCL/CLK (P1.5) <-> SCK + * + */ + +/* $Id:$ */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#if defined(WIN32NATIVE) +# include /* for alloca() */ +#endif + +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "serial.h" + +/* ====== Private data structure ====== */ + +struct pdata +{ + void * none; +}; +#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) + +#define CMD_GENERAL_GET_INFO 0x01 +#define CMD_GENERAL_PING 0x02 +#define CMD_GENERAL_GO_IDLE 0x04 +#define CMD_GENERAL_INTERACTIVE 0x08 +#define CMD_DIGITAL_INTERACTIVE 0x18 +#define CMD_DIGITAL_READ 0x19 +#define CMD_DIGITAL_WRITE 0x1A +#define CMD_DIGITAL_EXPECT 0x1B +#define CMD_SPI_INTERACTIVE 0x28 +#define CMD_SPI_TRANSFER 0x29 + +/* ====== Feature checks ====== */ + +/* ====== MSP430 Toolbox methods ====== */ +static void msp430toolbox_send_cmd(struct programmer_t *pgm, char cmd, char * args, unsigned int len) +{ + char buf[1]; + int i; + + buf[0] = cmd; + serial_send(&pgm->fd, buf, 1); + + for(i=0;ifd, args, 1); + args++; + } +} + +static char msp430toolbox_read_result(struct programmer_t *pgm) { + char buf[1]; + serial_recv(&pgm->fd, buf, 1); + return buf[0]; +} + +/* ====== Programmer methods ======= */ +static int msp430toolbox_open(struct programmer_t *pgm, char * port) +{ + if(pgm->baudrate == 0) + pgm->baudrate = 115200; + + strcpy(pgm->port, port); + if (serial_open(port, pgm->baudrate, &pgm->fd)==-1) { + printf("Open failed\n"); + return -1; + } + + /* drain any extraneous input */ + serial_drain(&pgm->fd, 0); + + return 0; +} + +static void msp430toolbox_close(struct programmer_t *pgm) +{ + char buf[2]; + + buf[0] = 0x11; + buf[1] = 0x10; + switch(pgm->exit_reset) { + case EXIT_RESET_ENABLED: + buf[1] = 0x00; + case EXIT_RESET_DISABLED: + msp430toolbox_send_cmd(pgm, CMD_DIGITAL_WRITE, buf, 2); + msp430toolbox_read_result(pgm); + break; + default: + break; + } + /*msp430toolbox_send_cmd(pgm, CMD_GENERAL_GO_IDLE, 0x0, 0); + msp430toolbox_read_result(pgm);*/ + + serial_close(&pgm->fd); + pgm->fd.ifd = -1; +} + +static void msp430toolbox_enable(struct programmer_t *pgm) +{ + char buf[2]; + + buf[0] = 0x01; + buf[1] = 0x01; + msp430toolbox_send_cmd(pgm, CMD_DIGITAL_WRITE, buf, 2); + msp430toolbox_read_result(pgm); +} + +static void msp430toolbox_disable(struct programmer_t *pgm) +{ + char buf[2]; + + buf[0] = 0x01; + buf[1] = 0x00; + msp430toolbox_send_cmd(pgm, CMD_DIGITAL_WRITE, buf, 2); + msp430toolbox_read_result(pgm); +} + +static int msp430toolbox_initialize(struct programmer_t *pgm, AVRPART * p) +{ + char buf[3]; + char res; + pgm->powerup(pgm); + + msp430toolbox_send_cmd(pgm, CMD_GENERAL_GO_IDLE, 0x0, 0); + serial_drain(&pgm->fd, 0); + + /* Ensure connection is proper */ + msp430toolbox_send_cmd(pgm, CMD_GENERAL_GET_INFO, 0x0, 0); + serial_recv(&pgm->fd, buf, 3); + + /*printf("MSP430 chip: %x\n", buf[0] | (buf[1] <<8)); + printf("Running at %d MHz\n", buf[2]);*/ + + /* Go into interactive mode */ + msp430toolbox_send_cmd(pgm, CMD_GENERAL_INTERACTIVE, 0x0, 0); + res = msp430toolbox_read_result(pgm); + + /* Next we enable DIGITAL interactive, in order + * to control RESET pin (P1.4, 0x10) and + * LED0 (P1.0) */ + usleep(2000); + buf[0] = 0x0; // no input ports + buf[1] = 0x11; // P1.4 as output port + msp430toolbox_send_cmd(pgm, CMD_DIGITAL_INTERACTIVE, buf, 2); + res = msp430toolbox_read_result(pgm); + + /* Pull reset pin high and turn off LED*/ + buf[0] = 0x11; + buf[1] = 0x10; + msp430toolbox_send_cmd(pgm, CMD_DIGITAL_WRITE, buf, 2); + res = msp430toolbox_read_result(pgm); + + /* Enable SPI in interactive mode */ + /* We have to prepare two argument bytes: + * byte 1: SPI Characteristics + * byte 2: SPI Clocking. */ + buf[0] = 0x40; // Clock active high + buf[0] |= 0x20; // Data change on second edge (Capture->Change) + buf[0] |= 8; // 8-bit transfers + buf[1] = 0x8 | 0xC0; // SMCLK / 16 + msp430toolbox_send_cmd(pgm, CMD_SPI_INTERACTIVE, buf, 2); + res = msp430toolbox_read_result(pgm); + + return pgm->program_enable(pgm, p); +} + +static void msp430toolbox_powerup(struct programmer_t *pgm) +{ +} + +static void msp430toolbox_powerdown(struct programmer_t *pgm) +{ +#if 0 + char buf[2]; + char res; + + /* Pull reset pin high */ + buf[0] = 0x11; + buf[1] = 0x10; + msp430toolbox_send_cmd(pgm, CMD_DIGITAL_WRITE, buf, 2); + res = msp430toolbox_read_result(pgm); +#endif +} + +static int msp430toolbox_cmd(struct programmer_t *pgm, + unsigned char cmd[4], + unsigned char res[4]) +{ + int i; + char buf[3]; + + for(i=0;i<4;i++) { + buf[0] = cmd[i]; // Low-byte + //buf[1] = 0x00; // High-byte + msp430toolbox_send_cmd(pgm, CMD_SPI_TRANSFER, buf, 1); + serial_recv(&pgm->fd, buf, 1); + res[i] = buf[0]; + //serial_recv(&pgm->fd, buf, 1); + } + + return 0; +} + +static int msp430toolbox_program_enable(struct programmer_t *pgm, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + char buf[2]; + + buf[0] = 0x10; + buf[1] = 0x00; + msp430toolbox_send_cmd(pgm, CMD_DIGITAL_WRITE, buf, 2); + msp430toolbox_read_result(pgm); + + 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 msp430toolbox_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; +} + +static void msp430toolbox_display(PROGRAMMER * pgm, const char *p) +{ + +} + +static int msp430toolbox_pgm_led(struct programmer_t *pgm, int value) +{ + char buf[2]; + buf[0] = 0x01; + if (value == ON) + buf[1] = 0x01; + else + buf[1] = 0x00; + msp430toolbox_send_cmd(pgm, CMD_DIGITAL_WRITE, buf, 2); + msp430toolbox_read_result(pgm); + return 0; +} + +/* + * parse the -E string + */ +static int msp430toolbox_parseexitspecs(PROGRAMMER * pgm, char *s) +{ + char *cp; + + while ((cp = strtok(s, ","))) { + if (strcmp(cp, "reset") == 0) { + pgm->exit_reset = EXIT_RESET_ENABLED; + } + else if (strcmp(cp, "noreset") == 0) { + pgm->exit_reset = EXIT_RESET_DISABLED; + } + else { + return -1; + } + s = 0; /* strtok() should be called with the actual string only once */ + } + + return 0; +} + +void msp430toolbox_initpgm(struct programmer_t *pgm) +{ + strcpy(pgm->type, "MSP430Toolbox"); + + pgm->display = msp430toolbox_display; + pgm->exit_reset = EXIT_RESET_UNSPEC; + + /* MSP430Toolbox itself related methods */ + pgm->open = msp430toolbox_open; + pgm->close = msp430toolbox_close; + pgm->enable = msp430toolbox_enable; + pgm->disable = msp430toolbox_disable; + pgm->initialize = msp430toolbox_initialize; + pgm->pgm_led = msp430toolbox_pgm_led; + + pgm->parseexitspecs = msp430toolbox_parseexitspecs; + + /* Chip related methods */ + pgm->powerup = msp430toolbox_powerup; + pgm->powerdown = msp430toolbox_powerdown; + pgm->program_enable = msp430toolbox_program_enable; + pgm->chip_erase = msp430toolbox_chip_erase; + pgm->cmd = msp430toolbox_cmd; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* Support functions */ + //pgm->parseextparams = msp430toolbox_parseextparms; + + /* Allocate private data */ + if ((pgm->cookie = calloc(1, sizeof(struct pdata))) == 0) { + fprintf(stderr, "%s: msp430toolbox_initpgm(): Out of memory allocating private data\n", + progname); + exit(1); + } +} + Index: config_gram.y =================================================================== --- config_gram.y (revision 962) +++ config_gram.y (working copy) @@ -48,6 +48,7 @@ #include "avr.h" #include "jtagmkI.h" #include "jtagmkII.h" +#include "msp430toolbox.h" #if defined(WIN32NATIVE) #define strtok_r( _s, _sep, _lasts ) \ @@ -114,6 +115,7 @@ %token K_JTAG_MKII_PDI %token K_LOADPAGE %token K_MAX_WRITE_DELAY +%token K_MSP430TOOLBOX %token K_MIN_WRITE_DELAY %token K_MISO %token K_MOSI @@ -438,6 +440,12 @@ } } | + K_TYPE TKN_EQUAL K_MSP430TOOLBOX { + { + msp430toolbox_initpgm(current_prog); + } + } | + K_TYPE TKN_EQUAL K_STK600 { { stk600_initpgm(current_prog); Index: msp430toolbox.h =================================================================== --- msp430toolbox.h (revision 0) +++ msp430toolbox.h (revision 0) @@ -0,0 +1,29 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * + * avrdude support for MSP430Toolbox. Loosely based on the bus pirate support + * Copyright (C) 2011 Paul Fleischer + * + * 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 + */ + +/* $Id: $ */ + +#ifndef msp430toolbox_h +#define msp430toolbox_h + +void msp430toolbox_initpgm (struct programmer_t *pgm); + +#endif Index: avrdude.conf.in =================================================================== --- avrdude.conf.in (revision 962) +++ avrdude.conf.in (working copy) @@ -350,6 +350,12 @@ type = buspirate; ; +programmer + id = "msp430toolbox"; + desc = "The MSP430 Toolbox"; + type = msp430toolbox; +; + # 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 Index: lexer.l =================================================================== --- lexer.l (revision 962) +++ lexer.l (working copy) @@ -128,6 +128,7 @@ bs2 { yylval=NULL; return K_BS2; } buff { yylval=NULL; return K_BUFF; } buspirate { yylval=NULL; return K_BUSPIRATE; } +msp430toolbox { yylval=NULL; return K_MSP430TOOLBOX; } butterfly { yylval=NULL; return K_BUTTERFLY; } chip_erase_delay { yylval=NULL; return K_CHIP_ERASE_DELAY; } desc { yylval=NULL; return K_DESC; } Index: Makefile.am =================================================================== --- Makefile.am (revision 962) +++ Makefile.am (working copy) @@ -93,6 +93,8 @@ bitbang.h \ buspirate.c \ buspirate.h \ + msp430toolbox.c \ + msp430toolbox.h \ butterfly.c \ butterfly.h \ config.c \