diff --git a/redbee-econotag/drivers/gpio.c b/redbee-econotag/drivers/gpio.c new file mode 100644 index 0000000000..c9b867277a --- /dev/null +++ b/redbee-econotag/drivers/gpio.c @@ -0,0 +1,74 @@ +/* + * gpio.c - GPIO driver for redbee + * Copyright (C) 2013 Thomas Eichinger + * + * 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 0000000000..6a727b9da8 --- /dev/null +++ b/redbee-econotag/drivers/include/gpio.h @@ -0,0 +1,157 @@ +/* + * gpio.h - GPIO driver for redbee + * Copyright (C) 2013 Thomas Eichinger + * + * 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 + +/* 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 0000000000..44359b8f60 --- /dev/null +++ b/redbee-econotag/drivers/include/uart.h @@ -0,0 +1,139 @@ +/* + * uart.h - UART driver for redbee + * Copyright (C) 2013 Thomas Eichinger + * + * 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(char 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(char 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 0000000000..52d2cb5f42 --- /dev/null +++ b/redbee-econotag/drivers/redbee_uart.c @@ -0,0 +1,171 @@ +/* + * redbee_uart.c - UART driver for redbee + * Copyright (C) 2013 Thomas Eichinger + * + * 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) */ + +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; + } + } +} + +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); + } + 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); + } + + uart_set_baudrate( uart, baudrate ); +} + +int fw_puts(char *astring,int length) +{ + int i = 0; + for (; i + * 2013 Thomas Eichinger * * This source code is licensed under the GNU General Public License, * Version 3. See the file LICENSE for more details. @@ -9,35 +10,145 @@ */ #include "mc1322x.h" +#include "uart.h" -static volatile unsigned int running = 0; -static volatile unsigned int fifo = 0; +volatile uint8_t u1_tx_buf[UART1_TX_BUFFERSIZE]; +volatile uint32_t u1_tx_head, u1_tx_tail; -static inline int uart0_puts(char *astring, int length) -{ - int i; - for (i=0;iTXCON != 0); - UART1->DATA = astring[i]; +#if UART1_RX_BUFFERSIZE > 32 +volatile uint8_t u1_rx_buf[UART1_RX_BUFFERSIZE]; +volatile uint32_t u1_rx_head, u1_rx_tail; +#endif + +void uart1_isr ( void ) { +#if UART1_RX_BUFFERSIZE > 32 + /* receive interrupt */ + if ( UART1->USTATbits.RXRDY == 1) { + /* copy fifo into SW buffer */ + while (UART1->RXCON != 0) { + uint32_t u1_rx_tail_next; + u1_rx_tail_next = u1_rx_tail + 1; + if ( u1_rx_tail_next >= sizeof(u1_rx_buf) ) { + u1_rx_tail_next = 0; + } + if ( u1_rx_head != u1_rx_tail_next ) { + u1_rx_buf[u1_rx_tail] = UART1->DATA; + u1_rx_tail = u1_rx_tail_next; + } + /* buffer full, flush fifo */ + else { + while ( UART1->RXCON != 0 ) { + UART1->DATA; + } + } + } + return; + } +#endif + while ( UART1->TXCON != 0 ) { + if ( u1_tx_head == u1_tx_tail ) { +#if UART1_RX_BUFFERSIZE > 32 + UART1->CONbits.MTXR = 1; +#else + disable_irq(UART1); +#endif + return; + } + + UART1->DATA = u1_tx_buf[u1_tx_tail++]; + if ( u1_tx_tail >= sizeof(u1_tx_buf) ) { + u1_tx_tail = 0; + } } - return length; } -int fw_puts(char *astring, int length) -{ - return uart0_puts(astring, length); -} - -void stdio_flush(void) -{ - /* disable TX interrupt */ +void uart1_putc ( uint8_t c ) { + /* disable UART1_IRQ since it modifies u1_tx_(head|tail) */ +#if UART1_RX_BUFFERSIZE > 32 UART1->CONbits.MTXR = 1; - while(running) { - while(UART1->TXCON != 0); - fifo=0; - push_queue(); // dequeue to fifo +#else + disable_irq(UART1); +#endif + if ( (u1_tx_head == u1_tx_tail) && (UART1->TXCON != 0) ) { + UART1->DATA = c; } - /* enable TX interrupt */ + else { + u1_tx_buf[u1_tx_head++] = c; + if ( u1_tx_head >= sizeof(u1_tx_buf) ) { + u1_tx_head = 0; + } + if ( u1_tx_head == u1_tx_tail ) { + uint32_t u1_tx_tail_save = u1_tx_tail; + /* back up head to show buffer not empty and enable tx interrupt */ + u1_tx_head--; +#if UART1_RX_BUFFERSIZE > 32 + UART1->CONbits.MTXR = 0; +#else + enable_irq(UART1); +#endif + /* tail will change after one char goes out */ + while ( u1_tx_tail_save == u1_tx_tail ) { + /* wait */ + } + /* restor head */ + u1_tx_head++; + return; + } + } +#if UART1_RX_BUFFERSIZE > 32 UART1->CONbits.MTXR = 0; +#else + enable_irq(UART1); +#endif } + +uint8_t uart1_getc ( void ) { +#if UART1_RX_BUFFERSIZE > 32 + /* pull from ram buffer */ + uint8_t c = 0; + if ( u1_rx_head != u1_rx_tail ) { + c = u1_rx_buf[u1_rx_head++]; + if ( u1_rx_head >= sizeof(u1_rx_buf) ) { + u1_rx_head = 0; + } + return c; + } +#endif + /* pull from hw fifo */ + while ( uart1_can_get() == 0 ) { + /* wait */ + } + return UART1->DATA; +} + +// 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;iTXCON != 0); +// UART1->DATA = astring[i]; +// } +// return length; +// } +// +// int fw_puts(char *astring, int length) +// { +// return uart0_puts(astring, length); +// } +// +// void stdio_flush(void) +// { +// /* disable TX interrupt */ +// UART1->CONbits.MTXR = 1; +// while(running) { +// while(UART1->TXCON != 0); +// fifo=0; +// push_queue(); // dequeue to fifo +// } +// /* enable TX interrupt */ +// UART1->CONbits.MTXR = 0; +// } diff --git a/redbee-econotag/drivers/redbee_uart2.c b/redbee-econotag/drivers/redbee_uart2.c new file mode 100644 index 0000000000..14af686c6c --- /dev/null +++ b/redbee-econotag/drivers/redbee_uart2.c @@ -0,0 +1,121 @@ +/* + * redbee_uart2.c - UART2 driver for redbee + * Copyright (C) 2013 Thomas Eichinger + * + * 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" + +volatile uint8_t u2_tx_buf[UART2_TX_BUFFERSIZE]; +volatile uint32_t u2_tx_head, u2_tx_tail; + +#if UART2_RX_BUFFERSIZE > 32 +volatile uint8_t u2_rx_buf[UART2_RX_BUFFERSIZE]; +volatile uint32_t u2_rx_head, u2_rx_tail; +#endif + +void uart2_isr ( void ) { +#if UART2_RX_BUFFERSIZE > 32 + /* receive interrupt */ + if ( UART2->USTATbits.RXRDY == 1) { + /* copy fifo into SW buffer */ + while (UART2->RXCON != 0) { + uint32_t u2_rx_tail_next; + u2_rx_tail_next = u2_rx_tail + 1; + if ( u2_rx_tail_next >= sizeof(u2_rx_buf) ) { + u2_rx_tail_next = 0; + } + if ( u2_rx_head != u2_rx_tail_next ) { + u2_rx_buf[u2_rx_tail] = UART2->DATA; + u2_rx_tail = u2_rx_tail_next; + } + /* buffer full, flush fifo */ + else { + while ( UART2->RXCON != 0 ) { + UART2->DATA; + } + } + } + return; + } +#endif + while ( UART2->TXCON != 0 ) { + if ( u2_tx_head == u2_tx_tail ) { +#if UART2_RX_BUFFERSIZE > 32 + UART2->CONbits.MTXR = 1; +#else + disable_irq(UART2); +#endif + return; + } + + UART2->DATA = u2_tx_buf[u2_tx_tail++]; + if ( u2_tx_tail >= sizeof(u2_tx_buf) ) { + u2_tx_tail = 0; + } + } +} + +void uart2_putc ( uint8_t c ) { + /* disable UART2_IRQ since it modifies u2_tx_(head|tail) */ +#if UART2_RX_BUFFERSIZE > 32 + UART2->CONbits.MTXR = 1; +#else + disable_irq(UART2); +#endif + if ( (u2_tx_head == u2_tx_tail) && (UART2->TXCON != 0) ) { + UART2->DATA = c; + } + else { + u2_tx_buf[u2_tx_head++] = c; + if ( u2_tx_head >= sizeof(u2_tx_buf) ) { + u2_tx_head = 0; + } + if ( u2_tx_head == u2_tx_tail ) { + uint32_t u2_tx_tail_save = u2_tx_tail; + /* back up head to show buffer not empty and enable tx interrupt */ + u2_tx_head--; +#if UART2_RX_BUFFERSIZE > 32 + UART2->CONbits.MTXR = 0; +#else + enable_irq(UART2); +#endif + /* tail will change after one char goes out */ + while ( u2_tx_tail_save == u2_tx_tail ) { + /* wait */ + } + /* restor head */ + u2_tx_head++; + return; + } + } +#if UART2_RX_BUFFERSIZE > 32 + UART2->CONbits.MTXR = 0; +#else + enable_irq(UART2); +#endif +} + +uint8_t uart2_getc ( void ) { +#if UART2_RX_BUFFERSIZE > 32 + /* pull from ram buffer */ + uint8_t c = 0; + if ( u2_rx_head != u2_rx_tail ) { + c = u2_rx_buf[u2_rx_head++]; + if ( u2_rx_head >= sizeof(u2_rx_buf) ) { + u2_rx_head = 0; + } + return c; + } +#endif + /* pull from hw fifo */ + while ( uart2_can_get() == 0 ) { + /* wait */ + } + return UART2->DATA; +} \ No newline at end of file