diff --git a/redbee-econotag/Makefile b/redbee-econotag/Makefile index 391c9bd42f07c4d2520fb080a1a3e1adec80b2fb..ae4ccfd0a780265afd897e9e6930b8b90f81579d 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/README b/redbee-econotag/README new file mode 100644 index 0000000000000000000000000000000000000000..7cce0fdd0536ab9f6da6205048dc66f544f02f12 --- /dev/null +++ b/redbee-econotag/README @@ -0,0 +1,11 @@ +Flashing: +tools/mc1322x-load.pl -f <path/to/binary> -t /dev/<tty-device> + +more information: https://github.com/malvira/libmc1322x/wiki/libmc1322x#loading-images-to-ram-with-mc1322x-loadpl + +Erase: +cd tools/ftditools/ +make +./bbmc -l redbee-econotag erase + +more information: https://github.com/malvira/libmc1322x/wiki/bbmc \ No newline at end of file diff --git a/redbee-econotag/board_init.c b/redbee-econotag/board_init.c index 5a0b03177cb1366c47f0b445a2ba77d1ca91a537..7c157b10382d729df73162b82f8697b321f03eee 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/gpio.c b/redbee-econotag/drivers/gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..c9b867277a6e6fa082d03b369c494f70b1df430c --- /dev/null +++ b/redbee-econotag/drivers/gpio.c @@ -0,0 +1,74 @@ +/* + * gpio.c - GPIO driver for redbee + * Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "gpio.h" + +inline void gpio_pad_dir(volatile uint64_t data) +{ + GPIO->PAD_DIR0 = (data & 0xffffffff); + GPIO->PAD_DIR1 = (data >> 32); +} + +inline void gpio_data(volatile uint64_t data) +{ + GPIO->DATA0 = (data & 0xffffffff); + GPIO->DATA1 = (data >> 32); +} + +inline uint64_t gpio_data_get(volatile uint64_t bits) { + uint64_t rdata = 0; + + rdata = GPIO->DATA0 & (bits & 0xffffffff); + rdata |= (GPIO->DATA1 & (bits >> 32)) << 32; + + return rdata; +} + +inline void gpio_pad_pu_en(volatile uint64_t data) +{ + GPIO->PAD_PU_EN0 = (data & 0xffffffff); + GPIO->PAD_PU_EN1 = (data >> 32); +} + +inline void gpio_data_sel(volatile uint64_t data) +{ + GPIO->DATA_SEL0 = (data & 0xffffffff); + GPIO->DATA_SEL1 = (data >> 32); +} + +inline void gpio_pad_pu_sel(volatile uint64_t data) +{ + GPIO->PAD_PU_SEL0 = (data & 0xffffffff); + GPIO->PAD_PU_SEL1 = (data >> 32); +} + +inline void gpio_data_set(volatile uint64_t data) +{ + GPIO->DATA_SET0 = (data & 0xffffffff); + GPIO->DATA_SET1 = (data >> 32); +} + +inline void gpio_data_reset(volatile uint64_t data) +{ + GPIO->DATA_RESET0 = (data & 0xffffffff); + GPIO->DATA_RESET1 = (data >> 32); +} + +inline void gpio_pad_dir_set(volatile uint64_t data) +{ + GPIO->PAD_DIR_SET0 = (data & 0xffffffff); + GPIO->PAD_DIR_SET1 = (data >> 32); +} + +inline void gpio_pad_dir_reset(volatile uint64_t data) +{ + GPIO->PAD_DIR_RESET0 = (data & 0xffffffff); + GPIO->PAD_DIR_RESET1 = (data >> 32); +} \ No newline at end of file diff --git a/redbee-econotag/drivers/include/gpio.h b/redbee-econotag/drivers/include/gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..b46051a1a7954ad6cda37a982eb14acd7046a8b8 --- /dev/null +++ b/redbee-econotag/drivers/include/gpio.h @@ -0,0 +1,159 @@ +/* + * gpio.h - GPIO driver for redbee + * Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#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: + + GPIO->FUNC_SEL0 |= 0x00008000; // set a whole register + + GPIO->FUNC_SEL_08 = 2; // set just one pin + + #define MY_PIN GPIO_08 + GPIO->FUNC_SEL.MY_PIN = 2; // same, to allow #define for pin names + GPIO->DATA.MY_PIN = 1; + + gpio_set(GPIO_08); // efficiently set or clear a single output bit + gpio_reset(GPIO_08); +*/ + +// GPIO to Function Alias macros: + +#define ADC0 GPIO_30 +#define ADC1 GPIO_31 +#define ADC2 GPIO_32 +#define ADC3 GPIO_33 +#define ADC4 GPIO_34 +#define ADC5 GPIO_35 +#define ADC6 GPIO_36 +#define ADC7 GPIO_37 +#define TDO GPIO_49 +#define TDI GPIO_48 +#define TCK GPIO_47 +#define TMS GPIO_46 +#define U2RTS GPIO_21 +#define U2CTS GPIO_20 +#define U2RX GPIO_19 +#define U2TX GPIO_18 +#define U1RTS GPIO_17 +#define U1CTS GPIO_16 +#define U1RX GPIO_15 +#define U1TX GPIO_14 +#define SDA GPIO_13 +#define SCL GPIO_12 +#define TMR3 GPIO_11 +#define TMR2 GPIO_10 +#define TMR1 GPIO_09 +#define TMR0 GPIO_08 +#define SCK GPIO_07 +#define MOSI GPIO_06 +#define MISO GPIO_05 +#define SS GPIO_04 +#define BTCK GPIO_03 +#define FSYN GPIO_02 +#define SSIRX GPIO_01 +#define SSITX GPIO_00 +#define KBI7 GPIO_29 +#define KBI6 GPIO_28 +#define KBI5 GPIO_27 +#define KBI4 GPIO_26 +#define KBI3 GPIO_25 +#define KBI2 GPIO_24 +#define KBI1 GPIO_23 +#define KBI0 GPIO_22 +#define TXON GPIO_44 +#define RXON GPIO_45 +#define ANT1 GPIO_42 +#define ANT2 GPIO_43 +#define VREF2H GPIO_38 +#define VREF2L GPIO_39 +#define VREF1H GPIO_40 +#define VREF1L GPIO_41 +#define MDO0 GPIO_51 +#define MDO1 GPIO_52 +#define MDO2 GPIO_53 +#define MDO3 GPIO_54 +#define MDO4 GPIO_55 +#define MDO5 GPIO_56 +#define MDO6 GPIO_57 +#define MDO7 GPIO_58 +#define MSEO0 GPIO_59 +#define MSEO1 GPIO_60 +#define RDY GPIO_61 +#define EVTO GPIO_62 +#define MCKO GPIO_50 +#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) \ + _V(x,n,08) _V(x,n,09) _V(x,n,10) _V(x,n,11) _V(x,n,12) _V(x,n,13) _V(x,n,14) _V(x,n,15) \ + _V(x,n,16) _V(x,n,17) _V(x,n,18) _V(x,n,19) _V(x,n,20) _V(x,n,21) _V(x,n,22) _V(x,n,23) \ + _V(x,n,24) _V(x,n,25) _V(x,n,26) _V(x,n,27) _V(x,n,28) _V(x,n,29) _V(x,n,30) _V(x,n,31) \ + _V(x,n,32) _V(x,n,33) _V(x,n,34) _V(x,n,35) _V(x,n,36) _V(x,n,37) _V(x,n,38) _V(x,n,39) \ + _V(x,n,40) _V(x,n,41) _V(x,n,42) _V(x,n,43) _V(x,n,44) _V(x,n,45) _V(x,n,46) _V(x,n,47) \ + _V(x,n,48) _V(x,n,49) _V(x,n,50) _V(x,n,51) _V(x,n,52) _V(x,n,53) _V(x,n,54) _V(x,n,55) \ + _V(x,n,56) _V(x,n,57) _V(x,n,58) _V(x,n,59) _V(x,n,60) _V(x,n,61) _V(x,n,62) _V(x,n,63) + +struct GPIO_struct { +#define _IO(x) \ + union { struct { uint32_t x##0; uint32_t x##1; }; \ + struct { _REP(x, 1) }; \ + struct GPIO_##x { _REP(GPIO, 1) } x; }; +#define _IO_2bit(x) \ + union { struct { uint32_t x##0; uint32_t x##1; uint32_t x##2; uint32_t x##3; }; \ + struct { _REP(x, 2) }; \ + struct GPIO_##x { _REP(GPIO, 2) } x; }; + + _IO(PAD_DIR); + _IO(DATA); + _IO(PAD_PU_EN); + _IO_2bit(FUNC_SEL); + _IO(DATA_SEL); + _IO(PAD_PU_SEL); + _IO(PAD_HYST_EN); + _IO(PAD_KEEP); + _IO(DATA_SET); + _IO(DATA_RESET); + _IO(PAD_DIR_SET); + _IO(PAD_DIR_RESET); +}; +#undef _IO +#undef _IO_2bit + +/* Build an enum lookup to map GPIO_08 -> 8 */ +#undef _V +#define _V(x,n,i) __NUM_GPIO_GPIO_##i, +enum { _REP(0,0) }; + +/* Macros to set or reset a data pin in the fastest possible way */ +#define gpio_set(gpio_xx) __gpio_set(gpio_xx) +#define __gpio_set(gpio_xx) \ + ((__NUM_GPIO_##gpio_xx < 32) \ + ? (GPIO->DATA_SET0 = (1 << (__NUM_GPIO_##gpio_xx - 0))) \ + : (GPIO->DATA_SET1 = (1 << (__NUM_GPIO_##gpio_xx - 32)))) +#define gpio_reset(gpio_xx) __gpio_reset(gpio_xx) +#define __gpio_reset(gpio_xx) \ + ((__NUM_GPIO_##gpio_xx < 32) \ + ? (GPIO->DATA_RESET0 = (1 << (__NUM_GPIO_##gpio_xx - 0))) \ + : (GPIO->DATA_RESET1 = (1 << (__NUM_GPIO_##gpio_xx - 32)))) + +#undef _REP +#undef _V + +static volatile struct GPIO_struct * const GPIO = (void *) (0x80000000); + +#endif \ No newline at end of file diff --git a/redbee-econotag/drivers/include/uart.h b/redbee-econotag/drivers/include/uart.h new file mode 100644 index 0000000000000000000000000000000000000000..928a2157a9b90109aad9a5391b29794ba93696af --- /dev/null +++ b/redbee-econotag/drivers/include/uart.h @@ -0,0 +1,139 @@ +/* + * uart.h - UART driver for redbee + * Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#ifndef UART_H +#define UART_H + +/*-----------------------------------------------------------------*/ +/* UART */ +#define UART1_BASE (0x80005000) +#define UART2_BASE (0x8000B000) + +struct UART_struct { + union { + uint32_t CON; + struct UART_CON { + uint32_t :16; + uint32_t TST:1; + uint32_t MRXR:1; + uint32_t MTXR:1; + uint32_t FCE:1; + uint32_t FCP:1; + uint32_t XTIM:1; + uint32_t :2; + uint32_t TXOENB:1; + uint32_t CONTX:1; + uint32_t SB:1; + uint32_t ST2:1; + uint32_t EP:1; + uint32_t PEN:1; + uint32_t RXE:1; + uint32_t TXE:1; + } CONbits; + }; + union { + uint32_t STAT; + struct UART_STAT { + uint32_t :24; + uint32_t TXRDY:1; + uint32_t RXRDY:1; + uint32_t RUE:1; + uint32_t ROE:1; + uint32_t TOE:1; + uint32_t FE:1; + uint32_t PE:1; + uint32_t SE:1; + } USTATbits; + }; + union { + uint32_t DATA; + struct UART_DATA { + uint32_t :24; + uint32_t DATA:8; + } DATAbits; + }; + union { + uint32_t RXCON; + struct UART_URXCON { + uint32_t :26; + uint32_t LVL:6; + } RXCONbits; + }; + union { + uint32_t TXCON; + struct UART_TXCON { + uint32_t :26; + uint32_t LVL:6; + } TXCONbits; + }; + union { + uint32_t CTS; + struct UART_CTS { + uint32_t :27; + uint32_t LVL:5; + } CTSbits; + }; + union { + uint32_t BR; + struct UART_BR { + uint32_t INC:16; + uint32_t MOD:16; + } BRbits; + }; +}; + +static volatile struct UART_struct * const UART1 = (void *) (UART1_BASE); +static volatile struct UART_struct * const UART2 = (void *) (UART2_BASE); + +void uart_init(volatile struct UART_struct * uart, uint32_t baud); +void uart_set_baudrate(volatile struct UART_struct * uart, uint32_t baud); +void uart_flow_ctl(volatile struct UART_struct * uart, uint8_t on); + + +/* The mc1322x has a 32 byte hardware FIFO for transmitted characters. + * Currently it is always filled from a larger RAM buffer. It would be + * possible to eliminate that overhead by filling directly from a chain + * of data buffer pointers, but printf's would be not so easy. + */ +#define UART1_TX_BUFFERSIZE 1024 +extern volatile uint32_t u1_tx_head, u1_tx_tail; +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. + * RAM transfers will occur on interrupt when the FIFO is nearly full. + * If a smaller buffersize is specified hardware flow control will be + * initiated at that FIFO level. + * Set to 32 for no flow control or RAM buffer. + */ +#define UART1_RX_BUFFERSIZE 128 +#if UART1_RX_BUFFERSIZE > 32 +extern volatile uint32_t u1_rx_head, u1_rx_tail; +#define uart1_can_get() ((u1_rx_head!=u1_rx_tail) || (*UART1_URXCON > 0)) +#else +#define uart1_can_get() (*UART1_URXCON > 0) +#endif +uint8_t uart1_getc(void); + + +#define UART2_TX_BUFFERSIZE 1024 +extern volatile uint32_t u2_tx_head, u2_tx_tail; +void uart2_putc(uint8_t c); + +#define UART2_RX_BUFFERSIZE 128 +#if UART2_RX_BUFFERSIZE > 32 +extern volatile uint32_t u2_rx_head, u2_rx_tail; +#define uart2_can_get() ((u2_rx_head!=u2_rx_tail) || (*UART2_URXCON > 0)) +#else +#define uart2_can_get() (*UART2_URXCON > 0) +#endif +uint8_t uart2_getc(void); + +#endif \ No newline at end of file diff --git a/redbee-econotag/drivers/redbee_uart.c b/redbee-econotag/drivers/redbee_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..621d94e060a1942cbb61d3b66f0e61e09d2f5419 --- /dev/null +++ b/redbee-econotag/drivers/redbee_uart.c @@ -0,0 +1,204 @@ +/* + * redbee_uart.c - UART driver for redbee + * Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "mc1322x.h" +#include "uart.h" +#include "gpio.h" +#include "io.h" + +#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; + + /* calculate inc following equation 13-1 from datasheet */ + /* multiply by another 10 to get a fixed point*/ + inc = ((uint64_t) baudrate * DIV_ * MOD_ * 10 / CLK_) - 10; + /* add 5 and div by 10 to get a rounding */ + inc = (inc + 5) / 10; + + /* disable UARTx to set baudrate */ + uart->CONbits.TXE = 0; + uart->CONbits.RXE = 0; + + /* set baudrate */ + uart->BRbits.INC = inc; + uart->BRbits.MOD = MOD_; + + /* reenable UARTx again */ + /* uart->CON.XTIM = 0 is 16x oversample (datasheet is incorrect) */ + uart->CONbits.XTIM = 0; + uart->CONbits.TXE = 1; + uart->CONbits.RXE = 1; +} + +void uart_flow_ctl ( volatile struct UART_struct* uart, uint8_t on ) { + if (on) { + /* enable flow control */ + if (uart == UART1) { + /* CTS and RTS directions */ + GPIO->PAD_DIR_SET.U1CTS = 1; + GPIO->PAD_DIR_RESET.U1RTS = 1; + /* function select to uart */ + GPIO->FUNC_SEL.U1CTS = 1; + GPIO->FUNC_SEL.U1RTS = 1; + } + else { + /* UART2 */ + /* CTS and RTS directions */ + GPIO->PAD_DIR_SET.U2CTS = 1; + GPIO->PAD_DIR_RESET.U2RTS = 1; + /* function select to uart */ + GPIO->FUNC_SEL.U2CTS = 1; + GPIO->FUNC_SEL.U2RTS = 1; + } + /* enable flow control */ + uart->CONbits.FCE = 1; + } + else { + /* disable flow control */ + uart->CONbits.FCE = 0; + if (uart == UART1) { + /* CTS and RTS directions */ + GPIO->PAD_DIR_RESET.U1CTS = 1; + GPIO->PAD_DIR_RESET.U1RTS = 1; + /* function select to GPIO */ + GPIO->FUNC_SEL.U1CTS = 3; + GPIO->FUNC_SEL.U1RTS = 3; + } + else { + /* CTS and RTS directions */ + GPIO->PAD_DIR_RESET.U2CTS = 1; + GPIO->PAD_DIR_RESET.U2RTS = 1; + /* function select to GPIO */ + GPIO->FUNC_SEL.U2CTS = 3; + GPIO->FUNC_SEL.U2RTS = 3; + } + } +} + +// 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 */ + uart->CONbits.TXE = 1; + uart->CONbits.RXE = 1; + + /* interrupt when this or more bytes are free in the tx buffer */ + uart->TXCON = 16; + + if (uart == UART1) { + /* TX and RX direction */ + GPIO->PAD_DIR_SET.U1TX = 1; + GPIO->PAD_DIR_RESET.U1RX = 1; + + /* set function selection to UART */ + GPIO->FUNC_SEL.U1TX = 1; + GPIO->FUNC_SEL.U1RX = 1; + + UART1->CONbits.TXE = 1; /*< enable transmit */ + 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; +#elif UART1_RX_BUFFERSIZE < 32 + UART1->CONbits.FCE = 1; /*< enable flowcontrol */ + UART1->CONbits.MRXR = 1; /*< disable Rx interrupt */ + UART1->CTSbits.LVL = UART1_RX_BUFFERSIZE; /*< drop cts when tx buffer at trigger level */ + GPIO->FUNC_SEL1.U1CTS = 1; /*< set GPIO 16 to UART1 CTS */ + GPIO->FUNC_SEL1.U1RTS = 1; /*< set GPIO 17 to UART1 RTS */ +#else + UART1->CONbits.MRXR = 1; /*< disable rx interrupt */ +#endif + + //u1_tx_head = 0; + //u1_tx_tail = 0; + + //enable_irq(UART1); + ITC->INTENABLEbits.UART1 = 1; + } + else { + /* UART2 */ + /* TX and RX direction */ + GPIO->PAD_DIR_SET.U2TX = 1; + GPIO->PAD_DIR_RESET.U2RX = 1; + + /* set function selection to UART */ + GPIO->FUNC_SEL.U2TX = 1; + GPIO->FUNC_SEL.U2RX = 1; + + UART2->CONbits.TXE = 1; /*< enable transmit */ + 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; +#elif UART2_RX_BUFFERSIZE < 32 + UART2->CONbits.FCE = 1; /*< enable flowcontrol */ + UART2->CONbits.MRXR = 1; /*< disable Rx interrupt */ + UART2->CTSbits.LVL = UART2_RX_BUFFERSIZE; /*< drop cts when tx buffer at trigger level */ + GPIO->FUNC_SEL1.U1CTS = 1; /*< set GPIO 16 to UART2 CTS */ + GPIO->FUNC_SEL1.U1RTS = 1; /*< set GPIO 17 to UART2 RTS */ +#else + UART2->CONbits.MRXR = 1; /*< disable rx interrupt */ +#endif + + // u2_tx_head = 0; + //u2_tx_tail = 0; + + //enable_irq(UART2); + ITC->INTENABLEbits.UART2 = 1; + } + + uart_set_baudrate( uart, baudrate ); +} + +static inline uint32_t uart0_puts ( uint8_t *astring, uint32_t length ) { + uint32_t i = 0; + for (; i<length; i++) { + uart1_putc( astring[i] ); + } + + return i; +} + +void stdio_flush(void) +{ + ITC->INTENABLEbits.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 046ed26ab16a5fb38278271fc944caef297e7ef0..a4a53afc4015565c68a013d45f70cad72ec3da65 100644 --- a/redbee-econotag/drivers/redbee_uart1.c +++ b/redbee-econotag/drivers/redbee_uart1.c @@ -1,6 +1,7 @@ /* - * redbee_uart1.c - UART1 driver for redbee + * uart1.c - UART1 driver for redbee * Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr> + * 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> * * This source code is licensed under the GNU General Public License, * Version 3. See the file LICENSE for more details. @@ -9,35 +10,39 @@ */ #include "mc1322x.h" +#include "board_uart0.h" +#include "uart.h" -static volatile unsigned int running = 0; -static volatile unsigned int fifo = 0; - -static inline int uart0_puts(char *astring, int length) -{ - int i; - for (i=0;i<length;i++) { - /* TODO: Fix me */ - while(UART1->TXCON != 0); - UART1->DATA = astring[i]; +void uart1_isr ( void ) { + if ( UART1->USTATbits.RXRDY == 1 ) { +#ifdef MODULE_UART0 + if ( uart0_handler_pid ) { + while ( UART1->RXCON != 0 ) { + uart0_handle_incoming( UART1->DATA ); + if ( ++i >= UART0_BUFSIZE ) { + uart0_notify_thread(); + i = 0; + } + } + uart0_notify_thread(); + } +#endif } - return length; } -int fw_puts(char *astring, int length) -{ - return uart0_puts(astring, length); +void uart1_putc ( uint8_t c ) { + /* while uart fifo is full */ + while ( UART1->TXCON == 0 ) { + /* wait */ + } + UART1->DATA = c; } -void stdio_flush(void) -{ - /* disable TX interrupt */ - UART1->CONbits.MTXR = 1; - while(running) { - while(UART1->TXCON != 0); - fifo=0; - push_queue(); // dequeue to fifo +uint8_t uart1_getc ( void ) { + /* while uart fifo is empty */ + while ( UART1->RXCON == 0 ) { + /* wait */ } - /* enable TX interrupt */ - UART1->CONbits.MTXR = 0; -} + + return UART1->DATA; +} \ No newline at end of file diff --git a/redbee-econotag/drivers/redbee_uart2.c b/redbee-econotag/drivers/redbee_uart2.c new file mode 100644 index 0000000000000000000000000000000000000000..a1b2e6bab9a0e399554d74897f24cb35985fd6cd --- /dev/null +++ b/redbee-econotag/drivers/redbee_uart2.c @@ -0,0 +1,48 @@ +/* + * uart1.c - UART1 driver for redbee + * Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr> + * 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "mc1322x.h" +#include "board_uart0.h" +#include "uart.h" + +void uart2_isr ( void ) { + int i = 0; + if ( UART2->USTATbits.RXRDY == 1 ) { +#ifdef MODULE_UART0 + if ( uart0_handler_pid ) { + while ( UART2->RXCON != 0 ) { + uart0_handle_incoming( UART2->DATA ); + if ( ++i >= UART0_BUFSIZE ) { + uart0_notify_thread(); + i = 0; + } + } + uart0_notify_thread(); + } +#endif + } +} + +void uart2_putc ( uint8_t c ) { + /* while uart fifo is full */ + while ( UART2->TXCON == 0 ) { + /* wait */ + } + UART2->DATA = c; +} + +uint8_t uart2_getc ( void ) { + /* while uart fifo is empty */ + while ( UART2->RXCON == 0 ) { + /* wait */ + } + return UART2->DATA; +} \ No newline at end of file diff --git a/redbee-econotag/tools/ftditools/Makefile b/redbee-econotag/tools/ftditools/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..521d7d14ff292bdadb245ce797f70ca696843a97 --- /dev/null +++ b/redbee-econotag/tools/ftditools/Makefile @@ -0,0 +1,17 @@ +INSTALL= /usr/local/bin + +################ + +LDLIBS = -lftdi + +TARGETS = bbmc + +CFLAGS = -Wall -Wextra #-Werror + +all: $(TARGETS) + +clean: + -rm -f $(TARGETS) + +install: all + cp bbmc $(INSTALL) \ No newline at end of file diff --git a/redbee-econotag/tools/ftditools/bbmc.c b/redbee-econotag/tools/ftditools/bbmc.c new file mode 100644 index 0000000000000000000000000000000000000000..7e2b6544129e40a208bdfcc4a2c01ff0e9832866 --- /dev/null +++ b/redbee-econotag/tools/ftditools/bbmc.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2010, Mariano Alvira <mar@devl.org> 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. + * + * This file is part of libmc1322x: see http://mc1322x.devl.org + * for details. + * + * + */ + +/* control reset and VREF2 lines */ + +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <getopt.h> +#include <ftdi.h> + +#define DEBUG 0 + +#define low(x) (1 << x) +#define high(x) (1 << (x + 8)) + +#define REDBEE_ECONOTAG_RESET high(2) +#define REDBEE_ECONOTAG_VREF2L high(7) +#define REDBEE_ECONOTAG_VREF2H high(6) +#define REDBEE_ECONOTAG_INTERFACE INTERFACE_A + +#define REDBEE_USB_RESET high(2) +#define REDBEE_USB_VREF2L low(5) +#define REDBEE_USB_VREF2H low(6) +#define REDBEE_USB_INTERFACE INTERFACE_B + +#define FLEXIBITY_USB_RESET high(2) +#define FLEXIBITY_USB_VREF2L high(7) +#define FLEXIBITY_USB_VREF2H high(6) +#define FLEXIBITY_USB_INTERFACE INTERFACE_A + +#define BOARD REDBEE_USB + +#define STR(x) #x +#define STR2(x) STR(x) +#define CAT(x,y) x##y +#define CAT2(x, y, z) x##y##z + +#define dir(x) ( CAT(x,_RESET) | CAT(x,_VREF2L) | CAT(x,_VREF2H)) +#define interface(x) ( CAT(x,_INTERFACE) ) +#define reset_release(x) ( CAT(x,_RESET) ) +#define reset_set(x) ( 0 ) +#define vref2_normal(x) ( CAT(x,_VREF2H) ) +#define vref2_erase(x) ( CAT(x,_VREF2L) ) + +/* fgets input buffer length: for prompts and such */ +#define BUF_LEN 32 + +struct layout { + char *name; + char *desc; + enum ftdi_interface interface; + uint16_t dir; + uint16_t reset_release; + uint16_t reset_set; + uint16_t vref2_normal; + uint16_t vref2_erase; +}; + +int print_and_prompt( struct ftdi_device_list *devlist ); +int bb_mpsee(struct ftdi_context *ftdic, uint16_t dir, uint16_t val); +void reset(struct ftdi_context *ftdic, const struct layout * l); +void erase(struct ftdi_context *ftdic, const struct layout * l); +void usage(void); + +#define std_layout(x) \ + .interface = interface(x), \ + .dir = dir(x), \ + .reset_release = reset_release(x), \ + .reset_set = reset_set(x), \ + .vref2_normal = vref2_normal(x), \ + .vref2_erase = vref2_erase(x), + +static struct layout layouts[] = +{ + { .name = "redbee-econotag", + .desc = "Redbee Econotag", + std_layout(REDBEE_ECONOTAG) + }, + { .name = "redbee-usb", + .desc = "Redbee USB stick", + std_layout(REDBEE_USB) + }, + { .name = "flexibity", + .desc = "Flexibity USB Interface", + std_layout(FLEXIBITY_USB) + }, + { .name = NULL, /* end of table */ }, +}; + +struct command { + char *name; + char *desc; + void (*cmd)(struct ftdi_context *ftdic, const struct layout * l); +}; + +static const struct command commands[] = +{ + { + .name = "reset", + .desc = "Toggles reset pin", + .cmd = reset, + }, + { + .name = "erase", + .desc = "Sets VREF2 erase mode; toggles reset; waits 2 sec.; sets normal; toggles reset again", + .cmd = erase, + }, + { .name = NULL, /* end of table */ }, +}; + +struct layout * find_layout(char * str) +{ + uint32_t i = 0; + + while(layouts[i].name != NULL) { + if(strcmp(layouts[i].name, str) == 0) { return &layouts[i]; } + i++; + } + + return NULL; +} + +static uint32_t vendid = 0x0403; uint32_t prodid = 0x6010; + +#if __APPLE__ +static void restore_ftdi_kext(void) +{ + system("sudo kextload /System/Library/Extensions/FTDIUSBSerialDriver.kext"); +} +#endif + +int main(int argc, char **argv) +{ + struct ftdi_context ftdic; + struct ftdi_device_list *devlist; + int dev_index = -1; int num_devs; + char layout_str[BUF_LEN]; + struct layout layout; + struct layout *l = NULL; + int i, ret; + + /* overrides for layout parameters */ + int interface = -1; + int dir = -1; + int reset_release = -1; + int reset_set = -1; + int vref2_normal = -1; + int vref2_erase = -1; + + layout.name = NULL; + + while (1) { + int c; + int option_index = 0; + static struct option long_options[] = { + {"layout", required_argument, 0, 'l'}, + {"index", required_argument, 0, 'i'}, + {"vendor", required_argument, 0, 'v'}, + {"product", required_argument, 0, 'p'}, + {"dir", required_argument, 0, 0 }, + {"reset_release", required_argument, 0, 0 }, + {"reset_set", required_argument, 0, 0 }, + {"vref2_normal", required_argument, 0, 0 }, + {"vref2_erase", required_argument, 0, 0 }, + {"interface", required_argument, 0, 0 }, + {"help", no_argument, 0, '?'}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "i:l:v:p:", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + /* process long opts */ + case 0: + if(strcmp(long_options[option_index].name, "interface") == 0) { + sscanf(optarg, "%i", &interface); + } + if(strcmp(long_options[option_index].name, "dir") == 0) { + sscanf(optarg, "%i", &dir); + } + if (strcmp(long_options[option_index].name, "reset_release") == 0) { + sscanf(optarg, "%i", &reset_release); + } + if (strcmp(long_options[option_index].name, "reset_set") == 0) { + sscanf(optarg, "%i", &reset_set); + } + if (strcmp(long_options[option_index].name, "vref2_normal") == 0) { + sscanf(optarg, "%i", &vref2_normal); + } + if (strcmp(long_options[option_index].name, "vref2_erase") == 0) { + sscanf(optarg, "%i", &vref2_erase); + } + break; + + case 'l': + strncpy(layout_str, optarg, BUF_LEN); + break; + case 'i': + dev_index = atoi(optarg); + break; + case 'v': + sscanf(optarg, "%i", &vendid); + break; + case 'p': + sscanf(optarg, "%i", &prodid); + break; + default: + usage(); + break; + } + } + + if( !(l = find_layout(layout_str)) && + !((interface >= 0) && + (dir >= 0) && + (reset_release >= 0) && + (reset_set >= 0) && + (vref2_normal >= 0) && + (vref2_erase >= 0)) + ) { + + printf("*** You must specify a layout or a complete set of overrides\n"); + return EXIT_FAILURE; + } + + if(l) { + memcpy(&layout, l, sizeof(struct layout)); + } + +#define override(x) if(x > 0) { layout.x = x; } + override(interface); + override(dir); + override(reset_release); override(reset_set); + override(vref2_normal); override(vref2_erase); + + if ((num_devs = ftdi_usb_find_all(&ftdic, &devlist, vendid, prodid)) < 0) + { + fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", + num_devs, + ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + + if (ftdi_init(&ftdic) < 0) + { + fprintf(stderr, "ftdi_init failed\n"); + return EXIT_FAILURE; + } + + if ((ret = ftdi_set_interface(&ftdic, layout.interface)) < 0) { + fprintf(stderr, "couldn't set interface %d, err %d (%s)\n", layout.interface, ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + + printf("Found %d devices with vendor id 0x%04x product id 0x%04x\n", + num_devs, vendid, prodid); + + if(num_devs == 0) { return EXIT_SUCCESS; } + + if(num_devs == 1) { dev_index = 0; } + while( (dev_index < 0) || (dev_index >= num_devs)){ + dev_index = print_and_prompt(devlist); + } + + if(layout.name != NULL) { + printf("Opening device %d interface %d using layout %s\n", + dev_index, layout.interface, layout.name); + } else { + printf("Opening device %d interface %d without a layout.\n", + dev_index, layout.interface); + } + + if( (ret = ftdi_usb_open_desc_index( + &ftdic, + vendid, + prodid, + NULL, + NULL, + dev_index)) < 0) { +#if __APPLE__ + if((ret==-5) && (0==system("sudo kextunload /System/Library/Extensions/FTDIUSBSerialDriver.kext"))) { + // Try again without the FTDI kext loaded this time + atexit(&restore_ftdi_kext); + ret = ftdi_usb_open_desc_index( + &ftdic, + vendid, + prodid, + NULL, + NULL, + dev_index + ); + } + if(ret) +#endif // __APPLE__ + { + fprintf(stderr, "couldn't open dev_index %d, err %d (%s)\n", dev_index, ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + } + + + for(i = 0; commands[i].name != NULL; i++) { + if( (argv[optind] != NULL) && + (strcmp(commands[i].name, argv[optind]) == 0)) { break; } + } + if(commands[i].name != NULL) { + commands[i].cmd(&ftdic, &layout); + } else { + printf("invalid command\n"); + + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); + + return EXIT_FAILURE; + } + + printf("done.\n"); + + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); + + return EXIT_SUCCESS; +} + +void usage(void) +{ + int i; + printf( "Usage: bbmc [options|overrides] -l|--layout layout command \n"); + printf( "Commands:\n"); + for(i = 0; commands[i].name != NULL; i++) { + printf( " %s: %s\n", commands[i].name, commands[i].desc); + } + printf("\n"); + printf( "Required options:\n"); + printf( " -l|--layout\t specifiy which board layout to use\n"); + printf( " \t layout is not necessary with a full\n"); + printf( " \t set of overrides\n"); + printf( "\nLayout overrides:\n"); + printf( " --interface\t\t FTDI interface to use\n"); + printf( " --dir\t\t direction (1 is output)\n"); + printf( " --reset_release\t reset release command\n"); + printf( " --reset_set\t\t reset set command\n"); + printf( " --vref2_normal\t vref2 normal\n"); + printf( " --vref2_erase\t vref2 erase\n"); + printf("\n"); + printf( "Layouts:\n"); + for(i = 0; layouts[i].name != NULL; i++) { + printf( "\t%s: %s\n", layouts[i].name, layouts[i].desc); + printf("\n"); + printf( "\t\tinterface: \t0x%04x\n", layouts[i].interface); + printf( "\t\tdir: \t\t0x%04x\n", layouts[i].dir); + printf( "\t\treset release: \t0x%04x\n", layouts[i].reset_release); + printf( "\t\treset hold: \t0x%04x\n", layouts[i].reset_set); + printf( "\t\tvref2 normal: \t0x%04x\n", layouts[i].vref2_normal); + printf( "\t\tvref2 erase: \t0x%04x\n", layouts[i].vref2_erase); + printf("\n"); + } + printf("\n"); + printf( "Options:\n"); + printf( " -i|--index specifiy which device to use (default 0)\n"); + printf( " -v|--vendor set vendor id (default 0x0403)\n"); + printf( " -p|--product set vendor id (default 0x6010)\n"); +} + +int print_and_prompt( struct ftdi_device_list *devlist ) +{ + int i, ret; + struct ftdi_context ftdic; + struct ftdi_device_list *curdev; + char manufacturer[128], description[128], serial[128]; + char input[BUF_LEN]; char *s; + int sel = -1; + + printf("\n"); + + i = 0; + for (curdev = devlist; curdev != NULL; i++) + { + printf(" [%d] ", i); + if (0 > (ret = ftdi_usb_get_strings(&ftdic, + curdev->dev, + manufacturer, 128, + description, 128, + serial, 128))) + { + fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", + ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + printf("Manufacturer: %s, Description: %s, Serial %s\n", + manufacturer, description, serial); + curdev = curdev->next; + } + + printf("\nUse which device? "); + + s = fgets(input, BUF_LEN, stdin); + if (s != NULL) { + size_t last = strlen (input) - 1; + if (input[last] == '\n') input[last] = '\0'; + } + + sscanf(s, "%i",&sel); + + return sel; +} + +void reset(struct ftdi_context *ftdic, const struct layout * l) +{ + + /* using MPSSE since it give access to high GPIO*/ + /* set as inputs for now */ + ftdi_set_bitmode(ftdic, 0 , BITMODE_MPSSE); + + printf("toggle reset\n"); + + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); + bb_mpsee(ftdic, l->dir, (l->reset_set | l->vref2_normal)); + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); + + return; + +} + + +void erase(struct ftdi_context *ftdic, const struct layout * l) +{ + printf("setting VREF2 erase\n"); + + /* using MPSSE since it give access to high GPIO*/ + /* set as inputs for now */ + ftdi_set_bitmode(ftdic, 0 , BITMODE_MPSSE); + + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_erase)); + + printf("toggle reset\n"); + + bb_mpsee(ftdic, l->dir, (l->reset_set | l->vref2_erase)); + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_erase)); + + printf("waiting for erase\n"); + + sleep(2); + + printf("setting VREF2 normal\n"); + + bb_mpsee(ftdic, l->dir, (l->reset_release | l->vref2_normal)); + + reset(ftdic, l); + + return; + +} + + +int bb_mpsee(struct ftdi_context *ftdic, uint16_t dir, uint16_t val) +{ + uint8_t buf[3]; + int ret; + + /* command "set data bits low byte" */ + buf[0] = 0x80; + buf[1] = (val & 0xff); + buf[2] = dir & 0xff; +#if DEBUG + fprintf(stderr,"write %x %x %x\n",buf[0],buf[1],buf[2]); +#endif + + if ((ret = (ftdi_write_data(ftdic, buf, 3))) < 0) + { + perror("ft2232_write error"); + fprintf(stderr, "ft2232_write command %x\n", buf[0]); + return EXIT_FAILURE; + } + + + /* command "set data bits high byte" */ + buf[0] = 0x82; + buf[1] = (val >> 8); + buf[2] = dir >> 8; +#if DEBUG + fprintf(stderr,"write %x %x %x\n",buf[0],buf[1],buf[2]); +#endif + + if ((ret = (ftdi_write_data(ftdic, buf, 3))) < 0) + { + perror("ft2232_write error"); + fprintf(stderr, "ft2232_write command %x\n", buf[0]); + return EXIT_FAILURE; + } + + return 0; + +} diff --git a/redbee-econotag/tools/mc1322x-load.c b/redbee-econotag/tools/mc1322x-load.c new file mode 100644 index 0000000000000000000000000000000000000000..d63df238022b26c8dab3b42b5e61db0f5d64d67c --- /dev/null +++ b/redbee-econotag/tools/mc1322x-load.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2012, Maxim Osipov <maxim.osipov@gmail.com> + * Copyright (c) 2010, Mariano Alvira <mar@devl.org> 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 <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <termios.h> +#include <fcntl.h> +#include <string.h> +#include <stdint.h> + + +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 0000000000000000000000000000000000000000..bfc1d1ffcdcfceb5a855e57de0017f04c42fd832 --- /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; +