diff --git a/Makefile b/Makefile index 6337154cb..7c3873052 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,7 @@ ALL = $(TESTS:.c=.srec) $(TESTS:.c=.bin) $(TESTS:.c=.dis) all: src/start.o src/isr.o $(ALL) +tests/flasher.obj: src/maca.o src/nvm.o tests/nvm-read.obj: src/maca.o src/nvm.o tests/nvm-write.obj: src/maca.o src/nvm.o tests/rftest-rx.obj: src/maca.o src/nvm.o diff --git a/mc1322x-load.pl b/mc1322x-load.pl index 797119a5e..45c13b3a8 100755 --- a/mc1322x-load.pl +++ b/mc1322x-load.pl @@ -8,29 +8,36 @@ use Time::HiRes qw(usleep); use strict; my $filename = ''; +my $second = ''; my $term = '/dev/ttyUSB0'; my $baud = '115200'; my $verbose; -GetOptions ('file=s' => \$filename, +GetOptions ('file=s' => \$filename, + 'secondfile=s' => \$second, 'terminal=s' => \$term, 'verbose' => \$verbose, - 'baud=s' => \$baud); + 'baud=s' => \$baud, + ); $| = 1; if($filename eq '') { print "Example usage: mc1322x-load.pl -f foo.bin -t /dev/ttyS0 -b 9600\n"; + print " or : mc1322x-load.pl -f flasher.bin -s flashme.bin 0x1e000,0x11223344,0x55667788\n"; print " -f required: binary file to load\n"; + print " -s optional: secondary binary file to send\n"; print " -t default: /dev/ttyUSB0\n"; print " -b default: 115200\n"; + print " anything on the command line is sent serial device\n"; + print " after all of the files have been sent\n"; exit; } - + my $ob = Device::SerialPort->new ($term) or die "Can't start $term\n"; # next test will die at runtime unless $ob -$baud = 115200 if (!defined($baud)); +if ($filename eq '') { die "you must specify a file with -f\n"; } $ob->baudrate($baud); $ob->parity('none'); @@ -39,56 +46,74 @@ $ob->stopbits(1); $ob->handshake("rts"); $ob->read_const_time(1000); # 1 second per unfulfilled "read" call -my $c; -my $count; -my $ret = ''; +my $s = 0; -$ob->write(pack('C','0')); -until($ret eq 'CONNECT') { - ($count,$c) = $ob->read(1); - if ($count == 0) { - print '.'; - $ob->write(pack('C','0')); - next; +while(1) { + + my $c; my $count; my $ret = ''; my $test=''; + + if($s == 1) { print "secondary send...\n"; } + + $ob->write(pack('C','0')); + + if($s == 1) { + $test = 'ready'; + } else { + $test = 'CONNECT'; } - $ret .= $c; -} -print $ret . "\n"; - - -#until($ret eq 'CONNECT') { -# $c = $ob->input; -# $ret .= $c; -#} -#print $ret . "\n"; - - -if (defined $filename) { - - my $size = -s $filename; - - print ("Size: $size bytes\n"); - $ob->write(pack('V',$size)); - - open(FILE, $filename) or die($!); - print "Sending $filename\n"; - - my $i = 1; - while(read(FILE, $c, 1)) { - print unpack('H',$c) . unpack('h',$c) if $verbose; -# print "\n" if ($verbose && ($i%4==0)); - $i++; -# usleep(44); # this is as fast is it can go... - usleep(50); # this is as fast is it can go... -# select undef, undef, undef, 0.0001; - $ob->write($c); + + until($ret =~ /$test$/) { + ($count,$c) = $ob->read(1); + if ($count == 0) { + print '.'; + $ob->write(pack('C','0')); + next; + } + $ret .= $c; } -} + print $ret . "\n"; + + if (-e $filename) { + + my $size = -s $filename; -print "done.\n"; + print ("Size: $size bytes\n"); + $ob->write(pack('V',$size)); + open(FILE, $filename) or die($!); + print "Sending $filename\n"; + + my $i = 1; + while(read(FILE, $c, 1)) { + $i++; + usleep(50); # this is as fast is it can go... + usleep(25) if ($s==1); + $ob->write($c); + } + } + + last if ($s==1); + if((-e $second)) { + $s=1; $filename = $second; + } else { + last; + } + +} + +print "done sending files.\n"; + +print "sending " ; +print @ARGV; +print ",\n"; + +$ob->write(@ARGV); +$ob->write(','); + +my $c; my $count; while(1) { - print $ob->input; + ($count, $c) = $ob->read(1); + print $c if ($count != 0); } $ob -> close or die "Close failed: $!\n"; diff --git a/tests/flasher.c b/tests/flasher.c new file mode 100644 index 000000000..931b335d6 --- /dev/null +++ b/tests/flasher.c @@ -0,0 +1,307 @@ +#define GPIO_FUNC_SEL0 0x80000018 /* GPIO 15 - 0; 2 bit blocks */ + +#define BASE_UART1 0x80005000 +#define UART1_CON 0x80005000 +#define UART1_STAT 0x80005004 +#define UART1_DATA 0x80005008 +#define UR1CON 0x8000500c +#define UT1CON 0x80005010 +#define UART1_CTS 0x80005014 +#define UART1_BR 0x80005018 + +#define GPIO_PAD_DIR0 0x80000000 +#define GPIO_DATA0 0x80000008 + +#include "embedded_types.h" +#include "nvm.h" +#include "maca.h" + +#define reg(x) (*(volatile uint32_t *)(x)) + +#define DELAY 400000 + +/* if both BOOT_OK and BOOT_SECURE are 0 then flash image will not be bootable */ +/* if both are 1 then flash image will be secure */ +#define BOOT_OK 1 +#define BOOT_SECURE 0 + +#define DEBUG 1 +#if DEBUG +#define dbg_putc(...) putc(__VA_ARGS__) +#define dbg_puts(...) puts(__VA_ARGS__) +#define dbg_put_hex(...) put_hex(__VA_ARGS__) +#define dbg_put_hex16(...) put_hex16(__VA_ARGS__) +#define dbg_put_hex32(...) put_hex32(__VA_ARGS__) +#else +#define dbg_putc(...) +#define dbg_puts(...) +#define dbg_put_hex(...) +#define dbg_put_hex16(...) +#define dbg_put_hex32(...) +#endif + +const uint8_t hex[16]={'0','1','2','3','4','5','6','7', + '8','9','a','b','c','d','e','f'}; + +uint8_t getc(void); +void flushrx(void); +uint32_t to_u32(char *c); + +#include "isr.h" + +#define NBYTES 16 + +enum parse_states { + SCAN_X, + READ_CHARS, + PROCESS, + MAX_STATE, +}; + +__attribute__ ((section ("startup"))) +void main(void) { + nvmType_t type=0; + nvmErr_t err; + volatile uint8_t c; + volatile uint32_t buf[NBYTES/4]; + volatile uint32_t i; + volatile uint32_t len=0; + volatile uint32_t state = SCAN_X; + volatile uint32_t addr,data; + + *(volatile uint32_t *)GPIO_PAD_DIR0 = 0x00000100; + + /* Restore UART regs. to default */ + /* in case there is still bootloader state leftover */ + + reg(UART1_CON) = 0x0000c800; /* mask interrupts, 16 bit sample --- helps explain the baud rate */ + + /* INC = 767; MOD = 9999 works: 115200 @ 24 MHz 16 bit sample */ + #define INC 767 + #define MOD 9999 + reg(UART1_BR) = INC<<16 | MOD; + + /* see Section 11.5.1.2 Alternate Modes */ + /* you must enable the peripheral first BEFORE setting the function in GPIO_FUNC_SEL */ + /* From the datasheet: "The peripheral function will control operation of the pad IF */ + /* THE PERIPHERAL IS ENABLED. */ + reg(UART1_CON) = 0x00000003; /* enable receive and transmit */ + reg(GPIO_FUNC_SEL0) = ( (0x01 << (14*2)) | (0x01 << (15*2)) ); /* set GPIO15-14 to UART (UART1 TX and RX)*/ + + vreg_init(); + + dbg_puts("Detecting internal nvm\n\r"); + + err = nvm_detect(gNvmInternalInterface_c, &type); + + dbg_puts("nvm_detect returned: 0x"); + dbg_put_hex(err); + dbg_puts(" type is: 0x"); + dbg_put_hex32(type); + dbg_puts("\n\r"); + + /* erase the flash */ + err = nvm_erase(gNvmInternalInterface_c, type, 0x4fffffff); + + dbg_puts("nvm_erase returned: 0x"); + dbg_put_hex(err); + dbg_puts("\n\r"); + + dbg_puts(" type is: 0x"); + dbg_put_hex32(type); + dbg_puts("\n\r"); + + /* say we are ready */ + len = 0; + puts("ready"); + flushrx(); + + /* read the length */ + for(i=0; i<4; i++) { + c = getc(); + /* bail if the first byte of the length is zero */ + len += (c<<(i*8)); + } + + dbg_puts("len: "); + dbg_put_hex32(len); + dbg_puts("\n\r"); + + /* write the OKOK magic */ + +#if BOOT_OK + ((uint8_t *)buf)[0] = 'O'; ((uint8_t *)buf)[1] = 'K'; ((uint8_t *)buf)[2] = 'O'; ((uint8_t *)buf)[3] = 'K'; +#elif BOOT_SECURE + ((uint8_t *)buf)[0] = 'S'; ((uint8_t *)buf)[1] = 'E'; ((uint8_t *)buf)[2] = 'C'; ((uint8_t *)buf)[3] = 'U'; +#else + ((uint8_t *)buf)[0] = 'N'; ((uint8_t *)buf)[1] = 'O'; ((uint8_t *)buf)[2] = 'N'; ((uint8_t *)buf)[3] = 'O'; +#endif + + dbg_puts(" type is: 0x"); + dbg_put_hex32(type); + dbg_puts("\n\r"); + + err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)buf, 0, 4); + + dbg_puts("nvm_write returned: 0x"); + dbg_put_hex(err); + dbg_puts("\n\r"); + + /* write the length */ + err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)&len, 4, 4); + + /* read a byte, write a byte */ + /* byte at a time will make this work as a contiki process better */ + /* for OTAP */ + for(i=0; i> 4]); + putc(hex[x & 15]); +} + +void put_hex16(uint16_t x) +{ + put_hex((x >> 8) & 0xFF); + put_hex((x) & 0xFF); +} + +void put_hex32(uint32_t x) +{ + put_hex((x >> 24) & 0xFF); + put_hex((x >> 16) & 0xFF); + put_hex((x >> 8) & 0xFF); + put_hex((x) & 0xFF); +} +