From 69539bb167246135b1bde3c55dca7d19bc3c7aee Mon Sep 17 00:00:00 2001 From: travisutk Date: Wed, 20 Jul 2011 19:00:33 +0000 Subject: [PATCH] TI Launchpad patch from Peter Lorenzen, edited to ease the mergequake. git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1029 12e2690d-a6be-4b82-a7b7-67c4a43b65c8 --- firmware/Makefile | 53 +++- firmware/apps/chipcon/chipcon.c | 60 ++++- firmware/apps/i2c/i2c.c | 44 +++- firmware/apps/jtag/jtag.c | 8 +- firmware/apps/jtag/jtag430.c | 4 +- firmware/apps/jtag/jtag430x2.c | 2 +- firmware/apps/jtag/openocd.c | 4 +- firmware/apps/monitor/monitor.c | 9 + firmware/apps/smartcard/smartcard.c | 2 +- firmware/apps/spi/spi.c | 4 +- firmware/goodfet.c | 37 ++- firmware/include/i2c.h | 2 +- firmware/include/msp430_serial.h | 135 ++++++++++ firmware/lib/command.c | 3 +- firmware/lib/msp430.c | 20 +- firmware/lib/msp430_serial.c | 374 ++++++++++++++++++++++++++++ firmware/lib/tilaunchpad.c | 298 ++++++++++++++++++++++ firmware/platforms/tilaunchpad.h | 87 +++++++ 18 files changed, 1107 insertions(+), 39 deletions(-) create mode 100644 firmware/include/msp430_serial.h create mode 100644 firmware/lib/msp430_serial.c create mode 100644 firmware/lib/tilaunchpad.c create mode 100644 firmware/platforms/tilaunchpad.h diff --git a/firmware/Makefile b/firmware/Makefile index e3c4ae2..3dcd605 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -1,4 +1,21 @@ + +#platform?=goodfet +#platform?=telosb +#platform?=z1 +#platform?=nhbadge +#platform?=nhbadgeb +#platofrm?=arduino +#platform?=tilaunchpad +platform?=goodfet + + +ifeq ($(platform),tilaunchpad) +mcu?=msp430x1612 +CFLAGS+=-DDEBUG_LEVEL=3 -DDEBUG_START=1 -DINBAND_DEBUG +#CFLAGS+= -Werror +endif + #include `uname`.mak GOODFET?=/dev/tty.usbser* @@ -6,23 +23,16 @@ GOODFET?=/dev/tty.usbser* #BSL?=avrdude -V -F -c stk500v1 -p m328p -b 57600 -P /dev/tty.usbserial-* -U flash:w:blink.hex #For tos-bsl, use --invert-reset --invert-test MSP430BSL?=goodfet.bsl --speed=38400 +JTAG=msp430-jtag #One of these should be defined explicitly. #Default removed because of confusion. -#mcu?=msp430x2274 #mcu?=msp430x2618 #mcu?=msp430x1612 #mcu?=atmega168 mcu?=RUNCONFIG -#platform?=goodfet -#platform?=telosb -#platform?=z1 -#platform?=nhbadge -#platform?=nhbadgeb -#platofrm?=arduino -platform?=goodfet #N.B., gcc WILL NOT BITCH if this file doesn't exist. GCCINC?= @@ -30,7 +40,7 @@ GCCINC?= #GCC?=avr-gcc GCC?=msp430-gcc -T ldscripts/$(mcu).x -CCEXTRA?= -D$(mcu) -D$(platform) -Dplatform=$(platform) -DGCC $(GCCINC) -I include -I platforms +CCEXTRA?= $(CFLAGS) -D$(mcu) -D$(platform) -Dplatform=$(platform) -DGCC $(GCCINC) -I include -I platforms CC=$(GCC) -Wall -Os -fno-strict-aliasing -g -mmcu=$(mcu) $(CCEXTRA) # Available Applications @@ -103,11 +113,22 @@ CC=$(GCC) -Wall -Os -fno-strict-aliasing -g -mmcu=$(mcu) $(CCEXTRA) # config = monitor sbw chipcon nrf ccspi spi jtagarm7 jtag430 jtag430x2 avr # New default. +ifeq ($(platform),tilaunchpad) +config ?= monitor chipcon i2c +else config ?= monitor chipcon spi jtag430 jtag430x2 avr openocd ccspi +endif # Build the needed list of app and lib object files from the config apps= + +ifeq ($(platform),tilaunchpad) +libs= lib/$(platform).o lib/command.o lib/apps.o lib/msp430_serial.o +#libs+=lib/setjmp.o +else libs= lib/$(mcu).o lib/command.o lib/dco_calib.o lib/apps.o lib/msp430.o lib/arduino.o +endif + hdrs= ERR= @@ -323,22 +344,32 @@ run: avrinstall: $(app).hex #to be merged avrdude -V -F -c stk500v1 -p m328p -b 57600 -P $(GOODFET) -U flash:w:$(app).hex + +ifeq ($(platform),tilaunchpad) +install: $(app).hex + $(JTAG) -e -p $(app).hex +verify: + $(JTAG) -v $(app).hex +erase: + $(JTAG) -e $(app).hex +else install: $(app).hex $(MSP430BSL) -e -p $(app).hex installinfo: $(MSP430BSL) -P $(app).hex -p info.txt || true #MSP430F2xx targets only, inelegant. verify: $(MSP430BSL) -P $(app).hex -v $(app).hex +endif dumpinfo: $(MSP430BSL) --dumpinfo +erase: + $(MSP430BSL) -e $(app).c: config builddate appsfiles err $(app): $(libs) $(apps) $(app).hex: $(app) msp430-objcopy goodfet -O ihex goodfet.hex m4s: $(app).hex msp430-objdump -D -m msp430 $(app).hex | m4s init -erase: - $(MSP430BSL) -e clean: rm -f $(app) $(app).hex $(libs) $(apps) lib/apps.c include/config.h include/builddate.h include/apps.h docs: diff --git a/firmware/apps/chipcon/chipcon.c b/firmware/apps/chipcon/chipcon.c index 7ce22b2..96fec22 100644 --- a/firmware/apps/chipcon/chipcon.c +++ b/firmware/apps/chipcon/chipcon.c @@ -50,7 +50,26 @@ app_t const chipcon_app = { //Pins and I/O //MISO and MOSI are the same pin, direction changes. + +#if (platform == tilaunchpad) +/* + * The Launchpad has only pins easily available + * P5.3 TCK SCK (labeled TEST J3-10 J2-17) DC closest to antenna (blue) + * P5.2 IO MISO MOSI (labeled RST J3-8 J2-16) DD next to closer to USB (yellow) + * P3.6 txd1 RST (labeled RXD J3-6 J1-4) next to GND, which is closest to USB (orange) + * P3.7 rxd1 RST (labeled TXD J3-4 J1-3) connect to led1 J1-2 + * + * for a permanent marriage between a TI-Launchpad, move RST to pin48 P5.4 + * (requeries soldering) and use rxd/txd for direct communication with IM-ME dongle. + */ + +#define RST BIT6 // P3.7 +#include +#else // tilaunchpad #define RST BIT0 +#define dputs(s) +#endif // ! tilaunchad + #define MOSI BIT2 #define MISO BIT2 #define SCK BIT3 @@ -69,13 +88,36 @@ app_t const chipcon_app = { #define CLRCLK SPIOUT&=~SCK #define READMISO (SPIIN&MISO?1:0) +#if (platform == tilaunchpad) +# if (SPIDIR != P5DIR) +# error "SPIDIR != P5DIR" +# endif +# if (SPIOUT != P5OUT) +# error "SPIOUT != P5OUT" +# endif +# define SETRST P3OUT|=RST +# define CLRRST P3OUT&=~RST +#else +# define SETRST P3OUT|=RST +# define CLRRST P3OUT&=~RST +#endif + #define CCWRITE SPIDIR|=MOSI #define CCREAD SPIDIR&=~MISO //! Set up the pins for CC mode. Does not init debugger. void ccsetup(){ +#if (platform == tilaunchpad) + dputs("ccsetup"); + SPIOUT|=MOSI+SCK; + SPIDIR|=MOSI+SCK; + P3OUT|=RST; + P3DIR|=RST; + dputs("done ccsetup"); +#else SPIOUT|=MOSI+SCK+RST; SPIDIR|=MOSI+SCK+RST; +#endif //P5REN=0xFF; } @@ -98,7 +140,13 @@ void ccsetup(){ //! Initialize the debugger void ccdebuginit(){ //Port output BUT NOT DIRECTION is set at start. +#if (platform == tilaunchpad) + dputs("ccdebuginit"); + SPIOUT|=MOSI+SCK; + P3OUT|=RST; +#else SPIOUT|=MOSI+SCK+RST; +#endif delay(30); //So the beginning is ready for glitching. @@ -106,7 +154,7 @@ void ccdebuginit(){ //Take RST low, pulse twice, then high. SPIOUT&=~SCK; delay(10); - SPIOUT&=~RST; + CLRRST; delay(10); @@ -122,7 +170,7 @@ void ccdebuginit(){ //delay(0); //Raise !RST. - SPIOUT|=RST; + SETRST; } //! Read and write a CC bit. @@ -207,9 +255,9 @@ void cc_handle_fn( uint8_t const app, break; case STOP://exit debugger //Take RST low, then high. - SPIOUT&=~RST; + CLRRST; CCDELAY(CCSPEED); - SPIOUT|=RST; + SETRST; txdata(app,verb,0); break; case SETUP: @@ -537,13 +585,13 @@ void cc_write_flash_page(u32 adr){ while(!(cc_read_status()&CC_STATUS_CPUHALTED)){ - PLEDOUT^=PLEDPIN;//blink LED while flashing + led_toggle();//blink LED while flashing } //debugstr("Done flashing."); - PLEDOUT&=~PLEDPIN;//clear LED + led_off(); } //! Read the PC diff --git a/firmware/apps/i2c/i2c.c b/firmware/apps/i2c/i2c.c index 85677df..af2c7f1 100644 --- a/firmware/apps/i2c/i2c.c +++ b/firmware/apps/i2c/i2c.c @@ -30,7 +30,7 @@ void i2c_handle_fn( uint8_t const app, app_t const i2c_app = { /* app number */ - I2C, + I2C_APP, /* handle fn */ i2c_handle_fn, @@ -43,13 +43,33 @@ app_t const i2c_app = { "\tturning your GoodFET into a USB-to-i2c adapter.\n" }; -#define SDA TDI -#define SCL TDO - #define I2CDELAY(x) delay(x<<4) //2xx only, need 1xx compat code +#if (platform == tilaunchpad) +// P3.1 SDA +// P3.3 SCL +#define SDA (1<<1) +#define SCL (1<<3) + +#define CLRSDA P3OUT&=~SDA +#define SETSDA P3OUT|=SDA +#define CLRSCL P3OUT&=~SCL +#define SETSCL P3OUT|=SCL + +#define READSDA (P3IN&SDA?1:0) +#define SDAINPUT P3DIR&=~SDA +#define SDAOUTPUT P3DIR|=SDA +#define SCLINPUT P3DIR&=~SCL +#define SCLOUTPUT P3DIR|=SCL +#define SETBOTH P3OUT|=(SDA|SCL) + +#else + +#define SDA TDI +#define SCL TDO + #define CLRSDA P5OUT&=~SDA #define SETSDA P5OUT|=SDA #define CLRSCL P5OUT&=~SCL @@ -57,6 +77,7 @@ app_t const i2c_app = { #define READSDA (P5IN&SDA?1:0) #define SETBOTH P5OUT|=(SDA|SCL) +#endif #define I2C_DATA_HI() SETSDA #define I2C_DATA_LO() CLRSDA @@ -74,7 +95,12 @@ void I2C_Init() //Direction, not value, is used to set the value. //(Pull-up or 0.) +#if (platform == tilaunchpad) + SDAOUTPUT; + SCLOUTPUT; +#else P5DIR|=(SDA|SCL); +#endif //P5REN|=SDA|SCL; @@ -84,6 +110,14 @@ void I2C_Init() I2CDELAY(1); } +#if (platform == tilaunchpad) +void I2C_Exit() +{ + SDAINPUT; + SCLINPUT; +} +#endif + //! Write an I2C bit. void I2C_WriteBit( unsigned char c ) { @@ -110,12 +144,14 @@ unsigned char I2C_ReadBit() I2C_DATA_HI(); I2C_CLOCK_HI(); + SDAINPUT; I2CDELAY(1); unsigned char c = READSDA; I2C_CLOCK_LO(); I2CDELAY(1); + SDAOUTPUT; return c; } diff --git a/firmware/apps/jtag/jtag.c b/firmware/apps/jtag/jtag.c index f072c49..ccddf2f 100644 --- a/firmware/apps/jtag/jtag.c +++ b/firmware/apps/jtag/jtag.c @@ -74,18 +74,18 @@ int in_state(enum eTAPState state) void jtag_reset_target() { SETRST; - PLEDOUT^=PLEDPIN; + led_toggle(); CLRRST; - PLEDOUT^=PLEDPIN; + led_toggle(); } //! Clock the JTAG clock line void jtag_tcktock() { CLRTCK; - PLEDOUT^=PLEDPIN; + led_toggle(); SETTCK; - PLEDOUT^=PLEDPIN; + led_toggle(); } //! Goes through test-logic-reset and ends in run-test-idle diff --git a/firmware/apps/jtag/jtag430.c b/firmware/apps/jtag/jtag430.c index edf18ec..8e6fe03 100644 --- a/firmware/apps/jtag/jtag430.c +++ b/firmware/apps/jtag/jtag430.c @@ -411,9 +411,9 @@ void jtag430_handle_fn(uint8_t const app, while((i=jtag430_readmem(0xff0))==0xFFFF){ debugstr("Reconnecting to target MSP430."); jtag430x2_start(); - PLEDOUT^=PLEDPIN; + led_toggle(); } - PLEDOUT&=~PLEDPIN; + led_off(); switch(verb){ diff --git a/firmware/apps/jtag/jtag430x2.c b/firmware/apps/jtag/jtag430x2.c index 67ef45b..0236662 100644 --- a/firmware/apps/jtag/jtag430x2.c +++ b/firmware/apps/jtag/jtag430x2.c @@ -87,7 +87,7 @@ void jtag430x2_writemem(unsigned long adr, SETTCLK; //init state }else{ - while(1) PLEDOUT^=PLEDPIN; //loop if locked up + while(1) led_toggle(); //loop if locked up } } diff --git a/firmware/apps/jtag/openocd.c b/firmware/apps/jtag/openocd.c index feb8e57..6417e54 100644 --- a/firmware/apps/jtag/openocd.c +++ b/firmware/apps/jtag/openocd.c @@ -69,10 +69,10 @@ void openocd_led(int led) { if (led) /* turn the LED on */ - PLEDDIR |= PLEDPIN; + led_on(); else /* turn the LED off */ - PLEDOUT &= ~PLEDPIN; + led_off(); } //! resets the device/JTAG logic diff --git a/firmware/apps/monitor/monitor.c b/firmware/apps/monitor/monitor.c index 39833d4..54d9cd0 100644 --- a/firmware/apps/monitor/monitor.c +++ b/firmware/apps/monitor/monitor.c @@ -7,6 +7,11 @@ #include "platform.h" #include "monitor.h" #include "builddate.h" +#if (platform == tilaunchpad) +#include +extern jmp_buf warmstart; + +#endif #define MONITOR_APP @@ -174,10 +179,14 @@ void monitor_ram_pattern() } txdata(0x00,0x90,0); +#if (platform == tilaunchpad) + longjmp(warmstart,1); +#else //Reboot #ifdef MSP430 asm("br &0xfffe"); #endif +#endif } //! Return the number of contiguous bytes 0xBEEF, to measure RAM usage. diff --git a/firmware/apps/smartcard/smartcard.c b/firmware/apps/smartcard/smartcard.c index 93beb3a..566081b 100644 --- a/firmware/apps/smartcard/smartcard.c +++ b/firmware/apps/smartcard/smartcard.c @@ -86,7 +86,7 @@ void smartcard_handle_fn( uint8_t const app, delay(5); SCTOCK; - PLEDOUT^=PLEDPIN; + led_toggle(); if(SCIN!=foo){ foo=SCIN; } diff --git a/firmware/apps/spi/spi.c b/firmware/apps/spi/spi.c index 1cb12e5..c880e8c 100644 --- a/firmware/apps/spi/spi.c +++ b/firmware/apps/spi/spi.c @@ -377,8 +377,8 @@ void spi_handle_fn( uint8_t const app, SETSS; //Raise !SS to end transaction. while(spiflash_status()&0x01)//while busy - PLEDOUT^=PLEDPIN; - PLEDOUT&=~PLEDPIN; + led_toggle(); + led_off(); txdata(app,verb,0); break; diff --git a/firmware/goodfet.c b/firmware/goodfet.c index 5f30c77..e75bda5 100644 --- a/firmware/goodfet.c +++ b/firmware/goodfet.c @@ -12,6 +12,13 @@ #include "apps.h" #include "glitch.h" +#if (platform == tilaunchpad) +#include +jmp_buf warmstart; +void coldstart(); +#include "msp430_serial.h" +#endif + #define RESET 0x80 // not a real app -- causes firmware to reset #define DEBUGAPP 0xFF @@ -45,7 +52,7 @@ void handle(uint8_t const app, int i; //debugstr("GoodFET"); - PLEDOUT&=~PLEDPIN; + led_off(); // find the app and call the handle fn for(i = 0; i < num_apps; i++){ @@ -74,8 +81,25 @@ int main(void) unsigned long len; // MSP reboot count for reset input & reboot function located at 0xFFFE volatile unsigned int reset_count = 0; +#if (platform == tilaunchpad) + int ret=0; + + //ret = setjmp(warmstart);// needs to be here since context from init() would be gone + warmstart: + if (ret == 0) { + coldstart(); // basic hardware setup, clock to TUSB3410, and enable + } else if (ret == 2) { + dputs("\nalmost BSL only one RTS change\n"); + } else if (ret > 2) { // reset released after more than two tst transisitions + // We could write a BSL, a nice exercise for a Sunday afternoon. + dputs("\nBSL\n"); + //call_BSL(); // once you are done uncomment ;-) + } else { // we come here after DTR high (release reset) + dputs("\nWarmstart\n"); + } +#else void (*reboot_function)(void) = (void *) 0xFFFE; - +#endif init(); txstring(MONITOR,OK,"http://goodfet.sf.net/"); @@ -102,7 +126,16 @@ int main(void) // WDTCTL = WDTPW + WDTCNTCL + WDTSSEL + 0x00; // but instead we'll jump to our reboot function pointer #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 (*reboot_function)(); +#endif #else debugstr("Rebooting not supported on this platform."); #endif diff --git a/firmware/include/i2c.h b/firmware/include/i2c.h index 5c41c60..5f52b0c 100644 --- a/firmware/include/i2c.h +++ b/firmware/include/i2c.h @@ -8,7 +8,7 @@ #include "app.h" -#define I2C 0x02 +#define I2C_APP 0x02 extern app_t const i2c_app; diff --git a/firmware/include/msp430_serial.h b/firmware/include/msp430_serial.h new file mode 100644 index 0000000..e8ffb2f --- /dev/null +++ b/firmware/include/msp430_serial.h @@ -0,0 +1,135 @@ +#ifndef _msp430_serial_h +#define _msp430_serial_h +/* Name: msp430_serial_h + * Tabsize: 8 + * Copyright: (c) 2011 by Peter@Lorenzen.us + * License: [BSD]eerware + */ + +#include + +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef NULL +# define NULL ((void *) 0) +#endif + +#define FIFO_SZ 64 // power of 2 +typedef struct fifo { + uint8_t i; + uint8_t o; + volatile uint8_t count, empty; + uint8_t b[FIFO_SZ]; // buffer +} fifo_t; + +extern fifo_t fiforx0; +extern fifo_t fifotx0; +extern fifo_t fiforx1; +extern fifo_t fifotx1; +extern fifo_t *rxfp0; +extern fifo_t *txfp0; +extern fifo_t *rxfp1; +extern fifo_t *txfp1; + +void serputc(char c, fifo_t *fp); +void serputs(char *cpt, fifo_t *fp); +void serputb(char c, fifo_t *fp); +void serputw(int w, fifo_t *fp); +int sergetc(fifo_t *fp); +int seravailable(fifo_t *fp); +void serflush(fifo_t *fp); +void ser0_init(int baud, fifo_t *rd, fifo_t *wr); +void ser1_init(int baud, fifo_t *rd, fifo_t *wr); +void serclear(fifo_t *fp); + +#ifdef INBAND_DEBUG +#if (DEBUG_LEVEL > 0) +extern char dlevel; +void dputc(char c); +void dputs(char *str); +void dputb(char c); +void dputw(int w); +#else +# define dputc(c) +# define dputs(s) +# define dputb(b) +# define dputw(w) +#endif +# define dflush() +# define ddflush() +# define dddflush() +#if (DEBUG_LEVEL > 1) +# define ddputc(c) if (dlevel>1) dputc(c) +# define ddputs(s) if (dlevel>1) dputs(s) +# define ddputb(b) if (dlevel>1) dputb(b) +# define ddputw(w) if (dlevel>1) dputw(w) +#else +# define ddputc(c) +# define ddputs(s) +# define ddputb(b) +# define ddputw(w) +#endif + +#if (DEBUG_LEVEL > 2) +# define dddputc(c) if (dlevel>2) dputc(c) +# define dddputs(s) if (dlevel>2) dputs(s) +# define dddputb(b) if (dlevel>2) dputb(b) +# define dddputw(w) if (dlevel>2) dputw(w) +#else +# define dddputc(c) +# define dddputs(s) +# define dddputb(b) +# define dddputw(w) +#endif +#else + +// we use fp1 for debug output +#if (DEBUG_LEVEL > 0) +extern char dlevel; + +# define dputc(c) if (dlevel) serputc(c,txfp1) +# define dputs(s) if (dlevel) serputs(s,txfp1) +# define dputb(b) if (dlevel) serputb(b,txfp1) +# define dputw(w) if (dlevel) serputw(w,txfp1) +# define dflush() if (dlevel) serflush(txfp1) +#else +# define dputc(c) +# define dputs(s) +# define dputb(b) +# define dputw(w) +# define dflush() +#endif +#if (DEBUG_LEVEL > 1) +# define ddputc(c) if (dlevel>1) serputc(c,txfp1) +# define ddputs(s) if (dlevel>1) serputs(s,txfp1) +# define ddputb(b) if (dlevel>1) serputb(b,txfp1) +# define ddputw(w) if (dlevel>1) serputw(w,txfp1) +# define ddflush() if (dlevel>1) serflush(txfp1) +#else +# define ddputc(c) +# define ddputs(s) +# define ddputb(b) +# define ddputw(w) +# define ddflush() +#endif + +#if (DEBUG_LEVEL > 2) +# define dddputc(c) if (dlevel>2) serputc(c,txfp1) +# define dddputs(s) if (dlevel>2) serputs(s,txfp1) +# define dddputb(b) if (dlevel>2) serputb(b,txfp1) +# define dddputw(w) if (dlevel>2) serputw(w,txfp1) +# define dddflush() if (dlevel>2) serflush(txfp1) +#else +# define dddputc(c) +# define dddputs(s) +# define dddputb(b) +# define dddputw(w) +# define dddflush() +#endif +#endif + +#endif diff --git a/firmware/lib/command.c b/firmware/lib/command.c index 92c0b4c..7c57798 100644 --- a/firmware/lib/command.c +++ b/firmware/lib/command.c @@ -151,7 +151,7 @@ void prep_timer() #warning "Function unimplemented for this platform." #endif } - +#if (platform != tilaunchpad) //! Delay for specified number of milliseconds (given 16 MHz clock) void delay_ms( unsigned int ms ) { @@ -198,3 +198,4 @@ void delay_ticks( unsigned int num_ticks ) debugstr("delay_ticks unimplemented"); #endif } +#endif diff --git a/firmware/lib/msp430.c b/firmware/lib/msp430.c index 3a71e14..1684f59 100644 --- a/firmware/lib/msp430.c +++ b/firmware/lib/msp430.c @@ -13,14 +13,30 @@ #include "apps.h" #include "glitch.h" +void led_init() +{ + PLEDDIR |= PLEDPIN; +} +void led_on() +{ + PLEDOUT |= PLEDPIN; +} +void led_off() +{ + PLEDOUT&=~PLEDPIN; + +} +void led_toggle() +{ +} //! Initialize MSP430 registers and all that jazz. void msp430_init(){ WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer //LED out and on. - PLEDDIR |= PLEDPIN; - PLEDOUT &= ~PLEDPIN; + led_init(); + led_off(); /* P5.0 out and low; this is chosen for the PIC app (in which P5.0 diff --git a/firmware/lib/msp430_serial.c b/firmware/lib/msp430_serial.c new file mode 100644 index 0000000..9a9885d --- /dev/null +++ b/firmware/lib/msp430_serial.c @@ -0,0 +1,374 @@ +/* Name: serial_io.c + * Tabsize: 8 + * Copyright: (c) 2011 by Peter@Lorenzen.us + * License: [BSD]eerware + * serput{c,s} sergetc functionality as on UNIX + */ + +#include "platform.h" +#include +#include +#include +#include "msp430_serial.h" + +#if (DEBUG_LEVEL > 0) +#ifdef DEBUG_START +char dlevel = DEBUG_START; +#else +char dlevel = DEBUG_LEVEL; +#endif +#ifdef INBAND_DEBUG +#include "command.h" +#endif +#endif + +fifo_t fiforx0, fifotx0; +fifo_t fiforx1, fifotx1; +fifo_t *rxfp0; // NULL not in use +fifo_t *txfp0; // NULL not in use +fifo_t *rxfp1; // NULL not in use +fifo_t *txfp1; // NULL not in use + +void fifo_init(fifo_t * fp) +{ + fp->i = 0; + fp->o = 0; + fp->count = 0; + fp->empty = 1; +} + +static void fifo_advance(uint8_t * ptr) +{ + if (*ptr == (FIFO_SZ - 1)) { + *ptr = 0; + } else { + (*ptr)++; + } +} + +static void fifo_wr(fifo_t * fp, char c) +{ + fp->b[fp->i] = c; + _DINT(); // only need to disable tx irq for this stream + fifo_advance(&fp->i); + fp->count++; + _EINT(); +} + +static uint8_t fifo_rd(fifo_t * fp) // only called if count>0 +{ + uint8_t c = fp->b[fp->o]; + _DINT(); // only need to disable tx irq for this stream + fifo_advance(&fp->o); + fp->count--; + _EINT(); + return c; +} + +//http://mspgcc.sourceforge.net/baudrate.html +/** TI lauchpad and EZ430/FETUIF with 12MHz crystal */ +#if (platform == tilaunchpad) +uint8_t bauds[6][3] = { + {0x68, 0x00, 0x04} // 0 - 12000000Hz 115273bps + , {0xE2, 0x04, 0x00} // 1 - 12000000Hz 9600bps + , {0x71, 0x02, 0x00} // 2 - 12000000Hz 19200bps + , {0x38, 0x01, 0x55} // 3 - 12000000Hz 38400bps + , {0xD0, 0x00, 0x4A} // 4 - 12000000Hz 57581bps + , {0x68, 0x00, 0x04} // 5 - 12000000Hz 115273bps +}; +#else +uint8_t bauds[6][3] = { + {0x20, 0x00, 0x00} // 0 - 3683400Hz 115106bps + , {0x7F, 0x01, 0x5B} // 1 - 3683400Hz 9599bps + , {0xBF, 0x00, 0xF7} // 2 - 3683400Hz 19194bps + , {0x5F, 0x00, 0xBF} // 3 - 3683400Hz 38408bps + , {0x40, 0x00, 0x00} // 4 - 3683400Hz 57553bps + , {0x20, 0x00, 0x00} // 5 - 3683400Hz 115106bps +}; +#endif + +void setbaud0(uint8_t rate) +{ + UBR00 = bauds[rate][0]; + UBR10 = bauds[rate][1]; + UMCTL0 = bauds[rate][2]; +} + +void setbaud1(uint8_t rate) +{ + UBR01 = bauds[rate][0]; + UBR11 = bauds[rate][1]; + UMCTL1 = bauds[rate][2]; +} + +// we assume rx and tx is always supplied, so no check +void ser0_init(int baud, fifo_t * rx, fifo_t * tx) +{ + rxfp0 = rx; + txfp0 = tx; + P3DIR &= ~BIT5; // Select P35 for input (UART0RX) + P3SEL |= BIT4 | BIT5; // P3.4,5 = USART0 TXD/RXD + P3DIR |= BIT4; + + UCTL0 = SWRST | CHAR; /* 8-bit character, UART mode */ + ME1 &= ~USPIE0; // USART1 SPI module disable + UTCTL0 = SSEL1; /* UCLK = MCLK */ + + setbaud0(baud); + + ME1 &= ~USPIE0; /* USART1 SPI module disable */ + ME1 |= (UTXE0 | URXE0); /* Enable USART1 TXD/RXD */ + + UCTL0 &= ~SWRST; + + //U0TCTL |= URXSE; // XXX Clear pending interrupts before enable!!! + fifo_init(rx); + fifo_init(tx); + + IE1 |= UTXIE0; // Enable USART0 TX interrupt + IE1 |= URXIE0; // Enable USART0 RX interrupt + + P1DIR |= DSR | CTS; + P1OUT &= ~(DSR | CTS); // We are On and we are ready +} + +// we can use uart1 tx for debug messages, using rx bit for something else +// or we can use full uart1 for pass through +// or not uart1 functions at all, +void ser1_init(int baud, fifo_t * rx, fifo_t * tx) +{ + rxfp1 = rx; + txfp1 = tx; + if (rx) { // RX enabled + P3SEL |= BIT7; // Select P37 for UART1 RX function + P3DIR &= ~BIT7; // P37 is input + } else { + P3SEL &= ~BIT7; // No UART1 RX, can be used as a bit port + } + if (tx) { // TX enabled + P3SEL |= BIT6; // Select P36 for UART1 TX function + P3DIR |= BIT6; // P36 is output UART1 TX + } else { + P3SEL &= ~BIT6; // No UART1 TX, can be used as a bit port + } + UCTL1 = SWRST | CHAR; // 8-bit character, UART mode stop UART state machine + if (rx || tx) { // RX or TX enabled + ME2 &= ~USPIE1; // USART1 SPI module disable + } + UTCTL1 = SSEL1; // UCLK = MCLK + + //U1TCTL |= URXSE; // XXX Clear pending interrupts before enable!!! + if (rx) { // RX enabled + ME2 |= URXE1; // Enable USART1 RX + fifo_init(rx); + } + if (tx) { // TX enabled + ME2 |= UTXE1; // Enable USART1 TXD + fifo_init(tx); + } + + setbaud1(baud); // we set it even when disabling uart1 - who cares + + UCTL1 &= ~SWRST; // enable UART state machine + if (tx) { // TX enabled + IE2 |= UTXIE1; // Enable USART1 TX interrupt + } else { + IE2 &= ~UTXIE1; // Disable USART1 TX interrupt + } + if (rx) { // RX enabled + IE2 |= URXIE1; // Enable USART1 RX interrupt + } else { + IE2 &= ~URXIE1; // Disable USART1 TX interrupt + } +} + + +int seravailable(fifo_t * fp) +{ + return fp->count; +} + +void serflush(fifo_t * fp) +{ + while (seravailable(fp) > 0) { + delay_ms(1); + } +} + +int sergetc(fifo_t * fp) +{ + int c; + if (fp == NULL) + return -1; + if (fp->count) { + c = fifo_rd(fp); + } else { + fp->empty = TRUE; + c = -1; + } + return c; +} + +void serclear(fifo_t *fp) +{ + while (seravailable(fp) > 0) { + sergetc(fp); + } +} + +#ifdef INBAND_DEBUG +// send debug messages over USB-serial link encapsulated in the goodfet protocol +void dputc(char c) +{ + char two[2]; + two[0]=c; + two[1]=0; + debugstr(two); +} + +void dputs(char *str) +{ + debugstr(str); +} +void dputb(char c) +{ + debugbytes(&c,1); +} + +void dputw(int w) +{ + debugbytes((char *)&w,2); +} +#else +// defines in msp430_serial.h resolves to the functions below on txfp1 +#endif + +void serputc(char c, fifo_t * fp) +{ + if (fp == NULL) + return; + while (seravailable(fp) == FIFO_SZ) { + } + fifo_wr(fp, c); // magic is in count-- indivisible, do not optimize + if (fp->empty && fp->count) { // buffer had been empty + fp->empty = FALSE; + c = fifo_rd(fp); + if (fp == txfp0) { + TXBUF0 = c; + } else { + TXBUF1 = c; + } + } +} + +void serputs(char *cpt, fifo_t * fp) +{ + while (*cpt) { + serputc(*cpt++, fp); + } +} + +char hex2c(char i) +{ + i &=0x0f; + return i > 9 ? 'a' + i - 10 : '0' + i; +} + +void serputb(char c, fifo_t * fp) +{ + serputc(hex2c(c>>4), fp); + serputc(hex2c(c), fp); +} + +void serputw(int w, fifo_t * fp) +{ + serputb(w >> 8, fp); + serputb(w & 0xff, fp); +} + +#if (DEBUG_LEVEL>2) +char *dddlog_input(char c) +{ + static char buf[7]; + int n = rxfp0->o; + buf[0]='<'; + buf[1]=hex2c(c>>4); + buf[2]=hex2c(c); + buf[3]='>'; + buf[4]=hex2c(n>>4); + buf[5]=hex2c(n); + buf[6]=0; + return buf; +} +#endif +// These is what goodfet uses +uint8_t serial0_rx() +{ + uint8_t c; + while (seravailable(rxfp0) == 0) { // wait for data to be available + // FIXME we should sleep + } + c = sergetc(rxfp0); + dddputs(dddlog_input(c)); + return c; +} + +uint8_t serial1_rx() +{ + uint8_t c; + while ((seravailable(rxfp1)) == 0) { // wait for data to be available + // FIXME we should sleep + } + c = sergetc(rxfp1); + return c; +} + +void serial0_tx(uint8_t x) +{ + serputc(x, txfp0); +} + +void serial1_tx(uint8_t x) +{ + serputc(x, txfp1); +} + +//Interrupt routines + +interrupt(UART0RX_VECTOR) UART0_RX_ISR(void) +{ + led_toggle(); + rxfp0->b[rxfp0->i] = RXBUF0; + fifo_advance(&rxfp0->i); + rxfp0->count++; +} + +interrupt(UART1RX_VECTOR) UART1_RX_ISR(void) +{ + led_toggle(); + rxfp1->b[rxfp1->i] = RXBUF1; + fifo_advance(&rxfp1->i); + rxfp1->count++; +} + +interrupt(UART0TX_VECTOR) UART0_TX_ISR(void) +{ + if (txfp0->count) { + TXBUF0 = txfp0->b[txfp0->o]; + fifo_advance(&txfp0->o); + txfp0->count--; + } else { + txfp0->empty = TRUE; + } +} + +interrupt(UART1TX_VECTOR) UART1_TX_ISR(void) +{ + if (txfp1->count) { + TXBUF1 = txfp1->b[txfp1->o]; + fifo_advance(&txfp1->o); + txfp1->count--; + } else { + txfp1->empty = TRUE; + } +} diff --git a/firmware/lib/tilaunchpad.c b/firmware/lib/tilaunchpad.c new file mode 100644 index 0000000..f858f39 --- /dev/null +++ b/firmware/lib/tilaunchpad.c @@ -0,0 +1,298 @@ +//! tilaunchpad clock and I/O definitions + +// serial io stuff moved to msp430_serial.c +// serial is common for the different versions of msp430 so it makes sense + +#include "platform.h" +#include +#include +#include + +#define MSP430_CPU_SPEED 6000000UL +#include +#include "msp430_serial.h" +extern jmp_buf warmstart; +void coldstart(); +#define USE_NMI_RESET_IRQ + +static void delay_1us() +{ + // 6 Mhz, 6000000 cycles/sec, 6000 cycles/msec, 6 cycles/usec + // 6 cycles = 1 usec + // asummung loop wil be 3 cycles + //asm(" nop"); // 1 cycle + asm(" nop"); // 1 cycle + asm(" nop"); // 1 cycle + asm(" nop"); // 1 cycle +} + +void delay_us(unsigned int us) +{ + while (us) { + delay_1us(); + us--; + } +} + +void delay_ms(unsigned int ms) +{ + while (ms) { + ms--; + delay_us(1000); + } +} + +void delay_sec(unsigned int s) +{ + while (s) { + s--; + delay_ms(1000); + } +} + +static char led_pin = 0; // since we are short on pins we might have LED on different pin +static char led_last; +// led_pin=0 is disabled +// BIT2 and BIT3 is on port 5 SBWDIO SBWTCK +// BIT6 and BIT7 os on port 3 BRDRX BRDTX +void led_init(char pin) +{ + ddputs("led="); + if (pin & BIT2) { + ddputs("P5.2"); + led_pin = BIT2; + P5DIR |= led_pin; + } else if (pin & BIT3) { + ddputs("P5.3"); + led_pin = BIT3; + P5DIR |= BIT3; + } else if (pin & BIT6) { + ddputs("P3.6"); + led_pin = BIT6; + P3SEL &= ~BIT6; // do not use as uart1 + P3DIR |= BIT6; + } else if (pin & BIT7) { + ddputs("P3.7"); + led_pin = BIT7; + P3SEL &= ~BIT7; // do not use as uart1 + P3DIR |= BIT7; + } else { + led_pin = 0; + ddputs("disabled"); + } +} + +void led_on() // 0 will disable, but it is up to the application to setup new use +{ +// dddputs("led_on="); +// dddputb(led_pin); + if (led_pin & BIT2) { + P5OUT |= BIT2; + } else if (led_pin & BIT3) { + P5OUT |= BIT3; + } else if (led_pin & BIT6) { + P3OUT |= BIT6; + } else if (led_pin & BIT7) { + P3OUT |= BIT7; + } + led_last = 1; +} + +void led_off() +{ + //dddputs("led_off="); + //dddputb(led_pin); + if (led_pin & BIT2) { + P5OUT &= ~BIT2; + } else if (led_pin & BIT3) { + P5OUT &= ~BIT3; + } else if (led_pin & BIT6) { + P3OUT &= ~BIT6; + } else if (led_pin & BIT7) { + P3OUT &= ~BIT7; + } + led_last = 0; +} + +void led_toggle() +{ + if (led_last) { + led_off(); + } else { + led_on(); + } +} + +void led_blink(int n) // long - n shorts +{ + int i; + return; + led_off(); + delay_ms(200); + led_on(); + delay_ms(500); + for (i = 0; i < n; i++) { + led_off(); + delay_ms(100); + led_on(); + delay_ms(150); + } + led_off(); +} + +void check_usb2serial() +{ + //ddputs("usb2serial "); + led_init(SBWTCK); // we will use TCK for LED + P5DIR &= ~SBWDIO; // input + + led_on(); // we will use TCK for LED + if ((P5IN & SBWDIO) == 0) { // TCK != DIO + led_init(0); // no led + dputs("low no usb2serial"); + return; + } + led_off(); // we will use TCK for LED + if (P5IN & SBWDIO) { // TCK != DIO + led_init(0); // no led + dputs("high no usb2serial"); + return; + } + // TCK is jumpered to DIO, lets start working as USB-serial converter. + serflush(txfp0); + serflush(txfp1); + delay_ms(100); + dputs("Serial pass through\n"); + serputs("Serial pass through\n", txfp0); + while (1) { + char c; + if (seravailable(rxfp0) > 0) { + c=sergetc(rxfp0); + serputc( c, txfp1); + } + if (seravailable(rxfp1) > 0) { + c=sergetc(rxfp1); + serputc( c, txfp0); + } + // FIXME we should sleep + } +} + +char rts_change = 1; // we cannot return 0 in longjmp so we take 1 + +interrupt(PORT1_VECTOR) POSRT1_ISR(void) +{ + if (P1IFG & RTS) { + if ((P1IN & DTR) == 0) { + rts_change++; + if (rts_change > 10) { // just there is no wrap-around + rts_change = 10; + } + } else { + rts_change = 1; + } + P1IFG &= ~RTS; // clear irq + } + if (P1IFG & DTR) { + int i; + P1IFG &= ~DTR; // clear irq + + for (i=0; (P1IN & DTR) == 0;i++) { // wait for DTR high + if (i>10000) { + i=10000; + } + } + if (i>5000) { //avoid spikes + longjmp(warmstart, rts_change); + } + } +} + +#ifdef USE_NMI_RESET_IRQ +// A reset is warmstart, ie. do not reset TUSB3410 +// to use this wire a reset switch or connect TUSB3410 DTR to RST/NMI +// for development it is conveenient ot implement a reset function +interrupt(NMI_VECTOR) NMI_ISR(void) +{ + IFG1 &= ~NMIIFG; + led_toggle(); + dputs("NMI(RESET)\n"); + dflush(); + longjmp(warmstart, rts_change); +} +#endif +// TI lauchpad has 12 Mhz X-tal on XT2 which also is the base clock for the TUSB34010 +// For Launchpad and probably EZ430/FETUIF +// EZ430/FETUIF may need BCSCTL2 = SELM1 | DIVM1 | SELS; +void coldstart() +{ + _DINT(); +#ifdef USE_NMI_RESET_IRQ + WDTCTL = WDTPW + WDTHOLD + WDTNMI; // Stop WDT, deactivate RESET + //IE1 |= NMIIE; // msp430f1612.pdf page 13 +#else + WDTCTL = WDTPW + WDTHOLD; // Stop WDT +#endif + //led_init(SBWTCK); + led_init(0); + led_off(); +// reset for TUSB3410 + P4OUT &= ~BIT6; // reset TUSB3410 + P4DIR |= BIT6; +// 12 Mhz on XT2 + BCSCTL1 &= ~0x80; // turn on XT2 oscillator + do { // delay for X-tal to settle + IFG1 &= ~OFIFG; + delay_us(100); // wait at least 50 usec + } while (IFG1 & OFIFG); + //BCSCTL2 = SELM_2 | DIVM_1 | SELS | DIVS_0; // 6Mhz MCLK=XT2/2 SMCLK=XT2 + BCSCTL2 = SELM_2 | DIVM_2 | SELS | DIVS_0; // 3Mhz MCLK=XT2/4 SMCLK=XT2 +// Disable eeprom P3.1 SDA P3.3 SCL + P3OUT &= ~(BIT1 | BIT3); // pull dcl and sda down + P3DIR |= BIT1 | BIT3; +// generate 12 Mhz clock for TUSB3410 + P5SEL |= BIT5; // P5.5 is SMCLK to TUSG3410 + P5DIR |= BIT5; // P5.5 is output +// release reset for TUSB3410 + delay_ms(100); + P4OUT &= ~BIT6; // release reset to TUSB3410 + P4DIR &= ~BIT6; // and release port TUSB3410 +// P1.3 RTS input, P1.4 DTR input can generate IRQ + P1DIR &= ~(RTS | DTR); // input + P1SEL &= ~(RTS | DTR); // no special funtions + P1IES &= ~RTS; // low to high + P1IES |= DTR; // high to low + P1IFG &= ~(RTS | DTR); // clear irqs if any, to avoid instant irq + P1IE |= RTS | DTR; // enable IRQ on pin 3,4 + IE1 |= NMIIE; // msp430f1612.pdf page 13 + ser0_init(0, &fiforx0, &fifotx0); + //ser1_init(0, &fiforx1, &fifotx1); + ser1_init(0, NULL, NULL); + _EINT(); // now we can print + dputs("->coldstart<-\n"); + led_blink(4); + led_on(); // led comes on after the very basic setup is done +} + +void msp430_init() +{ +#ifdef USE_NMI_RESET_IRQ + WDTCTL = WDTPW + WDTHOLD + WDTNMI; // Stop WDT, deactivate RESET + //IFG1 &= ~NMIIFG; + IE1 |= NMIIE; // msp430f1612.pdf page 13 +#else + WDTCTL = WDTPW + WDTHOLD; // Stop WDT +#endif + serclear(rxfp0); + ddputs("msp430_init\n"); + led_blink(10); + + check_usb2serial(); // configure as USB-serial if jumper RST-TEST + led_blink(2); + led_on(); +} + +//! Initialization is correct. +void msp430_init_dco_done() +{ +} diff --git a/firmware/platforms/tilaunchpad.h b/firmware/platforms/tilaunchpad.h new file mode 100644 index 0000000..13a2572 --- /dev/null +++ b/firmware/platforms/tilaunchpad.h @@ -0,0 +1,87 @@ +/*! \file tilaunchpad.h + \author Peter Lorenzen + \brief Port descriptions for the TI-launchpad platform. +// Port setup on TI Launchpad +// P1.3 RTS input +// P1.4 DTR input +// P1.5 DSR output +// P1.6 CTS output +// P2.4 P4.7 P5.1 P5.2 SBWDIO 47k pull-up +// P3.1 SDA +// P3.3 SCL +// P3.4 TXD0 to TUSB3410 +// P3.5 RXD0 to TUSB3410 +// P3.6 TXD1 BTXD +// P3.7 RXD1 BRXD +// P4.6 Reset to TUSB3410 +// P4.7 P2.4 P5.1 P5.2 SBWDIO 47k pull-up +// P5.1 P4.7 P2.4 P5.2 SBWDIO 47k pull-up +// P5.2 P4.7 P2.4 P5.1 SBWDIO 47k pull-up labelled RST +// P5.3 SBWTCK 47k pull-down labelled TEST +// P5.5 SMCLK 12 Mhz send to TUSG3410 + +The Launchpad has only four pins easily available +but this is fine for f.ex chipcon +P5.3 TCK SCK +P5.2 IO MISO MOSI +P3.7 rxd1 RST +P3.6 txd1 used for led in chipcon application + +P2.4 could probably be made available without too much destruction +a normal goodfet has +Port SPI JTAG +----+----+------ +P5.0 SS TMS +P5.1 MOSI TDI TCLK +P5.2 MISO TDO +P5.2 SCK TCK + +//These are not on P5 +P2.6 RST +P4.0 TST + +P1.0 LED + +*/ +#define TI_LAUNCHPAD 1 + +#include +#include +#include + +// Here is how I try to remember rs232 signaling +// think of halfduplex rs485, and this makes total sense. +#define DTR BIT4 // -> Minicom has opened the device in handshake on mode +#define DSR BIT5 // <- TI Launchpad signals back that it is turned ON +#define RTS BIT3 // -> Minicom request control of rs485 bus +#define CTS BIT6 // <- we reply yes we got the rs485 bus - just carry on on + +#define SBWDIO BIT2 +#define SBWTCK BIT3 + +#define SPIOUT P5OUT +#define SPIDIR P5DIR +#define SPIIN P5IN +#define SPIREN P5REN + +// 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 + + +void delay_us(unsigned int us); +void delay_ms(unsigned int ms); +void delay_sec(unsigned int s); +void led_init(char pin); +void led_on(); +void led_off(); +void led_toggle(); +void led_blink(int n); // long - n shorts + -- 2.20.1