diff --git a/redbee-econotag/Makefile b/redbee-econotag/Makefile index 391c9bd42f..ae4ccfd0a7 100644 --- a/redbee-econotag/Makefile +++ b/redbee-econotag/Makefile @@ -4,6 +4,12 @@ OBJ = $(SRC:%.c=$(BINDIR)%.o)## defines DEP = $(SRC:%.c=$(BINDIR)%.d) export ARCH = redbee-econotag_base.a +INCLUDES += -I$(RIOTBOARD)/redbee-econotag/drivers/include +INCLUDES += -I$(RIOTBASE)/cpu/arm_common/include +INCLUDES += -I$(RIOTBASE)/cpu/mc1322x/include + +.PHONY: $(BINDIR)/$(ARCH) + all: $(BINDIR)$(ARCH) $(MAKE) -C drivers diff --git a/redbee-econotag/board_init.c b/redbee-econotag/board_init.c index 5a0b03177c..7c157b1038 100644 --- a/redbee-econotag/board_init.c +++ b/redbee-econotag/board_init.c @@ -9,3 +9,11 @@ void board_init(void) { asm("nop"); } + +void bl_init_clks( void ) { + // dummy to compile +} + +void bl_init_ports( void ) { + // dummy to compile +} diff --git a/redbee-econotag/drivers/include/gpio.h b/redbee-econotag/drivers/include/gpio.h index 6a727b9da8..b46051a1a7 100644 --- a/redbee-econotag/drivers/include/gpio.h +++ b/redbee-econotag/drivers/include/gpio.h @@ -11,6 +11,9 @@ #ifndef GPIO_H #define GPIO_H +// TODO: why do we need to include this for macro expansion? +#include "stdint.h" + /* Structure-based GPIO access Example usage: @@ -94,7 +97,6 @@ #define EVTI GPIO_63 - #define _V(x,n,i) uint32_t x##_##i : n; #define _REP(x,n) \ _V(x,n,00) _V(x,n,01) _V(x,n,02) _V(x,n,03) _V(x,n,04) _V(x,n,05) _V(x,n,06) _V(x,n,07) \ diff --git a/redbee-econotag/drivers/include/uart.h b/redbee-econotag/drivers/include/uart.h index 44359b8f60..928a2157a9 100644 --- a/redbee-econotag/drivers/include/uart.h +++ b/redbee-econotag/drivers/include/uart.h @@ -104,7 +104,7 @@ void uart_flow_ctl(volatile struct UART_struct * uart, uint8_t on); */ #define UART1_TX_BUFFERSIZE 1024 extern volatile uint32_t u1_tx_head, u1_tx_tail; -void uart1_putc(char c); +void uart1_putc(uint8_t c); /* The mc1322x has a 32 byte hardware FIFO for received characters. * If a larger rx buffersize is specified the FIFO will be extended into RAM. @@ -125,7 +125,7 @@ uint8_t uart1_getc(void); #define UART2_TX_BUFFERSIZE 1024 extern volatile uint32_t u2_tx_head, u2_tx_tail; -void uart2_putc(char c); +void uart2_putc(uint8_t c); #define UART2_RX_BUFFERSIZE 128 #if UART2_RX_BUFFERSIZE > 32 diff --git a/redbee-econotag/drivers/redbee_uart.c b/redbee-econotag/drivers/redbee_uart.c index 1015bb7759..621d94e060 100644 --- a/redbee-econotag/drivers/redbee_uart.c +++ b/redbee-econotag/drivers/redbee_uart.c @@ -16,6 +16,8 @@ #define MOD_ 9999 #define CLK_ 24000000 #define DIV_ 16 /* uart->CON.XTIM = 0 is 16x oversample (datasheet is incorrect) */ +#define BAUTRATE_UART1 115200 +#define BAUTRATE_UART2 115200 void uart_set_baudrate ( volatile struct UART_struct* uart, uint32_t baudrate ) { uint64_t inc = 0; @@ -86,6 +88,7 @@ void uart_flow_ctl ( volatile struct UART_struct* uart, uint8_t on ) { } } +// TODO: clean from u*_(rx|tx)_(head|tail) void uart_init ( volatile struct UART_struct* uart, uint32_t baudrate ) { /* enable the uart so we can set the gpio mode */ /* has to be enabled before setting the function with GPIO->FUNC_SEL */ @@ -108,8 +111,8 @@ void uart_init ( volatile struct UART_struct* uart, uint32_t baudrate ) { UART1->CONbits.RXE = 1; /*< enable receive */ #if UART1_RX_BUFFERSIZE > 32 UART1->RXCONbits.LVL = 30; /*< interrupt when fifo is nearly full */ - u1_rx_head = 0; - u1_rx_tail = 0; + //u1_rx_head = 0; + //u1_rx_tail = 0; #elif UART1_RX_BUFFERSIZE < 32 UART1->CONbits.FCE = 1; /*< enable flowcontrol */ UART1->CONbits.MRXR = 1; /*< disable Rx interrupt */ @@ -120,10 +123,11 @@ void uart_init ( volatile struct UART_struct* uart, uint32_t baudrate ) { UART1->CONbits.MRXR = 1; /*< disable rx interrupt */ #endif - u1_tx_head = 0; - u1_tx_tail = 0; + //u1_tx_head = 0; + //u1_tx_tail = 0; - enable_irq(UART1); + //enable_irq(UART1); + ITC->INTENABLEbits.UART1 = 1; } else { /* UART2 */ @@ -139,8 +143,8 @@ void uart_init ( volatile struct UART_struct* uart, uint32_t baudrate ) { UART2->CONbits.RXE = 1; /*< enable receive */ #if UART2_RX_BUFFERSIZE > 32 UART2->RXCONbits.LVL = 30; /*< interrupt when fifo is nearly full */ - u2_rx_head = 0; - u2_rx_tail = 0; + //u2_rx_head = 0; + //u2_rx_tail = 0; #elif UART2_RX_BUFFERSIZE < 32 UART2->CONbits.FCE = 1; /*< enable flowcontrol */ UART2->CONbits.MRXR = 1; /*< disable Rx interrupt */ @@ -151,25 +155,50 @@ void uart_init ( volatile struct UART_struct* uart, uint32_t baudrate ) { UART2->CONbits.MRXR = 1; /*< disable rx interrupt */ #endif - u2_tx_head = 0; - u2_tx_tail = 0; + // u2_tx_head = 0; + //u2_tx_tail = 0; - enable_irq(UART2); + //enable_irq(UART2); + ITC->INTENABLEbits.UART2 = 1; } uart_set_baudrate( uart, baudrate ); } -int fw_puts(char *astring,int length) -{ - return uart0_puts ( astring, length ); -} - static inline uint32_t uart0_puts ( uint8_t *astring, uint32_t length ) { - int i = 0; + uint32_t i = 0; for (; iINTENABLEbits.UART1 = 0; + ITC->INTENABLEbits.UART2 = 0; + + ITC->INTENABLEbits.UART1 = 1; + ITC->INTENABLEbits.UART2 = 1; + /** taken from msba2-uart0.c + U0IER &= ~BIT1; // disable THRE interrupt + while(running) { + while(!(U0LSR & (BIT5|BIT6))){}; // transmit fifo + fifo=0; + push_queue(); // dequeue to fifo + } + U0IER |= BIT1; // enable THRE interrupt + */ +} + + +int fw_puts(char *astring,int length) +{ + return uart0_puts ( (uint8_t*) astring, (uint32_t) length ); +} + +int bl_uart_init(void) { + uart_init( UART1, BAUTRATE_UART1 ); + uart_init( UART2, BAUTRATE_UART2 ); } \ No newline at end of file diff --git a/redbee-econotag/drivers/redbee_uart1.c b/redbee-econotag/drivers/redbee_uart1.c index ffe386791e..a4a53afc40 100644 --- a/redbee-econotag/drivers/redbee_uart1.c +++ b/redbee-econotag/drivers/redbee_uart1.c @@ -14,7 +14,6 @@ #include "uart.h" void uart1_isr ( void ) { - int i = 0; if ( UART1->USTATbits.RXRDY == 1 ) { #ifdef MODULE_UART0 if ( uart0_handler_pid ) { diff --git a/redbee-econotag/tools/mc1322x-load.c b/redbee-econotag/tools/mc1322x-load.c new file mode 100644 index 0000000000..d63df23802 --- /dev/null +++ b/redbee-econotag/tools/mc1322x-load.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2012, Maxim Osipov + * Copyright (c) 2010, Mariano Alvira and other contributors + * to the MC1322x project (http://mc1322x.devl.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +char* filename; +char* second; +char* term = "/dev/ttyUSB0"; +int baud = B115200; +int verbose = 0; +char* rts = "rts"; +char* command; +int first_delay = 50; +int second_delay = 100; +int do_exit = 0; +int zerolen = 0; +char *args = NULL; + +struct stat sbuf; +struct termios options; +char buf[256]; +int pfd; +int ffd; +int sfd; + +void help(void); + +int main(int argc, char **argv) +{ + int c = 0; + int r = 0; + int i = 0; + uint32_t s = 0; + opterr = 0; + + /* Parse options */ + while ((c = getopt(argc, argv, "f:s:zt:vu:r:c:a:b:eh")) != -1) { + switch (c) + { + case 'f': + filename = optarg; + break; + case 's': + second = optarg; + break; + case 'z': + zerolen = 1; + break; + case 't': + term = optarg; + break; + case 'v': + verbose = 1; + break; + case 'u': + if (strcmp(optarg, "115200")) { + baud = B115200; + } else if (strcmp(optarg, "57600")) { + baud = B115200; + } else if (strcmp(optarg, "19200")) { + baud = B19200; + } else if (strcmp(optarg, "9600")) { + baud = B9600; + } else { + printf("Unknown baud rate %s!\n", optarg); + return -1; + } + break; + case 'r': + rts = optarg; + break; + case 'c': + command = optarg; + break; + case 'a': + first_delay = atoi(optarg); + break; + case 'b': + second_delay = atoi(optarg); + break; + case 'e': + do_exit = 1; + break; + case 'h': + case '?': + help(); + return 0; + default: + abort(); + } + } + /* Get other arguments */ + if (optind < argc) + args = argv[optind]; + + /* Print settings */ + if (verbose) { + printf("Primary file (RAM): %s\n", filename); + printf("Secondary file (Flash): %s\n", second); + printf("Zero secondary file: %s\n", zerolen == 1 ? "Yes" : "No"); + printf("Port: %s\n", term); + printf("Baud rate: %i\n", baud); + printf("Flow control: %s\n", rts); + printf("Reset command: %s\n", command); + printf("Exit after load: %s\n", do_exit == 1 ? "Yes" : "No"); + printf("Delay 1: %i\n", first_delay); + printf("Delay 2: %i\n", second_delay); + } + + /* Open and configure serial port */ + pfd = open(term, O_RDWR | O_NOCTTY | O_NDELAY); + if (pfd == -1) { + printf("Cannot open serial port %s!\n", term); + return -1; + } + fcntl(pfd, F_SETFL, FNDELAY); + tcgetattr(pfd, &options); + cfsetispeed(&options, baud); + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + if (strcmp(rts, "rts")) { + options.c_cflag &= ~CRTSCTS; + } else { + options.c_cflag |= CRTSCTS; + } + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_oflag &= ~OPOST; + tcsetattr(pfd, TCSANOW, &options); + + /* Reset the board if we can */ + printf("Reset the board to enter bootloader (waiting for CONNECT)...\n"); + if (command) { + printf("Performing reset: %s\n", command); + system(command); + } + + /* Primary bootloader wait loop */ + i = 0; + while (1) { + /* Wait for CONNECT */ + r = write(pfd, (const void*)"\0", 1); + sleep(1); + r = read(pfd, &buf[i], sizeof(buf)-1-i); + if (r > 0) { + buf[i+r] = '\0'; + printf("%s", &buf[i]); fflush(stdout); + if (strstr(&buf[i], "CONNECT")) { + printf("\n"); + break; + } + i += r; + if (i >= sizeof(buf)-1) { + i = 0; + } + } else { + printf("."); fflush(stdout); + } + } + + /* Send primary file */ + if (!filename) { + printf("Please specify firmware file name (-f option)!\n"); + return -1; + } + if (stat(filename, &sbuf)) { + printf("Cannot open firmware file %s!\n", filename); + return -1; + } + ffd = open(filename, O_RDONLY); + if (ffd == -1) { + printf("Cannot open firmware file %s!\n", filename); + return -1; + } + s = sbuf.st_size; + printf("Sending %s (%i bytes)...\n", filename, s); + r = write(pfd, (const void*)&s, 4); + i = 0; + r = read(ffd, buf, 1); + while (r > 0) { + do { + usleep(first_delay); + c = write(pfd, (const void*)buf, r); + } while(c < r); + i += r; + printf("Written %i\r", i); fflush(stdout); + r = read(ffd, buf, 1); + } + printf("\n"); + + /* Secondary loader wait loop */ + if (second || zerolen) { + /* Wait for ready */ + printf("Sending secondary file (waiting for ready)...\n"); + i = 0; + while (1) { + sleep(1); + r = read(pfd, &buf[i], sizeof(buf)-1-i); + if (r > 0) { + buf[i+r] = '\0'; + printf("%s", &buf[i]); fflush(stdout); + if (strstr(buf, "ready")) { + printf("\n"); + break; + } + i += r; + if (i >= sizeof(buf)-1) { + i = 0; + } + } else { + printf("."); fflush(stdout); + } + } + + /* Send secondary file */ + if (second) { + if (stat(second, &sbuf)) { + printf("Cannot open secondary file %s!\n", second); + return -1; + } + sfd = open(second, O_RDONLY); + if (sfd == -1) { + printf("Cannot open secondary file %s!\n", second); + return -1; + } + s = sbuf.st_size; + printf("Sending %s (%i bytes)...\n", second, s); + r = write(pfd, (const void*)&s, 4); + i = 0; + r = read(sfd, buf, 1); + while (r > 0) { + do { + usleep(second_delay); + c = write(pfd, (const void*)buf, r); + } while(c < r); + i += r; + printf("Written %i\r", i); fflush(stdout); + r = read(sfd, buf, 1); + } + printf("\n"); + } else if (zerolen) { + s = 0; + printf("Sending %i...\n", s); + write(pfd, (const void*)&s, 4); + } + } + + /* Send the remaining arguments */ + if (args) { + printf("Sending %s\n", args); + r = write(pfd, (const void*)args, strlen(args)); + r = write(pfd, (const void*)",", 1); + } + + /* Drop in echo mode */ + if (!do_exit) { + while (1) { + r = read(pfd, buf, sizeof(buf)); + if (r > 0) { + buf[r] = '\0'; + printf("%s", buf); fflush(stdout); + } + } + } +} + + +void help(void) +{ + printf("Example usage: mc1322x-load -f foo.bin -t /dev/ttyS0 -b 9600\n"); + printf(" or : mc1322x-load -f flasher.bin -s flashme.bin 0x1e000,0x11223344,0x55667788\n"); + printf(" or : mc1322x-load -f flasher.bin -z 0x1e000,0x11223344,0x55667788\n"); + printf(" -f required: binary file to load\n"); + printf(" -s optional: secondary binary file to send\n"); + printf(" -z optional: send a zero length file as secondary\n"); + printf(" -t, terminal default: /dev/ttyUSB0\n"); + printf(" -u, baud rate default: 115200\n"); + printf(" -r [none|rts] flow control default: rts\n"); + printf(" -c command to run for autoreset: \n"); + printf(" e.g. -c 'bbmc -l redbee-econotag -i 0 reset'\n"); + printf(" -e exit instead of dropping to terminal display\n"); + printf(" -a first intercharacter delay, passed to usleep\n"); + printf(" -b second intercharacter delay, passed to usleep\n"); + printf("\n"); + printf("Anything on the command line is sent after all of the files.\n\n"); +} diff --git a/redbee-econotag/tools/mc1322x-load.pl b/redbee-econotag/tools/mc1322x-load.pl new file mode 100755 index 0000000000..bfc1d1ffcd --- /dev/null +++ b/redbee-econotag/tools/mc1322x-load.pl @@ -0,0 +1,171 @@ +#!/usr/bin/perl -w + +use Device::SerialPort; +use Term::ReadKey; +use Getopt::Long; +use Time::HiRes qw(usleep); + +use strict; + +my $filename = ''; +my $second = ''; +my $term = '/dev/ttyUSB0'; +my $baud = '115200'; +my $verbose; +my $rts = 'rts'; +my $command = ''; +my $first_delay = 50; +my $second_delay = 100; +my $do_exit; +my $zerolen; + +GetOptions ('file=s' => \$filename, + 'secondfile=s' => \$second, + 'zerolen' => \$zerolen, + 'terminal=s' => \$term, + 'verbose' => \$verbose, + 'u|baud=s' => \$baud, + 'rts=s' => \$rts, + 'command=s' => \$command, + 'a=s' => \$first_delay, + 'b=s' => \$second_delay, + 'exit' => \$do_exit, + ) or die 'bad options'; + +$| = 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 " or : mc1322x-load.pl -f flasher.bin -z 0x1e000,0x11223344,0x55667788\n"; + print " -f required: binary file to load\n"; + print " -s optional: secondary binary file to send\n"; + print " -z optional: send a zero length file as secondary\n"; + print " -t, terminal default: /dev/ttyUSB0\n"; + print " -u, --baud baud rate default: 115200\n"; + print " -r [none|rts] flow control default: rts\n"; + print " -c command to run for autoreset: \n"; + print " e.g. -c 'bbmc -l redbee-econotag -i 0 reset'\n"; + print " -e exit instead of dropping to terminal display\n"; + print " -a first intercharacter delay, passed to usleep\n"; + print " -b second intercharacter delay, passed to usleep\n"; + print "\n"; + print "anything on the command line is sent\n"; + print "after all of the files.\n\n"; + exit; +} + +if (!(-e $filename)) { die "file $filename not found\n"; } +if (($second ne '') && !(-e $second)) { die "secondary file $second not found\n"; } + +my $ob = Device::SerialPort->new ($term) or die "Can't start $term\n"; + # next test will die at runtime unless $ob + +$ob->baudrate($baud); +$ob->parity('none'); +$ob->databits(8); +$ob->stopbits(1); +if($rts eq 'rts') { + $ob->handshake('rts'); +} else { + $ob->handshake('none'); +} +$ob->read_const_time(1000); # 1 second per unfulfilled "read" call +$ob->rts_active(1); + +my $s = 0; +my $reset = 0; +my $size = 0; + +while(1) { + + my $c; my $count; my $ret = ''; my $test=''; + + if($s == 1) { print "secondary send...\n"; } + + $ob->write(pack('C','0')); + + if(($command ne '') && + ($reset eq 0)) { + $reset++; + system($command); + } + + if($s == 1) { + $test = 'ready'; + } else { + $test = 'CONNECT'; + } + + 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 || (defined($zerolen) && ($s == 1))) { + + if(defined($zerolen) && ($s == 1)) { + $size = 0; + } else { + $size = -s $filename; + } + + print ("Size: $size bytes\n"); + $ob->write(pack('V',$size)); + + if(($s == 0) || + ((!defined($zerolen)) && ($s == 1))) { + open(FILE, $filename) or die($!); + print "Sending $filename\n"; + + my $i = 1; + while(read(FILE, $c, 1)) { + $i++; + usleep($first_delay) if ( $s == 0 ) && ($first_delay != 0); + usleep($second_delay) if ( $s == 1 ) && ($second_delay != 0); + $ob->write($c); + } + } + } + + last if ($s==1); + if((-e $second) || defined($zerolen)) { + $s=1; $filename = $second; + } else { + last; + } + +} + +print "done sending files.\n"; + +if(scalar(@ARGV)!=0) { + print "sending " ; + print @ARGV; + print ",\n"; + + $ob->write(@ARGV); + $ob->write(','); +} + +if(defined($do_exit)) { + exit; +} + +my $c; my $count; +while(1) { + ($count, $c) = $ob->read(1); + print $c if (defined($count) && ($count != 0)); +} + +$ob -> close or die "Close failed: $!\n"; +ReadMode 0; +undef $ob; # closes port AND frees memory in perl +exit; +