diff --git a/Makefile b/Makefile index aecfe17..b68b8e2 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ ASM_REL = $(ASM_SRC:.asm=.rel) ASM_RST = $(ASM_SRC:.asm=.rst) ASM_SYM = $(ASM_SRC:.asm=.sym) -PROGS = CCBootloader.hex +PROGS = CCBootloader.hex CCBootloader-rfcat-chronosdongle.hex CCBootloader-rfcat-donsdongle.hex CCBootloader-rfcat-ys1.hex PCDB = $(PROGS:.hex=.cdb) PLNK = $(PROGS:.hex=.lnk) PMAP = $(PROGS:.hex=.map) @@ -63,8 +63,40 @@ all: $(PROGS) CCBootloader.hex: $(REL) $(ASM_REL) Makefile $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o CCBootloader.hex $(ASM_REL) $(REL) +CCBootloader-rfcat-chronosdongle.hex: CFLAGS += -DRFCAT -DRFCAT_CHRONOS +CCBootloader-rfcat-chronosdongle.hex: $(REL) $(ASM_REL) Makefile + $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o CCBootloader-rfcat-chronosdongle.hex $(ASM_REL) $(REL) + +CCBootloader-rfcat-donsdongle.hex: CFLAGS += -DRFCAT -DRFCAT_DONSDONGLE +CCBootloader-rfcat-donsdongle.hex: $(REL) $(ASM_REL) Makefile + $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o CCBootloader-rfcat-donsdongle.hex $(ASM_REL) $(REL) + +CCBootloader-rfcat-ys1.hex: CFLAGS += -DRFCAT -DRFCAT_YARDSTICKONE +CCBootloader-rfcat-ys1.hex: $(REL) $(ASM_REL) Makefile + $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o CCBootloader-rfcat-ys1.hex $(ASM_REL) $(REL) + clean: rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) rm -f $(ASM_ADB) $(ASM_LNK) $(ASM_LST) $(ASM_REL) $(ASM_RST) $(ASM_SYM) rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) +install: CCBootloader.hex + goodfet.cc erase + goodfet.cc flash CCBootloader.hex + goodfet.cc verify CCBootloader.hex + +installchronosdongle: CCBootloader-rfcat-chronosdongle.hex + goodfet.cc erase + goodfet.cc flash CCBootloader-rfcat-chronosdongle.hex + goodfet.cc verify CCBootloader-rfcat-chronosdongle.hex + +installdonsdongle: CCBootloader-rfcat-donsdongle.hex + goodfet.cc erase + goodfet.cc flash CCBootloader-rfcat-donsdongle.hex + goodfet.cc verify CCBootloader-rfcat-donsdongle.hex + +installys1dongle: CCBootloader-rfcat-ys1.hex + goodfet.cc erase + goodfet.cc flash CCBootloader-rfcat-ys1.hex + goodfet.cc verify CCBootloader-rfcat-ys1.hex + diff --git a/bootload.py b/bootload.py index 84aa66c..5186799 100755 --- a/bootload.py +++ b/bootload.py @@ -30,6 +30,52 @@ def download_code(ihx_file, serial_port): print "Skipping non data record: '%s'" % line[:-1] return True +def verify_code(ihx_file, serial_port): + can_read_any= None + for line in ihx_file.readlines(): + record_type = int(line[7:9], 16) + if (record_type == 0x00): + length = int(line[1:3], 16) + start_addr = int(line[3:7], 16) + data = line[9:9+(length*2)] + # first time around, check if we can only read 16 byte chunks + if can_read_any == None: + can_read_any = False + do_flash_read(serial_port, start_addr, 1) + for read_data in serial_port: + read_data = read_data.strip() + if not read_data: + continue + if not read_data == ":00000001FF": + can_read_any = True + else: + break + if not can_read_any: + print "*** warning! this version of CC-Bootloader can only read 16 byte blocks!" + print "*** upgrade recommended!" + if can_read_any: + block_length= length + else: + block_length= ((length / 16) + 1) * 16 + print "\rVerifying %04d bytes at address: %04X" % (length, start_addr), + do_flash_read(serial_port, start_addr, block_length) + verify_data= '' + for read_data in serial_port: + read_data= read_data.strip() + if (not data or read_data == ":00000001FF"): + break + # strip header and checksum + verify_data += read_data[9:-2] + if (data == verify_data[:length*2]): + print '(OK)', + else: + print 'Failed! Expected:', data, 'Got:', verify_data[:length*2] + exit(1) + sys.stdout.flush() + else: + print "Skipping non data record: '%s'" % line[:-1] + return True + def run_user_code(serial_port): # User code is entered on intel HEX EOF record serial_port.write(":00000001FF\n") @@ -75,7 +121,7 @@ def erase_user_page(serial_port, page): return False return True -def flash_read(serial_port, start_addr, length): +def do_flash_read(serial_port, start_addr, length): chksum = (0xD9 + (0x100 - (start_addr & 0xFF)) + (0x100 - ((start_addr>>8) & 0xFF)) + @@ -83,10 +129,18 @@ def flash_read(serial_port, start_addr, length): (0x100 - ((length>>8) & 0xFF)) ) & 0xFF serial_port.write(":02%04X25%04X%02X\n" % (start_addr, length, chksum)) + + +def flash_read(ihx_file, serial_port, start_addr, length): + do_flash_read(serial_port, start_addr, length) for line in serial_port: - print line, - if (line == ":00000001FF\n"): - break + if not line == "\n": + if(ihx_file): + ihx_file.write(line) + else: + print line, + if (line == ":00000001FF\n"): + break def print_usage(): import sys @@ -96,13 +150,17 @@ def print_usage(): Usage: ./bootload.py serial_port command Commands: - download hex_file + + download + Download hex_file to the device. run + Run the user code. reset + The bootloader will not erase pages that have previously been written to before writing new data to that page. This allows for random access writes but prevents you from overwriting downloaded code unless the device is @@ -111,18 +169,26 @@ def print_usage(): cycling. erase_all + Erases the entire user flash area. - erage n + erage + Erases page n of the flash memory (organised into 1024 byte pages). The bootloader occupies the first few pages and the rest are reserved for user code. Attempting to erase a bootloader page will have no effect. To determine which page the user code starts on please check the USER_CODE_BASE setting in main.h. - read start_addr len - Reads len bytes from flash memory starting from start_addr. start_addr and - len should be specified in hexadecimal (e.g. 0x1234). + read [hex_file] + + Reads len bytes from flash memory starting from start_addr and optionally + write to hex_file. start_addr and len should be specified in hexadecimal + (e.g. 0x1234). + + verify + + Verify hex_file matches device flash memory. """ if __name__ == '__main__': @@ -137,13 +203,16 @@ def print_usage(): serial_port = serial.Serial(serial_port_name, timeout=1) try: - if (command == 'download'): + if (command == 'download' or command == 'verify'): if (len(options) < 1): print_usage() else: ihx_filename = options[0] ihx_file = open(ihx_filename, 'r') - download_code(ihx_file, serial_port) + if (command == 'download'): + download_code(ihx_file, serial_port) + else: + verify_code(ihx_file, serial_port) elif (command == 'run'): run_user_code(serial_port) @@ -164,8 +233,16 @@ def print_usage(): if (len(options) < 2): print_usage() else: - flash_read(serial_port, int(options[0], 16), int(options[1], 16)) - + ihx_file = None + if(len(options) == 3): + try: + ihx_filename = options[2] + ihx_file = open(ihx_filename, 'w') + print 'reading to:', ihx_filename + except: + print "couldn't open output file:", ihx_filename + exit(2) + flash_read(ihx_file, serial_port, int(options[0], 16), int(options[1], 16)) else: print_usage() diff --git a/src/hal.c b/src/hal.c index 0c1bdc6..5b2724f 100644 --- a/src/hal.c +++ b/src/hal.c @@ -18,29 +18,69 @@ */ #include "cc1111.h" +#include "hal.h" void setup_led() { // Setup LED and turn it off - P1DIR |= 2; - P1_1 = 0; + P1DIR |= LED_MASK; + led_off(); +} + +void setup_button() { +#ifdef RFCAT_DONSDONGLE + P1DIR &= ~4; +#endif +#ifdef RFCAT_CHRONOS + P2DIR &= ~4; +#endif +#ifdef RFCAT_YARDSTICKONE + P2DIR &= ~4; +#endif +} + +// any other gpio pins +void setup_gpio() { +#ifdef RFCAT_YARDSTICKONE + // amplifer configuration pins + //P0_0 input with pull-up (antenna port power off) + P0DIR &= ~1; // Set direction to IN (clear bit for P0_0) + P0INP &= ~P0INP_MDP0_0_TRISTATE; // Set as pull up/down (rather than tristate) + P2INP &= ~P2INP_PDUP0_PULL_DOWN; // clear pull down bit (i.e. pull up) + P2DIR |= 0x19; + TX_AMP_EN = 0; + RX_AMP_EN = 0; + AMP_BYPASS_EN = 1; +#endif } void led_on() { - P1_1 = 1; +#ifdef RFCAT_YARDSTICKONE + LED1 = 1; + LED2 = 1; + LED3 = 1; +#else + LED = 1; +#endif } void led_off() { - P1_1 = 0; +#ifdef RFCAT_YARDSTICKONE + LED1 = 0; + LED2 = 0; + LED3 = 0; +#else + LED = 0; +#endif } void usb_up() { // Bring up the USB link - P1DIR |= 1; - P1_0 = 1; + P1DIR |= USB_MASK; + USB_ENABLE = 1; } void usb_down() { // Bring down the USB link - P1_0 = 0; - P1DIR &= ~1; + USB_ENABLE = 0; + P1DIR &= ~USB_MASK; } diff --git a/src/hal.h b/src/hal.h index 1e1075c..560b471 100644 --- a/src/hal.h +++ b/src/hal.h @@ -20,11 +20,44 @@ #ifndef _HAL_H_ #define _HAL_H_ +#ifdef RFCAT_CHRONOS + #define LED P1_0 + #define LED_MASK 0x01 + #define USB_ENABLE P1_1 + #define USB_MASK 0x02 + #define CC1111CHRONOS_PIN_DC P2_2 +#endif + +#ifdef RFCAT_DONSDONGLE + #define LED P1_1 + #define LED_MASK 0x02 + #define USB_ENABLE P1_0 + #define USB_MASK 0x01 + #define CC1111EM_BUTTON P1_2 +#endif + +#ifdef RFCAT_YARDSTICKONE + #define LED1 P1_1 + #define LED2 P1_2 + #define LED3 P1_3 + #define LED_MASK 0x0E + #define USB_ENABLE P1_0 + #define USB_MASK 0x01 + #define CC1111YSONE_PIN_DC P2_2 + #define TX_AMP_EN P2_0 + #define RX_AMP_EN P2_4 + #define AMP_BYPASS_EN P2_3 +#endif + void setup_led(); void led_on(); void led_off(); +void setup_button(); +void setup_gpio(); void usb_up(); void usb_down(); +#define BUTTON_PRESSED 0 +#define GROUNDED 0 #endif // _HAL_H_ diff --git a/src/intel_hex.c b/src/intel_hex.c index 10813c4..4678bba 100644 --- a/src/intel_hex.c +++ b/src/intel_hex.c @@ -164,15 +164,18 @@ void to_hex16_ascii(char buff[], uint16_t x) { void ihx_read_print(__xdata uint8_t* start_addr, uint16_t len) { __xdata char buff[45]; - uint8_t byte, sum, i; + uint8_t byte, sum, i, chunk; - while (len >= 0x10) { + while (len) { sum = 0; + if(len > 0x10) + chunk = 0x10; + else + chunk = len; buff[0] = ':'; - // Record length is 0x10 - to_hex8_ascii(&buff[1], 0x10); - sum += 0x10; + to_hex8_ascii(&buff[1], chunk); + sum += chunk; // Write address into buffer to_hex16_ascii(&buff[3], (uint16_t)start_addr); sum += (uint16_t)start_addr & 0xFF; @@ -180,22 +183,25 @@ void ihx_read_print(__xdata uint8_t* start_addr, uint16_t len) { // Write record type into buffer to_hex8_ascii(&buff[7], 0x00); // Write data bytes into buffer - for (i=0; i<0x10; i++) { + for (i=0; i 0x10) { + start_addr += 0x10; + len -= 0x10; + } else // we're done + len = 0; } usb_putstr(":00000001FF\n"); } diff --git a/src/main.c b/src/main.c index 85ece0c..f864d60 100644 --- a/src/main.c +++ b/src/main.c @@ -71,22 +71,26 @@ void jump_to_user() { EA = 0; IEN0 = IEN1 = IEN2 = 0; - // Bring down the USB link - usb_down(); - - // Flag bootloader not running - bootloader_running = 0; if (check_for_payload()) { + // Bring down the USB link + usb_down(); + + // Flag bootloader not running + bootloader_running = 0; // Jump to user code __asm ljmp #USER_CODE_BASE __endasm; while (1) {} } else { + #ifdef RFCAT + return; // need to run bootloader! + #else // Oops, no payload. We're stuck now! led_on(); while (1) {} + #endif } } @@ -172,8 +176,18 @@ uint8_t want_bootloader() { if (!Px_y) return 0; */ - + + #ifdef RFCAT + // we use the unused I2S SFRs as semaphores. + // this would be safe even if I2S is in use as they should be reconfigured by + // user code + if(I2SCLKF2 == 0x69) + return 1; + // no thanks + return 0; + #else return 1; + #endif } void bootloader_main () @@ -181,10 +195,36 @@ void bootloader_main () __xdata char buff[100]; uint8_t ihx_status; uint16_t read_start_addr, read_len; - + +#ifdef RFCAT + // use I2S SFR to signal that bootloader is present + I2SCLKF0= 0xF0; + I2SCLKF1= 0x0D; + + setup_button(); + setup_gpio(); + + #ifdef RFCAT_DONSDONGLE + if (CC1111EM_BUTTON != BUTTON_PRESSED && !want_bootloader()) + #endif + + #ifdef RFCAT_CHRONOS + if (CC1111CHRONOS_PIN_DC != GROUNDED && !want_bootloader()) + #endif + + #ifdef RFCAT_YARDSTICKONE + if (CC1111YSONE_PIN_DC != GROUNDED && !want_bootloader()) + #endif + +#else if (!want_bootloader()) +#endif jump_to_user(); - +#ifdef RFCAT + // reset semaphore + I2SCLKF2= 0x00; +#endif + clock_init(); setup_led(); @@ -197,11 +237,12 @@ void bootloader_main () usb_init(); // Enable interrupts - EA = 1; + EA = 1; // Bring up the USB link usb_up(); - + led_on(); + while (1) { ihx_readline(buff); @@ -246,7 +287,7 @@ void bootloader_main () case IHX_RECORD_READ: // Read out a section of flash over USB read_start_addr = ihx_record_address(buff); - read_len = ihx_data_byte(buff, 0)<<8 + ihx_data_byte(buff, 1); + read_len = (ihx_data_byte(buff, 0)<<8) + ihx_data_byte(buff, 1); usb_putchar('\n'); ihx_read_print((__xdata uint8_t*)read_start_addr, read_len); break; @@ -259,6 +300,6 @@ void bootloader_main () } else { usb_putchar(ihx_status + '0'); usb_flush(); - } - } + } + } } diff --git a/src/usb.h b/src/usb.h index d0ca438..f3f606a 100644 --- a/src/usb.h +++ b/src/usb.h @@ -18,6 +18,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include "hal.h" + #ifndef _USB_H_ #define _USB_H_ @@ -118,17 +120,52 @@ struct usb_line_coding { #define USB_READ_AGAIN ((char) -1) -#define USB_VID 0xFFFE -#define USB_PID 0x000A - -// iManufacturer -#define USB_iManufacturer_LEN 0x10 -#define USB_iManufacturer_STRING "JobyGPS" -#define USB_iManufacturer_UCS2 'J', 0, 'o', 0, 'b', 0, 'y', 0, 'G', 0, 'P', 0, 'S', 0 -// iProduct -#define USB_iProduct_LEN 0x1C -#define USB_iProduct_STRING "CC Bootloader" -#define USB_iProduct_UCS2 'C', 0, 'C', 0, ' ', 0, 'B', 0, 'o', 0, 'o', 0, 't', 0, 'l', 0, 'o', 0, 'a', 0, 'd', 0, 'e', 0, 'r', 0 +#ifdef RFCAT_CHRONOS + #define USB_VID 0x1D50 + #define USB_PID 0x6049 + // iManufacturer + #define USB_iManufacturer_LEN 0x0C + #define USB_iManufacturer_STRING "RfCat" + #define USB_iManufacturer_UCS2 'R', 0, 'f', 0, 'C', 0, 'a', 0, 't', 0 + // iProduct + #define USB_iProduct_LEN 0x26 + #define USB_iProduct_STRING "Chronos Bootloader" + #define USB_iProduct_UCS2 'C', 0, 'h', 0, 'r', 0, 'o', 0, 'n', 0, 'o', 0, 's', 0, ' ', 0, 'B', 0, 'o', 0, 'o', 0, 't', 0, 'l', 0, 'o', 0, 'a', 0, 'd', 0, 'e', 0, 'r', 0 +#elif defined RFCAT_DONSDONGLE + #define USB_VID 0x1D50 + #define USB_PID 0x604A + // iManufacturer + #define USB_iManufacturer_LEN 0x0C + #define USB_iManufacturer_STRING "RfCat" + #define USB_iManufacturer_UCS2 'R', 0, 'f', 0, 'C', 0, 'a', 0, 't', 0 + // iProduct + #define USB_iProduct_LEN 0x20 + #define USB_iProduct_STRING "Dons Bootloader" + #define USB_iProduct_UCS2 'D', 0, 'o', 0, 'n', 0, 's', 0, ' ', 0, 'B', 0, 'o', 0, 'o', 0, 't', 0, 'l', 0, 'o', 0, 'a', 0, 'd', 0, 'e', 0, 'r', 0 +#elif defined RFCAT_YARDSTICKONE + #define USB_VID 0x1D50 + #define USB_PID 0x605C + // iManufacturer + #define USB_iManufacturer_LEN 0x28 + #define USB_iManufacturer_STRING "Great Scott Gadgets" + #define USB_iManufacturer_UCS2 'G', 0, 'r', 0, 'e', 0, 'a', 0, 't', 0, ' ', 0, 'S', 0, 'c', 0, 'o', 0, 't', 0, 't', 0, ' ', 0, 'G', 0, 'a', 0, 'd', 0, 'g', 0, 'e', 0, 't', 0, 's', 0 + // iProduct + #define USB_iProduct_LEN 0x34 + #define USB_iProduct_STRING "YARD Stick One Bootloader" + #define USB_iProduct_UCS2 'Y', 0, 'A', 0, 'R', 0, 'D', 0, ' ', 0, 'S', 0, 't', 0, 'i', 0, 'c', 0, 'k', 0, ' ', 0, 'O', 0, 'n', 0, 'e', 0, ' ', 0, 'B', 0, 'o', 0, 'o', 0, 't', 0, 'l', 0, 'o', 0, 'a', 0, 'd', 0, 'e', 0, 'r', 0 +#else + #define USB_VID 0xFFFE + #define USB_PID 0x000A + // iManufacturer + #define USB_iManufacturer_LEN 0x10 + #define USB_iManufacturer_STRING "JobyGPS" + #define USB_iManufacturer_UCS2 'J', 0, 'o', 0, 'b', 0, 'y', 0, 'G', 0, 'P', 0, 'S', 0 + // iProduct + #define USB_iProduct_LEN 0x1C + #define USB_iProduct_STRING "CC Bootloader" + #define USB_iProduct_UCS2 'C', 0, 'C', 0, ' ', 0, 'B', 0, 'o', 0, 'o', 0, 't', 0, 'l', 0, 'o', 0, 'a', 0, 'd', 0, 'e', 0, 'r', 0 +#endif + // iSerial #define USB_iSerial_LEN 0x0e #define USB_iSerial_STRING "000001"