From d93d129da6200d9872f9906d2d55832e2f84fd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Fri, 4 Apr 2014 19:33:11 +0200 Subject: [PATCH] cc2538: uart: Make it possible to use several UARTs simultaneously MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids the limitation of having a single UART available at runtime, without duplicating code. Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/dbg.c | 2 +- cpu/cc2538/dev/cc2538-rf.c | 2 +- cpu/cc2538/dev/uart.c | 311 +++++++++++++++++------ cpu/cc2538/dev/uart.h | 49 +--- cpu/cc2538/dev/uart1.h | 2 +- cpu/cc2538/slip-arch.c | 4 +- examples/cc2538dk/sniffer/project-conf.h | 2 +- platform/cc2538dk/README.md | 26 +- platform/cc2538dk/contiki-conf.h | 63 ++++- platform/cc2538dk/contiki-main.c | 5 +- platform/cc2538dk/dev/board.h | 21 +- platform/cc2538dk/startup-gcc.c | 12 +- 12 files changed, 353 insertions(+), 146 deletions(-) diff --git a/cpu/cc2538/dbg.c b/cpu/cc2538/dbg.c index fd136436b..b97936feb 100644 --- a/cpu/cc2538/dbg.c +++ b/cpu/cc2538/dbg.c @@ -51,7 +51,7 @@ #define write_byte(b) usb_serial_writeb(b) #define flush() usb_serial_flush() #else -#define write_byte(b) uart_write_byte(b) +#define write_byte(b) uart_write_byte(DBG_CONF_UART, b) #define flush() #endif /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index a42dd56a4..bca3f66c7 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -106,7 +106,7 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */ #define flush() usb_serial_flush() #else #include "dev/uart.h" -#define write_byte(b) uart_write_byte(b) +#define write_byte(b) uart_write_byte(CC2538_RF_CONF_SNIFFER_UART, b) #define flush() #endif diff --git a/cpu/cc2538/dev/uart.c b/cpu/cc2538/dev/uart.c index 1ab2f81f1..5019da413 100644 --- a/cpu/cc2538/dev/uart.c +++ b/cpu/cc2538/dev/uart.c @@ -48,88 +48,220 @@ #include #include -static int (* input_handler)(unsigned char c); -/*---------------------------------------------------------------------------*/ -#define UART_RX_PORT_BASE GPIO_PORT_TO_BASE(UART_RX_PORT) -#define UART_RX_PIN_MASK GPIO_PIN_MASK(UART_RX_PIN) +#ifndef UART0_RX_PORT +#define UART0_RX_PORT (-1) +#endif +#ifndef UART0_RX_PIN +#define UART0_RX_PIN (-1) +#endif +#if UART0_RX_PORT >= 0 && UART0_RX_PIN < 0 || \ + UART0_RX_PORT < 0 && UART0_RX_PIN >= 0 +#error Both UART0_RX_PORT and UART0_RX_PIN must be valid or invalid +#endif -#define UART_TX_PORT_BASE GPIO_PORT_TO_BASE(UART_TX_PORT) -#define UART_TX_PIN_MASK GPIO_PIN_MASK(UART_TX_PIN) +#ifndef UART0_TX_PORT +#define UART0_TX_PORT (-1) +#endif +#ifndef UART0_TX_PIN +#define UART0_TX_PIN (-1) +#endif +#if UART0_TX_PORT >= 0 && UART0_TX_PIN < 0 || \ + UART0_TX_PORT < 0 && UART0_TX_PIN >= 0 +#error Both UART0_TX_PORT and UART0_TX_PIN must be valid or invalid +#endif -#define UART_CTS_PORT_BASE GPIO_PORT_TO_BASE(UART_CTS_PORT) -#define UART_CTS_PIN_MASK GPIO_PIN_MASK(UART_CTS_PIN) +#if UART0_RX_PORT >= 0 && UART0_TX_PORT < 0 || \ + UART0_RX_PORT < 0 && UART0_TX_PORT >= 0 +#error Both UART0_RX and UART0_TX pads must be valid or invalid +#endif -#define UART_RTS_PORT_BASE GPIO_PORT_TO_BASE(UART_RTS_PORT) -#define UART_RTS_PIN_MASK GPIO_PIN_MASK(UART_RTS_PIN) -/*---------------------------------------------------------------------------*/ -/* - * Once we know what UART we're on, configure correct values to be written to - * the correct registers - */ -#if UART_BASE==UART_1_BASE -/* Running, in sleep, in deep sleep, enable the clock for the correct UART */ -#define SYS_CTRL_RCGCUART_UART SYS_CTRL_RCGCUART_UART1 -#define SYS_CTRL_SCGCUART_UART SYS_CTRL_SCGCUART_UART1 -#define SYS_CTRL_DCGCUART_UART SYS_CTRL_DCGCUART_UART1 +#if UART_IN_USE(0) && UART0_RX_PORT < 0 +#error Contiki is configured to use UART0, but its pads are not valid +#endif -#define NVIC_INT_UART NVIC_INT_UART1 -#define IOC_PXX_SEL_UART_TXD IOC_PXX_SEL_UART1_TXD -#define IOC_UARTRXD_UART IOC_UARTRXD_UART1 -#else /* Defaults for UART0 */ -#define SYS_CTRL_RCGCUART_UART SYS_CTRL_RCGCUART_UART0 -#define SYS_CTRL_SCGCUART_UART SYS_CTRL_SCGCUART_UART0 -#define SYS_CTRL_DCGCUART_UART SYS_CTRL_DCGCUART_UART0 +#ifndef UART1_RX_PORT +#define UART1_RX_PORT (-1) +#endif +#ifndef UART1_RX_PIN +#define UART1_RX_PIN (-1) +#endif +#if UART1_RX_PORT >= 0 && UART1_RX_PIN < 0 || \ + UART1_RX_PORT < 0 && UART1_RX_PIN >= 0 +#error Both UART1_RX_PORT and UART1_RX_PIN must be valid or invalid +#endif -#define NVIC_INT_UART NVIC_INT_UART0 +#ifndef UART1_TX_PORT +#define UART1_TX_PORT (-1) +#endif +#ifndef UART1_TX_PIN +#define UART1_TX_PIN (-1) +#endif +#if UART1_TX_PORT >= 0 && UART1_TX_PIN < 0 || \ + UART1_TX_PORT < 0 && UART1_TX_PIN >= 0 +#error Both UART1_TX_PORT and UART1_TX_PIN must be valid or invalid +#endif -#define IOC_PXX_SEL_UART_TXD IOC_PXX_SEL_UART0_TXD -#define IOC_UARTRXD_UART IOC_UARTRXD_UART0 +#if UART1_RX_PORT >= 0 && UART1_TX_PORT < 0 || \ + UART1_RX_PORT < 0 && UART1_TX_PORT >= 0 +#error Both UART1_RX and UART1_TX pads must be valid or invalid +#endif + +#if UART_IN_USE(1) && UART1_RX_PORT < 0 +#error Contiki is configured to use UART1, but its pads are not valid +#endif + +#ifndef UART1_CTS_PORT +#define UART1_CTS_PORT (-1) +#endif +#ifndef UART1_CTS_PIN +#define UART1_CTS_PIN (-1) +#endif +#if UART1_CTS_PORT >= 0 && UART1_CTS_PIN < 0 || \ + UART1_CTS_PORT < 0 && UART1_CTS_PIN >= 0 +#error Both UART1_CTS_PORT and UART1_CTS_PIN must be valid or invalid +#endif + +#ifndef UART1_RTS_PORT +#define UART1_RTS_PORT (-1) +#endif +#ifndef UART1_RTS_PIN +#define UART1_RTS_PIN (-1) +#endif +#if UART1_RTS_PORT >= 0 && UART1_RTS_PIN < 0 || \ + UART1_RTS_PORT < 0 && UART1_RTS_PIN >= 0 +#error Both UART1_RTS_PORT and UART1_RTS_PIN must be valid or invalid #endif /*---------------------------------------------------------------------------*/ +/* + * Baud rate defines used in uart_init() to set the values of UART_IBRD and + * UART_FBRD in order to achieve the configured baud rates. + */ +#define UART_CLOCK_RATE 16000000 /* 16 MHz */ +#define UART_CTL_HSE_VALUE 0 +#define UART_CTL_VALUE (UART_CTL_RXE | UART_CTL_TXE | (UART_CTL_HSE_VALUE << 5)) + +/* DIV_ROUND() divides integers while avoiding a rounding error: */ +#define DIV_ROUND(num, denom) (((num) + (denom) / 2) / (denom)) + +#define BAUD2BRD(baud) DIV_ROUND(UART_CLOCK_RATE << (UART_CTL_HSE_VALUE + 2), (baud)) +#define BAUD2IBRD(baud) (BAUD2BRD(baud) >> 6) +#define BAUD2FBRD(baud) (BAUD2BRD(baud) & 0x3f) +/*---------------------------------------------------------------------------*/ +typedef struct { + int8_t port; + int8_t pin; +} uart_pad_t; +typedef struct { + uint32_t sys_ctrl_rcgcuart_uart; + uint32_t sys_ctrl_scgcuart_uart; + uint32_t sys_ctrl_dcgcuart_uart; + uint32_t base; + uint32_t ioc_uartrxd_uart; + uint32_t ioc_pxx_sel_uart_txd; + uint32_t ibrd; + uint32_t fbrd; + uart_pad_t rx; + uart_pad_t tx; + uart_pad_t cts; + uart_pad_t rts; + uint8_t nvic_int; +} uart_regs_t; +/*---------------------------------------------------------------------------*/ +static const uart_regs_t uart_regs[UART_INSTANCE_COUNT] = { + { + .sys_ctrl_rcgcuart_uart = SYS_CTRL_RCGCUART_UART0, + .sys_ctrl_scgcuart_uart = SYS_CTRL_SCGCUART_UART0, + .sys_ctrl_dcgcuart_uart = SYS_CTRL_DCGCUART_UART0, + .base = UART_0_BASE, + .ioc_uartrxd_uart = IOC_UARTRXD_UART0, + .ioc_pxx_sel_uart_txd = IOC_PXX_SEL_UART0_TXD, + .ibrd = BAUD2IBRD(UART0_CONF_BAUD_RATE), + .fbrd = BAUD2FBRD(UART0_CONF_BAUD_RATE), + .rx = {UART0_RX_PORT, UART0_RX_PIN}, + .tx = {UART0_TX_PORT, UART0_TX_PIN}, + .cts = {-1, -1}, + .rts = {-1, -1}, + .nvic_int = NVIC_INT_UART0 + }, { + .sys_ctrl_rcgcuart_uart = SYS_CTRL_RCGCUART_UART1, + .sys_ctrl_scgcuart_uart = SYS_CTRL_SCGCUART_UART1, + .sys_ctrl_dcgcuart_uart = SYS_CTRL_DCGCUART_UART1, + .base = UART_1_BASE, + .ioc_uartrxd_uart = IOC_UARTRXD_UART1, + .ioc_pxx_sel_uart_txd = IOC_PXX_SEL_UART1_TXD, + .ibrd = BAUD2IBRD(UART1_CONF_BAUD_RATE), + .fbrd = BAUD2FBRD(UART1_CONF_BAUD_RATE), + .rx = {UART1_RX_PORT, UART1_RX_PIN}, + .tx = {UART1_TX_PORT, UART1_TX_PIN}, + .cts = {UART1_CTS_PORT, UART1_CTS_PIN}, + .rts = {UART1_RTS_PORT, UART1_RTS_PIN}, + .nvic_int = NVIC_INT_UART1 + } +}; +static int (* input_handler[UART_INSTANCE_COUNT])(unsigned char c); +/*---------------------------------------------------------------------------*/ static void -reset(void) +reset(uint32_t uart_base) { uint32_t lchr; /* Make sure the UART is disabled before trying to configure it */ - REG(UART_BASE | UART_CTL) = UART_CTL_VALUE; + REG(uart_base | UART_CTL) = UART_CTL_VALUE; /* Clear error status */ - REG(UART_BASE | UART_ECR) = 0xFF; + REG(uart_base | UART_ECR) = 0xFF; /* Store LCHR configuration */ - lchr = REG(UART_BASE | UART_LCRH); + lchr = REG(uart_base | UART_LCRH); /* Flush FIFOs by clearing LCHR.FEN */ - REG(UART_BASE | UART_LCRH) = 0; + REG(uart_base | UART_LCRH) = 0; /* Restore LCHR configuration */ - REG(UART_BASE | UART_LCRH) = lchr; + REG(uart_base | UART_LCRH) = lchr; /* UART Enable */ - REG(UART_BASE | UART_CTL) |= UART_CTL_UARTEN; + REG(uart_base | UART_CTL) |= UART_CTL_UARTEN; } /*---------------------------------------------------------------------------*/ static bool permit_pm1(void) { - /* Note: UART_FR.TXFE reads 0 if the UART clock is gated. */ - return (REG(SYS_CTRL_RCGCUART) & SYS_CTRL_RCGCUART_UART) == 0 || - (REG(UART_BASE | UART_FR) & UART_FR_TXFE) != 0; + const uart_regs_t *regs; + + for(regs = &uart_regs[0]; regs < &uart_regs[UART_INSTANCE_COUNT]; regs++) { + /* Note: UART_FR.TXFE reads 0 if the UART clock is gated. */ + if((REG(SYS_CTRL_RCGCUART) & regs->sys_ctrl_rcgcuart_uart) != 0 && + (REG(regs->base | UART_FR) & UART_FR_TXFE) == 0) { + return false; + } + } + + return true; } /*---------------------------------------------------------------------------*/ void -uart_init(void) +uart_init(uint8_t uart) { + const uart_regs_t *regs; + + if(uart >= UART_INSTANCE_COUNT) { + return; + } + regs = &uart_regs[uart]; + if(regs->rx.port < 0 || regs->tx.port < 0) { + return; + } + lpm_register_peripheral(permit_pm1); /* Enable clock for the UART while Running, in Sleep and Deep Sleep */ - REG(SYS_CTRL_RCGCUART) |= SYS_CTRL_RCGCUART_UART; - REG(SYS_CTRL_SCGCUART) |= SYS_CTRL_SCGCUART_UART; - REG(SYS_CTRL_DCGCUART) |= SYS_CTRL_DCGCUART_UART; + REG(SYS_CTRL_RCGCUART) |= regs->sys_ctrl_rcgcuart_uart; + REG(SYS_CTRL_SCGCUART) |= regs->sys_ctrl_scgcuart_uart; + REG(SYS_CTRL_DCGCUART) |= regs->sys_ctrl_dcgcuart_uart; /* Run on SYS_DIV */ - REG(UART_BASE | UART_CC) = 0; + REG(regs->base | UART_CC) = 0; /* * Select the UARTx RX pin by writing to the IOC_UARTRXD_UARTn register @@ -139,91 +271,116 @@ uart_init(void) * * (port << 3) + pin */ - REG(IOC_UARTRXD_UART) = (UART_RX_PORT << 3) + UART_RX_PIN; + REG(regs->ioc_uartrxd_uart) = (regs->rx.port << 3) + regs->rx.pin; /* * Pad Control for the TX pin: - * - Set function to UART0 TX + * - Set function to UARTn TX * - Output Enable */ - ioc_set_sel(UART_TX_PORT, UART_TX_PIN, IOC_PXX_SEL_UART_TXD); - ioc_set_over(UART_TX_PORT, UART_TX_PIN, IOC_OVERRIDE_OE); + ioc_set_sel(regs->tx.port, regs->tx.pin, regs->ioc_pxx_sel_uart_txd); + ioc_set_over(regs->tx.port, regs->tx.pin, IOC_OVERRIDE_OE); /* Set RX and TX pins to peripheral mode */ - GPIO_PERIPHERAL_CONTROL(UART_TX_PORT_BASE, UART_TX_PIN_MASK); - GPIO_PERIPHERAL_CONTROL(UART_RX_PORT_BASE, UART_RX_PIN_MASK); + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->tx.port), + GPIO_PIN_MASK(regs->tx.pin)); + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->rx.port), + GPIO_PIN_MASK(regs->rx.pin)); + + if(regs->cts.port >= 0 || regs->rts.port >= 0) { + /* TODO Hardware flow control */ + } /* * UART Interrupt Masks: * Acknowledge RX and RX Timeout * Acknowledge Framing, Overrun and Break Errors */ - REG(UART_BASE | UART_IM) = UART_IM_RXIM | UART_IM_RTIM; - REG(UART_BASE | UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM; + REG(regs->base | UART_IM) = UART_IM_RXIM | UART_IM_RTIM; + REG(regs->base | UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM; - REG(UART_BASE | UART_IFLS) = + REG(regs->base | UART_IFLS) = UART_IFLS_RXIFLSEL_1_8 | UART_IFLS_TXIFLSEL_1_2; /* Make sure the UART is disabled before trying to configure it */ - REG(UART_BASE | UART_CTL) = UART_CTL_VALUE; + REG(regs->base | UART_CTL) = UART_CTL_VALUE; /* Baud Rate Generation */ - uart_set_baudrate(UART_CONF_BAUD_RATE); + REG(regs->base | UART_IBRD) = regs->ibrd; + REG(regs->base | UART_FBRD) = regs->fbrd; /* UART Control: 8N1 with FIFOs */ - REG(UART_BASE | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; + REG(regs->base | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; /* UART Enable */ - REG(UART_BASE | UART_CTL) |= UART_CTL_UARTEN; + REG(regs->base | UART_CTL) |= UART_CTL_UARTEN; /* Enable UART0 Interrupts */ - nvic_interrupt_enable(NVIC_INT_UART); + nvic_interrupt_enable(regs->nvic_int); } /*---------------------------------------------------------------------------*/ void -uart_set_input(int (* input)(unsigned char c)) +uart_set_input(uint8_t uart, int (* input)(unsigned char c)) { - input_handler = input; -} -/*---------------------------------------------------------------------------*/ -void -uart_write_byte(uint8_t b) -{ - /* Block if the TX FIFO is full */ - while(REG(UART_BASE | UART_FR) & UART_FR_TXFF); + if(uart >= UART_INSTANCE_COUNT) { + return; + } - REG(UART_BASE | UART_DR) = b; + input_handler[uart] = input; } /*---------------------------------------------------------------------------*/ void -uart_isr(void) +uart_write_byte(uint8_t uart, uint8_t b) { + uint32_t uart_base; + + if(uart >= UART_INSTANCE_COUNT) { + return; + } + uart_base = uart_regs[uart].base; + + /* Block if the TX FIFO is full */ + while(REG(uart_base | UART_FR) & UART_FR_TXFF); + + REG(uart_base | UART_DR) = b; +} +/*---------------------------------------------------------------------------*/ +void +uart_isr(uint8_t uart) +{ + uint32_t uart_base; uint16_t mis; ENERGEST_ON(ENERGEST_TYPE_IRQ); + uart_base = uart_regs[uart].base; + /* Store the current MIS and clear all flags early, except the RTM flag. * This will clear itself when we read out the entire FIFO contents */ - mis = REG(UART_BASE | UART_MIS) & 0x0000FFFF; + mis = REG(uart_base | UART_MIS) & 0x0000FFFF; - REG(UART_BASE | UART_ICR) = 0x0000FFBF; + REG(uart_base | UART_ICR) = 0x0000FFBF; if(mis & (UART_MIS_RXMIS | UART_MIS_RTMIS)) { - while(!(REG(UART_BASE | UART_FR) & UART_FR_RXFE)) { - if(input_handler != NULL) { - input_handler((unsigned char)(REG(UART_BASE | UART_DR) & 0xFF)); + while(!(REG(uart_base | UART_FR) & UART_FR_RXFE)) { + if(input_handler[uart] != NULL) { + input_handler[uart]((unsigned char)(REG(uart_base | UART_DR) & 0xFF)); } else { /* To prevent an Overrun Error, we need to flush the FIFO even if we * don't have an input_handler. Use mis as a data trash can */ - mis = REG(UART_BASE | UART_DR); + mis = REG(uart_base | UART_DR); } } } else if(mis & (UART_MIS_OEMIS | UART_MIS_BEMIS | UART_MIS_FEMIS)) { /* ISR triggered due to some error condition */ - reset(); + reset(uart_base); } ENERGEST_OFF(ENERGEST_TYPE_IRQ); } +/*---------------------------------------------------------------------------*/ +#define UART_ISR(u) void uart##u##_isr(void) { uart_isr(u); } +UART_ISR(0) +UART_ISR(1) /** @} */ diff --git a/cpu/cc2538/dev/uart.h b/cpu/cc2538/dev/uart.h index fbc18fc18..f28b77438 100644 --- a/cpu/cc2538/dev/uart.h +++ b/cpu/cc2538/dev/uart.h @@ -47,42 +47,17 @@ #include /*---------------------------------------------------------------------------*/ +/** \name UART instance count + * @{ + */ +#define UART_INSTANCE_COUNT 2 +/** @} */ +/*---------------------------------------------------------------------------*/ /** \name UART base addresses * @{ */ #define UART_0_BASE 0x4000C000 #define UART_1_BASE 0x4000D000 - -/* Default to UART 0 unless the configuration tells us otherwise */ -#ifdef UART_CONF_BASE -#define UART_BASE UART_CONF_BASE -#else -#define UART_BASE UART_0_BASE -#endif -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name Baud rate defines - * - * Used in uart_init() to set the values of UART_IBRD and UART_FBRD in order to - * achieve some standard baud rates. - * @{ - */ -#define UART_CLOCK_RATE 16000000 /* 16 MHz */ -#define UART_CTL_HSE_VALUE 0 -#define UART_CTL_VALUE ( UART_CTL_RXE | UART_CTL_TXE | (UART_CTL_HSE_VALUE << 5) ) - -/* DIV_ROUND() divides integers while avoiding a rounding error: */ -#define DIV_ROUND(num, denom) ( ((num) + (denom) / 2) / (denom) ) - -#define BAUD2BRD(baud) DIV_ROUND(UART_CLOCK_RATE << (UART_CTL_HSE_VALUE + 2), (baud)) - -#define uart_set_baudrate(baud) do { \ - REG(UART_BASE | UART_IBRD) = BAUD2BRD(baud) >> 6; \ - REG(UART_BASE | UART_FBRD) = BAUD2BRD(baud) & 0x3f; \ - REG(UART_BASE | UART_LCRH) = REG(UART_BASE | UART_LCRH); \ -} while(0) - /** @} */ /*---------------------------------------------------------------------------*/ /** \name UART Register Offsets @@ -356,18 +331,22 @@ */ /** \brief Initialises the UART controller, configures I/O control - * and interrupts */ -void uart_init(void); + * and interrupts + * \param uart The UART instance to use (0 to \c UART_INSTANCE_COUNT - 1) + */ +void uart_init(uint8_t uart); /** \brief Sends a single character down the UART + * \param uart The UART instance to use (0 to \c UART_INSTANCE_COUNT - 1) * \param b The character to transmit */ -void uart_write_byte(uint8_t b); +void uart_write_byte(uint8_t uart, uint8_t b); /** \brief Assigns a callback to be called when the UART receives a byte + * \param uart The UART instance to use (0 to \c UART_INSTANCE_COUNT - 1) * \param input A pointer to the function */ -void uart_set_input(int (* input)(unsigned char c)); +void uart_set_input(uint8_t uart, int (* input)(unsigned char c)); /** @} */ diff --git a/cpu/cc2538/dev/uart1.h b/cpu/cc2538/dev/uart1.h index e0e03b487..7493ea048 100644 --- a/cpu/cc2538/dev/uart1.h +++ b/cpu/cc2538/dev/uart1.h @@ -44,7 +44,7 @@ #include "dev/uart.h" #define BAUD2UBR(x) x -#define uart1_set_input(f) uart_set_input(f) +#define uart1_set_input(f) uart_set_input(UART1_CONF_UART, f) #endif /* UART1_H_ */ diff --git a/cpu/cc2538/slip-arch.c b/cpu/cc2538/slip-arch.c index f26dad0f3..4205a1826 100644 --- a/cpu/cc2538/slip-arch.c +++ b/cpu/cc2538/slip-arch.c @@ -52,8 +52,8 @@ #define set_input(f) usb_serial_set_input(f) #define flush() usb_serial_flush() #else -#define write_byte(b) uart_write_byte(b) -#define set_input(f) uart_set_input(f) +#define write_byte(b) uart_write_byte(SLIP_ARCH_CONF_UART, b) +#define set_input(f) uart_set_input(SLIP_ARCH_CONF_UART, f) #define flush() #endif diff --git a/examples/cc2538dk/sniffer/project-conf.h b/examples/cc2538dk/sniffer/project-conf.h index a5e9627cb..fd70cd9c9 100644 --- a/examples/cc2538dk/sniffer/project-conf.h +++ b/examples/cc2538dk/sniffer/project-conf.h @@ -42,7 +42,7 @@ #define CC2538_RF_CONF_AUTOACK 0 #define NETSTACK_CONF_RDC stub_rdc_driver -#define UART_CONF_BAUD_RATE 460800 +#define UART0_CONF_BAUD_RATE 460800 #endif /* PROJECT_CONF_H_ */ diff --git a/platform/cc2538dk/README.md b/platform/cc2538dk/README.md index 966d41333..474f08f94 100644 --- a/platform/cc2538dk/README.md +++ b/platform/cc2538dk/README.md @@ -363,11 +363,33 @@ By default, everything is configured to use the UART (stdio, border router's SLI You can multiplex things (for instance, SLIP as well as debugging over USB or SLIP over USB but debugging over UART and other combinations). +Selecting UART0 and/or UART1 +---------------------------- +By default, everything is configured to use the UART0 (stdio, border router's SLIP, sniffer's output stream). If you want to change this, these are the relevant lines in contiki-conf.h (0: UART0, 1: UART1): + + #define SERIAL_LINE_CONF_UART 0 + #define SLIP_ARCH_CONF_UART 0 + #define CC2538_RF_CONF_SNIFFER_UART 0 + #define DBG_CONF_UART 0 + #define UART1_CONF_UART 0 + +A single UART is available on CC2538DK, so all the configuration values above should be the same (i.e. either all 0 or all 1), but 0 and 1 could be mixed for other CC2538-based platforms supporting 2 UARTs. + +The chosen UARTs must have their ports and pins defined in board.h: + + #define UART0_RX_PORT GPIO_A_NUM + #define UART0_RX_PIN 0 + #define UART0_TX_PORT GPIO_A_NUM + #define UART0_TX_PIN 1 + +Only the UART ports and pins implemented on the board can be defined. + UART Baud Rate -------------- -By default, the CC2538 UART is configured with a baud rate of 115200. It is easy to increase this to 230400 by changing the value of `UART_CONF_BAUD_RATE` in `contiki-conf.h` or `project-conf.h`. +By default, the CC2538 UART is configured with a baud rate of 115200. It is easy to increase this to 230400 by changing the value of `UART0_CONF_BAUD_RATE` or `UART1_CONF_BAUD_RATE` in `contiki-conf.h` or `project-conf.h`, according to the UART instance used. - #define UART_CONF_BAUD_RATE 230400 + #define UART0_CONF_BAUD_RATE 230400 + #define UART1_CONF_BAUD_RATE 230400 RF and USB DMA -------------- diff --git a/platform/cc2538dk/contiki-conf.h b/platform/cc2538dk/contiki-conf.h index 964d01074..2d87e222c 100644 --- a/platform/cc2538dk/contiki-conf.h +++ b/platform/cc2538dk/contiki-conf.h @@ -104,20 +104,53 @@ typedef uint32_t rtimer_clock_t; #define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ #endif -#ifndef UART_CONF_BAUD_RATE -#define UART_CONF_BAUD_RATE 115200 /**< Default baud rate */ +#ifndef UART0_CONF_BAUD_RATE +#define UART0_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */ +#endif + +#ifndef UART1_CONF_BAUD_RATE +#define UART1_CONF_BAUD_RATE 115200 /**< Default UART1 baud rate */ #endif #ifndef SLIP_ARCH_CONF_USB #define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */ #endif + #ifndef CC2538_RF_CONF_SNIFFER_USB #define CC2538_RF_CONF_SNIFFER_USB 0 /**< Sniffer out over UART by default */ #endif + #ifndef DBG_CONF_USB #define DBG_CONF_USB 0 /**< All debugging over UART by default */ #endif +#ifndef SERIAL_LINE_CONF_UART +#define SERIAL_LINE_CONF_UART 0 /**< UART to use with serial line */ +#endif + +#if !SLIP_ARCH_CONF_USB +#ifndef SLIP_ARCH_CONF_UART +#define SLIP_ARCH_CONF_UART 0 /**< UART to use with SLIP */ +#endif +#endif + +#if !CC2538_RF_CONF_SNIFFER_USB +#ifndef CC2538_RF_CONF_SNIFFER_UART +#define CC2538_RF_CONF_SNIFFER_UART 0 /**< UART to use with sniffer */ +#endif +#endif + +#if !DBG_CONF_USB +#ifndef DBG_CONF_UART +#define DBG_CONF_UART 0 /**< UART to use for debugging */ +#endif +#endif + +#ifndef UART1_CONF_UART +#define UART1_CONF_UART 0 /**< UART to use for examples relying on + the uart1_* API */ +#endif + /* Turn off example-provided putchars */ #define SLIP_BRIDGE_CONF_NO_PUTCHAR 1 #define SLIP_RADIO_CONF_NO_PUTCHAR 1 @@ -185,8 +218,32 @@ typedef uint32_t rtimer_clock_t; * this */ #if SLIP_ARCH_CONF_ENABLED -#define DBG_CONF_SLIP_MUX (SLIP_ARCH_CONF_USB==DBG_CONF_USB) +#define DBG_CONF_SLIP_MUX (SLIP_ARCH_CONF_USB == DBG_CONF_USB && \ + (SLIP_ARCH_CONF_USB || \ + SLIP_ARCH_CONF_UART == DBG_CONF_UART)) #endif + +/* + * Automatic detection of whether a specific UART is in use + */ +#define UART_IN_USE_BY_SERIAL_LINE(u) (SERIAL_LINE_CONF_UART == (u)) +#define UART_IN_USE_BY_SLIP(u) (SLIP_ARCH_CONF_ENABLED && \ + !SLIP_ARCH_CONF_USB && \ + SLIP_ARCH_CONF_UART == (u)) +#define UART_IN_USE_BY_RF_SNIFFER(u) (CC2538_RF_CONF_SNIFFER && \ + !CC2538_RF_CONF_SNIFFER_USB && \ + CC2538_RF_CONF_SNIFFER_UART == (u)) +#define UART_IN_USE_BY_DBG(u) (!DBG_CONF_USB && DBG_CONF_UART == (u)) +#define UART_IN_USE_BY_UART1(u) (UART1_CONF_UART == (u)) + +#define UART_IN_USE(u) ( \ + UART_CONF_ENABLE && \ + (UART_IN_USE_BY_SERIAL_LINE(u) || \ + UART_IN_USE_BY_SLIP(u) || \ + UART_IN_USE_BY_RF_SNIFFER(u) || \ + UART_IN_USE_BY_DBG(u) || \ + UART_IN_USE_BY_UART1(u)) \ +) /** @} */ /*---------------------------------------------------------------------------*/ /* board.h assumes that basic configuration is done */ diff --git a/platform/cc2538dk/contiki-main.c b/platform/cc2538dk/contiki-main.c index 9409fb460..93d10bc8a 100644 --- a/platform/cc2538dk/contiki-main.c +++ b/platform/cc2538dk/contiki-main.c @@ -153,8 +153,9 @@ main(void) * slip_input_byte instead */ #if UART_CONF_ENABLE - uart_init(); - uart_set_input(serial_line_input_byte); + uart_init(0); + uart_init(1); + uart_set_input(SERIAL_LINE_CONF_UART, serial_line_input_byte); #endif #if USB_SERIAL_CONF_ENABLE diff --git a/platform/cc2538dk/dev/board.h b/platform/cc2538dk/dev/board.h index 015acb164..729d703ab 100644 --- a/platform/cc2538dk/dev/board.h +++ b/platform/cc2538dk/dev/board.h @@ -110,22 +110,21 @@ * - CTS: PB0 (Can only be used with UART1) * - RTS: PD3 (Can only be used with UART1) * - * We configure the port to use UART0. To use UART1, change UART_CONF_BASE + * We configure the port to use UART0. To use UART1, replace UART0_* with + * UART1_* below. * @{ */ -#define UART_CONF_BASE UART_0_BASE +#define UART0_RX_PORT GPIO_A_NUM +#define UART0_RX_PIN 0 -#define UART_RX_PORT GPIO_A_NUM -#define UART_RX_PIN 0 +#define UART0_TX_PORT GPIO_A_NUM +#define UART0_TX_PIN 1 -#define UART_TX_PORT GPIO_A_NUM -#define UART_TX_PIN 1 +#define UART1_CTS_PORT GPIO_B_NUM +#define UART1_CTS_PIN 0 -#define UART_CTS_PORT GPIO_B_NUM -#define UART_CTS_PIN 0 - -#define UART_RTS_PORT GPIO_D_NUM -#define UART_RTS_PIN 3 +#define UART1_RTS_PORT GPIO_D_NUM +#define UART1_RTS_PIN 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name SmartRF Button configuration diff --git a/platform/cc2538dk/startup-gcc.c b/platform/cc2538dk/startup-gcc.c index 860a481d2..b47ae39ed 100644 --- a/platform/cc2538dk/startup-gcc.c +++ b/platform/cc2538dk/startup-gcc.c @@ -81,16 +81,8 @@ void usb_isr(void); /* Likewise for the UART[01] ISRs */ #if UART_CONF_ENABLE -void uart_isr(void); - -#if UART_BASE==UART_1_BASE -#define uart0_isr default_handler -#define uart1_isr uart_isr -#else -#define uart0_isr uart_isr -#define uart1_isr default_handler -#endif - +void uart0_isr(void); +void uart1_isr(void); #else /* UART_CONF_ENABLE */ #define uart0_isr default_handler #define uart1_isr default_handler