#platform?=tilaunchpad
platform?=goodfet
+# donb
+ifeq ($(platform),donbfet)
+GCC?=avr-gcc
+mcu?=atmega644p
+CFLAGS=$(DEBUG) -mmcu=$(mcu) -W -Os -mcall-prologues -Wall -Wextra -Wuninitialized -fpack-struct -fshort-enums -funsigned-bitfields
+endif
ifeq ($(platform),tilaunchpad)
mcu?=msp430x1612
config ?= monitor chipcon spi jtag430 jtag430x2 avr openocd ccspi
endif
+# donb
+ifeq ($(platform),donbfet)
+config=monitor avr spi jscan
+endif
+
# Build the needed list of app and lib object files from the config
apps=
hdrs+= ps2.h
endif
+# include jscan app
+ifeq ($(filter jscan, $(config)), jscan)
+ apps+= apps/jscan/jscan.o
+ hdrs+= jscan.h
+endif
+
# Rules
app= goodfet
$(MSP430BSL) -e
$(app).c: config builddate appsfiles err
$(app): $(libs) $(apps)
+
+ifeq ($(platform),donbfet)
+$(app).hex: $(app)
+ avr-objcopy -j .text -j .data -O ihex goodfet goodfet.hex
+else
$(app).hex: $(app)
msp430-objcopy goodfet -O ihex goodfet.hex
+endif
m4s: $(app).hex
msp430-objdump -D -m msp430 $(app).hex | m4s init
clean:
--- /dev/null
+/*! \file jscan.c
+ \author Don A. Bailey
+ \brief JTAG Scanner
+*/
+
+/* set tabstop=8 */
+
+#include "platform.h"
+#include "command.h"
+
+#if (platform != donbfet)
+# include <signal.h>
+# include <io.h>
+# include <iomacros.h>
+#endif
+
+#include "jscan.h"
+
+#define OFFSETIO 32
+#define NPATTERN 64
+
+typedef struct Pin Pin;
+
+struct
+Pin
+{
+ Pin * next;
+ Pin * prev;
+ uint8_t id;
+ uint8_t bit;
+ uint8_t pullup;
+ volatile uint8_t * ddr;
+ volatile uint8_t * pin;
+ volatile uint8_t * port;
+};
+
+static Pin * pins;
+static int nfound;
+static uint8_t found[CMDDATALEN];
+static char * tap_shiftir = "1111101100";
+static uint8_t xdelay = JSCAN_DEFAULT_DELAY;
+static uint8_t endian = JSCAN_ENDIAN_LITTLE;
+static char pattern[NPATTERN] = "0110011101001101101000010111001001";
+
+static void jscan(uint8_t, uint8_t, uint32_t);
+
+static uint8_t setdelay(uint32_t);
+static uint8_t setpullup(uint32_t);
+static uint8_t setendian(uint32_t);
+
+static uint8_t npins(void);
+static void listpin(uint8_t);
+static uint8_t addpin(Pin * );
+static uint8_t rmpin(uint32_t);
+static uint8_t newpin(uint32_t);
+static uint8_t findpin(uint8_t, Pin ** );
+
+static void scan(uint8_t);
+static void loopback(uint8_t);
+static void getresults(uint8_t);
+static void clockstrobe(Pin * );
+static void tdipulse(Pin *, Pin *, uint8_t);
+static void tapstate(char *, Pin *, Pin * );
+static void initpins(Pin *, Pin *, Pin *, Pin *, Pin * );
+static int checkdata(char *, int, Pin *, Pin *, Pin *, int * );
+
+app_t const
+jscan_app =
+{
+ JSCAN,
+ jscan,
+ "JSCAN",
+ "\tThe JScan app adds support for JTAG brute-force scanning.\n"
+};
+
+static void
+jscan(uint8_t a, uint8_t v, uint32_t l)
+{
+ switch(v)
+ {
+ case JSCAN_CMD_ADDPIN:
+ txdata(a, newpin(l), 1);
+ break;
+ case JSCAN_CMD_RMPIN:
+ txdata(a, rmpin(l), 1);
+ break;
+ case JSCAN_CMD_DELAY:
+ txdata(a, setdelay(l), 1);
+ break;
+ case JSCAN_CMD_PULLUP:
+ txdata(a, setpullup(l), 0);
+ break;
+ case JSCAN_CMD_LOOPBACK:
+ loopback(a);
+ break;
+ case JSCAN_CMD_ENDIAN:
+ txdata(a, setendian(l), 1);
+ break;
+ case JSCAN_CMD_SCAN:
+ scan(a);
+ break;
+ case JSCAN_CMD_LISTPIN:
+ listpin(a);
+ break;
+ case JSCAN_CMD_RESULTS:
+ getresults(a);
+ break;
+ default:
+ debugstr("Verb unimplemented in JSCAN application.");
+ txdata(a, NOK, 0);
+ break;
+ }
+}
+
+static uint8_t
+npins(void)
+{
+ uint8_t x;
+ Pin * p;
+
+ x = 0;
+ p = pins;
+ while(p)
+ {
+ p = p->next;
+ x++;
+ }
+
+ return x;
+}
+
+static uint8_t
+newpin(uint32_t l)
+{
+ Pin * p;
+
+ if(l != 5)
+ return NOK;
+
+ if(npins() == JSCAN_LIMIT_PINS)
+ {
+ return LIMIT;
+ }
+
+ if(findpin(cmddata[0], NULL))
+ {
+ return EXIST;
+ }
+
+ p = calloc(1, sizeof *p);
+ if(!p)
+ return NMEM;
+
+ /* enable pullups by default */
+ p->pullup = 1;
+
+ p->id = cmddata[0];
+ p->bit = cmddata[1];
+ p->ddr = (volatile uint8_t * )((uint16_t)cmddata[2] + OFFSETIO);
+ p->pin = (volatile uint8_t * )((uint16_t)cmddata[3] + OFFSETIO);
+ p->port = (volatile uint8_t * )((uint16_t)cmddata[4] + OFFSETIO);
+
+ /* explicitly set return value */
+ cmddata[0] = p->id;
+
+ return addpin(p);
+}
+
+static uint8_t
+addpin(Pin * p)
+{
+ Pin * a;
+
+ if(!pins)
+ {
+ pins = p;
+ return OK;
+ }
+
+ a = pins;
+ while(a && a->next)
+ a = a->next;
+ a->next = p;
+ p->prev = a;
+
+ return OK;
+}
+
+static uint8_t
+rmpin(uint32_t l)
+{
+ uint8_t i;
+ Pin * p;
+
+ if(l != 1)
+ return NOK;
+
+ i = cmddata[0];
+ if(!findpin(i, &p))
+ return NOK;
+
+ if(p->prev)
+ (p->prev)->next = p->next;
+ if(p->next)
+ (p->next)->prev = p->prev;
+ if(p == pins)
+ pins = p->next;
+
+ free(p);
+
+ cmddata[0] = i;
+
+ return OK;
+}
+
+static uint8_t
+findpin(uint8_t i, Pin ** pp)
+{
+ Pin * p;
+
+ p = pins;
+ while(p)
+ {
+ if(p->id == i)
+ {
+ if(pp)
+ *pp = p;
+ return 1;
+ }
+
+ p = p->next;
+ }
+
+ return 0;
+}
+
+static uint8_t
+setdelay(uint32_t l)
+{
+ if(l != 1)
+ {
+ cmddata[0] = xdelay;
+ return OK;
+ }
+
+ xdelay = cmddata[0];
+ return OK;
+}
+
+static uint8_t
+setpullup(uint32_t l)
+{
+ Pin * p;
+
+ if(l != 2)
+ return NOK;
+
+ /* change all or one? */
+ if(cmddata[0] != 0xff)
+ {
+ if(!findpin(l, &p))
+ return EXIST;
+ p->pullup = cmddata[1] ? 1 : 0 ;
+ }
+ else
+ {
+ p = pins;
+ while(p)
+ {
+ p->pullup = cmddata[1] ? 1 : 0 ;
+ p = p->next;
+ }
+ }
+
+ return OK;
+}
+
+static uint8_t
+setendian(uint32_t l)
+{
+ if(l != 1)
+ {
+ cmddata[0] = endian;
+ return OK;
+ }
+
+ switch(cmddata[0])
+ {
+ case JSCAN_ENDIAN_BIG:
+ endian = JSCAN_ENDIAN_BIG;
+ break;
+ case JSCAN_ENDIAN_LITTLE:
+ endian = JSCAN_ENDIAN_LITTLE;
+ break;
+ default:
+ return NOK;
+ }
+
+ return OK;
+}
+
+static void
+loopback(uint8_t a)
+{
+ Pin * tdo;
+ Pin * tdi;
+ int nb;
+ int r;
+
+ if(npins() < 2)
+ {
+ txdata(a, EXIST, 0);
+ return;
+ }
+
+ nb = 0;
+
+ tdo = pins;
+ while(tdo)
+ {
+ tdi = pins;
+ while(tdi)
+ {
+ if(tdi == tdo)
+ {
+ tdi = tdi->next;
+ continue;
+ }
+
+ initpins(NULL, NULL, tdi, NULL, NULL);
+
+ r = checkdata(pattern, (2*NPATTERN), NULL, tdi, tdo, NULL);
+ if(r == 1)
+ {
+ if(nb >= (CMDDATALEN-4))
+ {
+ txdata(a, NMEM, 0);
+ return;
+ }
+
+ /* add the response in couples; TDI first */
+ cmddata[nb++] = tdi->id;
+ cmddata[nb++] = tdo->id;
+ }
+
+ tdi = tdi->next;
+ }
+
+ tdo = tdo->next;
+ }
+
+ txdata(a, OK, nb);
+}
+
+static void
+initpins(Pin * tck, Pin * tms, Pin * tdi, Pin * tdo, Pin * nrst)
+{
+ Pin * p;
+
+/* XXX test removing syncs */
+ p = pins;
+ while(p)
+ {
+ /* set as input by default */
+ *p->ddr &= ~(1 << p->bit);
+
+ /* sync */
+ _delay_ms(xdelay);
+
+ /* set pullup if desired while in input mode */
+ if(p->pullup)
+ *p->port |= (1 << p->bit);
+ else
+ *p->port &= ~(1 << p->bit);
+
+ /* sync */
+ _delay_ms(xdelay);
+
+ if(p == nrst)
+ {
+ /* set as output */
+ *p->ddr |= (1 << p->bit);
+
+ /* nrst requires output fixed high */
+ *p->port &= ~(1 << p->bit);
+ *p->port |= (1 << p->bit);
+ }
+ else if(p == tck || p == tms || p == tdi)
+ {
+ /* set as output */
+ *p->ddr |= (1 << p->bit);
+
+ /* sync */
+ _delay_ms(xdelay);
+
+ /* these pins must start low */
+ *p->port &= ~(1 << p->bit);
+ }
+
+ /* tdo should need no special sauce */
+
+ /* sync */
+ _delay_ms(xdelay);
+
+ p = p->next;
+ }
+}
+
+static int
+checkdata(char * pattern, int ntimes, Pin * tck, Pin * tdi, Pin * tdo, int * nreg)
+{
+ char rcv[NPATTERN];
+ int tdo_read;
+ int tdo_prev;
+ int ntoggle;
+ uint8_t x;
+ int np;
+ int i;
+ int w;
+
+ w = 0;
+ np = strlen(pattern);
+
+ x = (*tdo->pin & (1 << tdo->bit)) >> tdo->bit;
+
+ tdo_prev = '0' + (x == 1);
+
+ for(i = 0; i < ntimes; i++)
+ {
+ tdipulse(tck, tdi, pattern[w++] - '0');
+ if(!pattern[w])
+ {
+ w = 0;
+ }
+
+ x = (*tdo->pin & (1 << tdo->bit)) >> tdo->bit;
+
+ tdo_read = '0' + (x == 1);
+
+ ntoggle += (tdo_read != tdo_prev);
+ tdo_prev = tdo_read;
+
+ if(i < np)
+ {
+ rcv[i] = tdo_read;
+ }
+ else
+ {
+ memmove(rcv, rcv + 1, np - 1);
+ rcv[np - 1] = tdo_read;
+ }
+
+ if(i >= np - 1)
+ {
+ if(!memcmp(pattern, rcv, np))
+ {
+ if(nreg)
+ *nreg = i + 1 - np;
+ return 1;
+ }
+ }
+ }
+
+ if(nreg)
+ *nreg = 0;
+
+ return ntoggle > 1 ? ntoggle : 0 ;
+}
+
+static void
+tdipulse(Pin * tck, Pin * tdi, uint8_t x)
+{
+ if(x)
+ *tdi->port |= (1 << tdi->bit);
+ else
+ *tdi->port &= ~(1 << tdi->bit);
+
+ /* sync */
+ _delay_ms(xdelay);
+
+ clockstrobe(tck);
+}
+
+static void
+clockstrobe(Pin * tck)
+{
+ *tck->port |= (1 << tck->bit);
+ _delay_ms(xdelay);
+
+ *tck->port &= ~(1 << tck->bit);
+ _delay_ms(xdelay);
+}
+
+static void
+scan(uint8_t a)
+{
+ Pin * nrst;
+ Pin * tck;
+ Pin * tms;
+ Pin * tdi;
+ Pin * tdo;
+ int nreg;
+ int r;
+
+ if(npins() < 5)
+ {
+ txdata(a, EXIST, 0);
+ return;
+ }
+
+ nfound = 0;
+ nrst = pins;
+
+ /* send back an OK to let the user know we've started */
+ txdata(a, OK, 0);
+
+ while(nrst)
+ {
+ tck = pins;
+ while(tck)
+ {
+ if(tck == nrst)
+ {
+ tck = tck->next;
+ continue;
+ }
+
+ tms = pins;
+ while(tms)
+ {
+ if(tms == nrst || tms == tck)
+ {
+ tms = tms->next;
+ continue;
+ }
+
+ tdo = pins;
+ while(tdo)
+ {
+ if(tdo == nrst || tdo == tck || tdo == tms)
+ {
+ tdo = tdo->next;
+ continue;
+ }
+
+ tdi = pins;
+ while(tdi)
+ {
+ if(tdi == nrst || tdi == tck || tdi == tms || tdi == tdo)
+ {
+ tdi = tdi->next;
+ continue;
+ }
+
+ initpins(tck, tms, tdi, tdo, nrst);
+
+ tapstate(tap_shiftir, tck, tms);
+
+ r = checkdata(pattern, (2*NPATTERN), tck, tdi, tdo, &nreg);
+ if(r == 1)
+ {
+ /* found potential JTAG */
+ /* NB */
+ /* can fit around 100 detections; but total should hover around 0.5% of total tests.
+ * so if the number of tests is really high, one could exceed 100 detected JTAGs,
+ * so caveat emptor
+ */
+ if(nfound < (CMDDATALEN-4)-5)
+ {
+ /* order is important */
+ found[nfound++] = tck->id;
+ found[nfound++] = tms->id;
+ found[nfound++] = tdi->id;
+ found[nfound++] = tdo->id;
+ found[nfound++] = nrst->id;
+ }
+ }
+
+ tdi = tdi->next;
+ }
+
+ tdo = tdo->next;
+ }
+
+ tms = tms->next;
+ }
+
+ tck = tck->next;
+ }
+
+ nrst = nrst->next;
+ }
+
+}
+
+static void
+tapstate(char * s, Pin * tck, Pin * tms)
+{
+ int x;
+
+ while(*s)
+ {
+ x = *s - '0';
+ /* issue */
+ if(x)
+ *tms->port |= (1 << tms->bit);
+ else
+ *tms->port &= ~(1 << tms->bit);
+
+ /* strobe */
+ *tck->port &= ~(1 << tck->bit);
+ _delay_ms(xdelay);
+ *tck->port |= (1 << tck->bit);
+
+ s++;
+ }
+}
+
+static void
+listpin(uint8_t a)
+{
+ Pin * p;
+ int nb;
+
+ nb = 0;
+ p = pins;
+ while(p)
+ {
+ cmddata[nb++] = p->id;
+ cmddata[nb++] = p->bit;
+ cmddata[nb++] = ((uint16_t)(p->ddr)) & 0xff;
+ cmddata[nb++] = ((uint16_t)(p->pin)) & 0xff;
+ cmddata[nb++] = ((uint16_t)(p->port)) & 0xff;
+ p = p->next;
+ }
+
+ txdata(a, OK, nb);
+}
+
+static void
+getresults(uint8_t a)
+{
+ memcpy(cmddata, found, nfound);
+ txdata(a, OK, nfound);
+}
+
#define INITCHIP arduino_init();
#endif
+#if (platform == donbfet)
+# define INITCHIP donbfet_init();
+#endif
+
#ifdef INITCHIP
INITCHIP
#else
} else { // we come here after DTR high (release reset)
dputs("\nWarmstart\n");
}
+#elif (platform == donbfet)
+ extern void donbfet_reboot(void);
+ void (*reboot_function)(void) = donbfet_reboot;
#else
void (*reboot_function)(void) = (void *) 0xFFFE;
#endif
// or
// WDTCTL = WDTPW + WDTCNTCL + WDTSSEL + 0x00;
// but instead we'll jump to our reboot function pointer
- #ifdef MSP430
-#if (platform == tilaunchpad)
+#ifdef MSP430
+# if (platform == tilaunchpad)
// do we really need this, we do not want to reset the TUSB3410
dputs("reset_count>4\n");
//longjmp(warmstart,111);
goto warmstart;
-#else
+# else
(*reboot_function)();
-#endif
- #else
+# endif
+#else /* !MSP430 */
+# if (platform == donbfet)
+ (*reboot_function)();
+# else
debugstr("Rebooting not supported on this platform.");
- #endif
+# endif
+#endif
}
continue;
#include "spi.h"
#include "app.h"
-#define AVR 0x32
+/* AVR is a known macro for the AVR C includes */
+#define XAVR 0x32
//! Setup the AVR pins.
void avrsetup();
//! Enable AVR programming mode.
void avr_prgen();
//! Read AVR device code.
-u8 avr_sig(u8 i);
+uint8_t avr_sig(uint8_t i);
//! Erase an AVR device
void avr_erase();
//! Read lock bits.
-u8 avr_lockbits();
+uint8_t avr_lockbits();
//! Write lock bits.
-void avr_setlock(u8 bits);
+void avr_setlock(uint8_t bits);
//! Read a byte of Flash
-u8 avr_peekflash(u16 adr);
+uint8_t avr_peekflash(uint16_t adr);
//! Read a byte of EEPROM.
-u8 avr_peekeeprom(u16 adr);
+uint8_t avr_peekeeprom(uint16_t adr);
//! Read a byte of EEPROM.
-u8 avr_pokeeeprom(u16 adr, u8 val);
+uint8_t avr_pokeeeprom(uint16_t adr, uint8_t val);
//! Is the AVR ready or busy?
-u8 avr_isready();
+uint8_t avr_isready();
//Command codes.
//! Perform a chip erase.
#define STOP 0x21
#define CALL 0x30
#define EXEC 0x31
+#define LIMIT 0x7B /* limit reached */
+#define EXIST 0x7C /* already or doesnt exist */
+#define NMEM 0x7D /* OOM */
#define NOK 0x7E
#define OK 0x7F
--- /dev/null
+/*! \file jscan.h
+ \author Don A. Bailey
+ \brief JSCAN App
+*/
+
+#ifndef JSCAN_H
+#define JSCAN_H
+
+#include "spi.h"
+#include "app.h"
+
+/* app id 'd' */
+#define JSCAN 0x64
+
+/* limits */
+#define JSCAN_LIMIT_PINS 254
+#define JSCAN_DEFAULT_DELAY 1
+
+/* endianness */
+#define JSCAN_ENDIAN_BIG 0
+#define JSCAN_ENDIAN_LITTLE 1
+
+/* commands */
+#define JSCAN_CMD 0x80
+#define JSCAN_CMD_SCAN (JSCAN_CMD + 0)
+#define JSCAN_CMD_ENDIAN (JSCAN_CMD + 1)
+#define JSCAN_CMD_SYNC (JSCAN_CMD + 2)
+#define JSCAN_CMD_ADDPIN (JSCAN_CMD + 3)
+#define JSCAN_CMD_RMPIN (JSCAN_CMD + 4)
+#define JSCAN_CMD_DELAY (JSCAN_CMD + 5)
+#define JSCAN_CMD_PULLUP (JSCAN_CMD + 6)
+#define JSCAN_CMD_LOOPBACK (JSCAN_CMD + 7)
+#define JSCAN_CMD_LISTPIN (JSCAN_CMD + 8)
+#define JSCAN_CMD_RESULTS (JSCAN_CMD + 9)
+
+extern app_t const jscan_app;
+
+#endif
+
#define SPI 0x01
//Pins and I/O
-#define MOSI BIT1
-#define MISO BIT2
-#define SCK BIT3
+#if (platform == donbfet)
+# define MOSI (1 << PA2)
+# define MISO (1 << PA1)
+# define SCK (1 << PA0)
+# define SS (1 << PA3)
+# define TST (1 << PA4)
+# define XRST (1 << PA5)
+#else
+# define MOSI BIT1
+# define MISO BIT2
+# define SCK BIT3
+#endif
#define SETMOSI SPIOUT|=MOSI
#define CLRMOSI SPIOUT&=~MOSI
#define READMISO (SPIIN&MISO?1:0)
//FIXME this should be defined by the platform.
-#define SETTST P4OUT|=TST
-#define CLRTST P4OUT&=~TST
-#define SETRST P2OUT|=RST
-#define CLRRST P2OUT&=~RST
+#if (platform == donbfet)
+# define SETTST PORTA|=(1 << PA4);
+# define CLRTST PORTA&=~(1 << PA4);
+# define SETRST PORTA|=(1 << PA5);
+# define CLRRST PORTA&=~(1 << PA5);
+#else
+# define SETTST P4OUT|=TST
+# define CLRTST P4OUT&=~TST
+# define SETRST P2OUT|=RST
+# define CLRRST P2OUT&=~RST
+#endif
//! Set up the pins for SPI mode.
void spisetup();
--- /dev/null
+#include "platform.h"
+
+#include <avr/io.h>
+#include <util/delay.h>
+
+//! Receive a byte.
+unsigned char serial0_rx(){
+ while( !(UCSR0A & (1 << RXC0)) );
+ return UDR0;
+}
+
+//! Receive a byte.
+unsigned char serial1_rx(){
+ return 0;
+}
+
+//! Transmit a byte.
+void serial0_tx(unsigned char x){
+ while (!(UCSR0A & (1<<UDRE0)) );
+ UDR0 = x;
+}
+
+//! Transmit a byte on the second UART.
+void serial1_tx(unsigned char x){
+}
+
+//! Set the baud rate.
+void setbaud0(unsigned char rate){
+ /* disable briefly */
+ UCSR0B = 0;
+
+ UBRR0L = 4; /* 500,000 baud at 20MHz */
+ //UBRR0L = 1; /* 500,000 baud at 8MHz */
+ //UBRR0L = 103; /* 9600 baud */
+ // XXX UBRR0L = 8; /* 115200 baud ERROR RATE TOO HIGH */
+ UBRR0H = 0;
+
+ UCSR0A = (1 << U2X0); /* double the baud rate */
+ UCSR0C = (3 << UCSZ00); /* 8N1 */
+
+ /* enabling rx/tx must be done after frame/baud setup */
+ UCSR0B = ((1 << TXEN0) | (1 << RXEN0));
+
+ return;
+
+}
+
+//! Set the baud rate of the second uart.
+void setbaud1(unsigned char rate){
+ //http://mspgcc.sourceforge.net/baudrate.html
+ switch(rate){
+ case 1://9600 baud
+
+ break;
+ case 2://19200 baud
+
+ break;
+ case 3://38400 baud
+
+ break;
+ case 4://57600 baud
+
+ break;
+ default:
+ case 5://115200 baud
+
+ break;
+ }
+}
+
+
+void donbfet_init_uart0(){
+ setbaud0(0);
+ _delay_ms(500); //takes a bit to stabilize
+}
+
+void
+led_on()
+{
+ PLEDOUT |= (1 << PLEDPIN);
+}
+
+void
+led_off()
+{
+ PLEDOUT &= ~(1 << PLEDPIN);
+}
+
+void
+donbfet_init()
+{
+ uint8_t x;
+
+ /* explicitly clear interrupts */
+ cli();
+
+ /* move the vectors */
+
+ /* move interrupts from boot flash section */
+ /* NB */
+ /* you MUST use a variable during this process. even highly optimized,
+ * masking the bit, shifting, ANDing, and setting MCUCR will exceed
+ * 4 CPU cycles! set a variable with the desired value for MCUCR and
+ * then set the register once IVCE is enabled
+ */
+ x = MCUCR & ~(1 << IVSEL);
+
+ /* enable change of interrupt vectors */
+ /* NOTE: setting IVCE disables interrupts until the bit is auto-unset
+ * 4 cycles after being set or after IVSEL is written
+ */
+ MCUCR |= (1 << IVCE);
+ MCUCR = x;
+
+ /* disable the watchdog timer; this macro will disable interrupts for us */
+ /* NOTE: ensure that the WDRF flag is unset in the MCUSR or we will spinlock
+ * when the watchdog times out
+ */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* init the USART */
+ donbfet_init_uart0();
+
+ /* set the LED as an output */
+ PLEDDIR |= (1 << PLEDPIN);
+ PLEDOUT |= (1 << PLEDPIN);
+
+ /* explicitly enable interrupts */
+ sei();
+}
+
+void
+donbfet_reboot()
+{
+ MCUSR &= ~(1 << WDRF);
+ wdt_enable(WDTO_15MS);
+ while(1)
+ _delay_ms(127);
+}
+
+void donbfet_init_uart1(){
+}
+
+uint8_t
+donbfet_get_byte(uint16_t v)
+{
+ /* NB */
+ /* we are only passed in a 16bit word. should
+ * be increased to 32bit if we want to handle
+ * far reads as well
+ */
+/* XXX should be far on the 1284P, but there are bugs with flash reads using _far */
+/* XXX until the bugs are figured out (probably my fault?) use _near */
+ return pgm_read_byte_near(v);
+}
+
+int *
+donbfet_ramend(void)
+{
+ /* NB */
+ /* ATmega1284P has 16K SRAM */
+ return (int * )0x4000;
+}
+
+void
+led_toggle(void)
+{
+ led_on();
+ _delay_ms(30);
+ led_off();
+}
+
--- /dev/null
+#include "platform.h"
+
+#include <avr/io.h>
+#include <util/delay.h>
+
+//! Receive a byte.
+unsigned char serial0_rx(){
+ while( !(UCSR0A & (1 << RXC0)) );
+ return UDR0;
+}
+
+//! Receive a byte.
+unsigned char serial1_rx(){
+ return 0;
+}
+
+//! Transmit a byte.
+void serial0_tx(unsigned char x){
+ while (!(UCSR0A & (1<<UDRE0)) );
+ UDR0 = x;
+}
+
+//! Transmit a byte on the second UART.
+void serial1_tx(unsigned char x){
+}
+
+//! Set the baud rate.
+void setbaud0(unsigned char rate){
+ /* disable briefly */
+ UCSR0B = 0;
+
+ UBRR0L = 4; /* 500,000 baud at 20MHz */
+ //UBRR0L = 1; /* 500,000 baud at 8MHz */
+ //UBRR0L = 103; /* 9600 baud */
+ // XXX UBRR0L = 8; /* 115200 baud ERROR RATE TOO HIGH */
+ UBRR0H = 0;
+
+ UCSR0A = (1 << U2X0); /* double the baud rate */
+ UCSR0C = (3 << UCSZ00); /* 8N1 */
+
+ /* enabling rx/tx must be done after frame/baud setup */
+ UCSR0B = ((1 << TXEN0) | (1 << RXEN0));
+
+ return;
+
+}
+
+//! Set the baud rate of the second uart.
+void setbaud1(unsigned char rate){
+ //http://mspgcc.sourceforge.net/baudrate.html
+ switch(rate){
+ case 1://9600 baud
+
+ break;
+ case 2://19200 baud
+
+ break;
+ case 3://38400 baud
+
+ break;
+ case 4://57600 baud
+
+ break;
+ default:
+ case 5://115200 baud
+
+ break;
+ }
+}
+
+
+void donbfet_init_uart0(){
+ setbaud0(0);
+ _delay_ms(500); //takes a bit to stabilize
+}
+
+void
+led_on()
+{
+ PLEDOUT |= (1 << PLEDPIN);
+}
+
+void
+led_off()
+{
+ PLEDOUT &= ~(1 << PLEDPIN);
+}
+
+void
+donbfet_init()
+{
+ uint8_t x;
+
+ /* explicitly clear interrupts */
+ cli();
+
+ /* move the vectors */
+
+ /* move interrupts from boot flash section */
+ /* NB */
+ /* you MUST use a variable during this process. even highly optimized,
+ * masking the bit, shifting, ANDing, and setting MCUCR will exceed
+ * 4 CPU cycles! set a variable with the desired value for MCUCR and
+ * then set the register once IVCE is enabled
+ */
+ x = MCUCR & ~(1 << IVSEL);
+
+ /* enable change of interrupt vectors */
+ /* NOTE: setting IVCE disables interrupts until the bit is auto-unset
+ * 4 cycles after being set or after IVSEL is written
+ */
+ MCUCR |= (1 << IVCE);
+ MCUCR = x;
+
+ /* disable the watchdog timer; this macro will disable interrupts for us */
+ /* NOTE: ensure that the WDRF flag is unset in the MCUSR or we will spinlock
+ * when the watchdog times out
+ */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* init the USART */
+ donbfet_init_uart0();
+
+ /* set the LED as an output */
+ PLEDDIR |= (1 << PLEDPIN);
+ PLEDOUT |= (1 << PLEDPIN);
+
+ /* explicitly enable interrupts */
+ sei();
+}
+
+void
+donbfet_reboot()
+{
+ MCUSR &= ~(1 << WDRF);
+ wdt_enable(WDTO_15MS);
+ while(1)
+ _delay_ms(127);
+}
+
+void donbfet_init_uart1(){
+}
+
+uint8_t
+donbfet_get_byte(uint16_t v)
+{
+ /* NB */
+ /* we are only passed in a 16bit word. should
+ * be increased to 32bit if we want to handle
+ * far reads as well
+ */
+ return pgm_read_byte_near(v);
+}
+
+int *
+donbfet_ramend(void)
+{
+ /* NB */
+ /* ATmega644P has 4K SRAM */
+ return (int * )0x1000;
+}
+
+void
+led_toggle(void)
+{
+ led_on();
+ _delay_ms(30);
+ led_off();
+}
+
--- /dev/null
+/*! \file donbfet.h
+ \author Don A. Bailey
+ \brief Port descriptions for the DonbFET platform.
+*/
+
+/* NB: define default CPU frequency */
+//XXX #define F_CPU 8000000UL
+#define F_CPU 20000000UL
+
+#include <avr/io.h>
+#include <avr/wdt.h>
+#include <avr/boot.h>
+#include <avr/sleep.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include <util/delay.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/* all AVR SRAM starts after I/O mapped memory and registers */
+#define RAMSTART 0x100
+
+#ifndef PB0
+# define PB0 PORTB0
+#endif
+#ifndef PA0
+# define PA0 PORTA0
+#endif
+#ifndef PA1
+# define PA1 PORTA1
+#endif
+#ifndef PA2
+# define PA2 PORTA2
+#endif
+#ifndef PA3
+# define PA3 PORTA3
+#endif
+#ifndef PA4
+# define PA4 PORTA4
+#endif
+#ifndef PA5
+# define PA5 PORTA5
+#endif
+
+//LED on P1.0
+#define PLEDOUT PORTB
+#define PLEDDIR DDRB
+#define PLEDPIN PB0
+
+//Use P3 instead of P5 for target I/O on chips without P5.
+#ifdef msp430x2274
+//#warning "No P5, using P3 instead. Will break 2618 and 1612 support."
+# define P5OUT P3OUT
+# define P5DIR P3DIR
+# define P5IN P3IN
+# define P5REN P3REN
+
+# define SPIOUT P3OUT
+# define SPIDIR P3DIR
+# define SPIIN P3IN
+# define SPIREN P3REN
+#else
+
+# if (platform == donbfet)
+# define SPIOUT PORTA
+# define SPIDIR DDRA
+# define SPIIN PINA
+//# define SPIREN P5REN
+# endif
+#endif
+
+//This is how things used to work, don't do it anymore.
+//#ifdef msp430x1612
+//#define P5REN somedamnedextern
+//#endif
+
+#if (platform == donbfet)
+# define SETSS PORTA|=SS;
+# define CLRSS PORTA&=~SS;
+# define DIRSS DDRA|=SS;
+#else
+//No longer works for Hope badge.
+# define SETSS P5OUT|=BIT0
+# define CLRSS P5OUT&=~BIT0
+# define DIRSS P5DIR|=BIT0;
+#endif
+
+//Used for the Nordic port, !RST pin on regular GoodFET.
+#define SETCE P2OUT|=BIT6
+#define CLRCE P2OUT&=~BIT6
+#define DIRCE P2DIR|=BIT6
+
+// network byte order converters
+#define htons(x) ((((uint16_t)(x) & 0xFF00) >> 8) | \
+ (((uint16_t)(x) & 0x00FF) << 8))
+#define htonl(x) ((((uint32_t)(x) & 0xFF000000) >> 24) | \
+ (((uint32_t)(x) & 0x00FF0000) >> 8) | \
+ (((uint32_t)(x) & 0x0000FF00) << 8) | \
+ (((uint32_t)(x) & 0x000000FF) << 24))
+
+#define ntohs htons
+#define ntohl htonl
+
+extern uint8_t donbfet_get_byte(uint16_t);
+