cc2538: uart: Make it possible to use several UARTs simultaneously

This avoids the limitation of having a single UART available at runtime, without
duplicating code.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
This commit is contained in:
Benoît Thébaudeau 2014-04-04 19:33:11 +02:00
parent db754a57d7
commit d93d129da6
12 changed files with 353 additions and 146 deletions

View file

@ -51,7 +51,7 @@
#define write_byte(b) usb_serial_writeb(b) #define write_byte(b) usb_serial_writeb(b)
#define flush() usb_serial_flush() #define flush() usb_serial_flush()
#else #else
#define write_byte(b) uart_write_byte(b) #define write_byte(b) uart_write_byte(DBG_CONF_UART, b)
#define flush() #define flush()
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -106,7 +106,7 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */
#define flush() usb_serial_flush() #define flush() usb_serial_flush()
#else #else
#include "dev/uart.h" #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() #define flush()
#endif #endif

View file

@ -48,88 +48,220 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
static int (* input_handler)(unsigned char c); #ifndef UART0_RX_PORT
/*---------------------------------------------------------------------------*/ #define UART0_RX_PORT (-1)
#define UART_RX_PORT_BASE GPIO_PORT_TO_BASE(UART_RX_PORT) #endif
#define UART_RX_PIN_MASK GPIO_PIN_MASK(UART_RX_PIN) #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) #ifndef UART0_TX_PORT
#define UART_TX_PIN_MASK GPIO_PIN_MASK(UART_TX_PIN) #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) #if UART0_RX_PORT >= 0 && UART0_TX_PORT < 0 || \
#define UART_CTS_PIN_MASK GPIO_PIN_MASK(UART_CTS_PIN) 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) #if UART_IN_USE(0) && UART0_RX_PORT < 0
#define UART_RTS_PIN_MASK GPIO_PIN_MASK(UART_RTS_PIN) #error Contiki is configured to use UART0, but its pads are not valid
/*---------------------------------------------------------------------------*/ #endif
/*
* 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
#define NVIC_INT_UART NVIC_INT_UART1 #ifndef UART1_RX_PORT
#define IOC_PXX_SEL_UART_TXD IOC_PXX_SEL_UART1_TXD #define UART1_RX_PORT (-1)
#define IOC_UARTRXD_UART IOC_UARTRXD_UART1 #endif
#else /* Defaults for UART0 */ #ifndef UART1_RX_PIN
#define SYS_CTRL_RCGCUART_UART SYS_CTRL_RCGCUART_UART0 #define UART1_RX_PIN (-1)
#define SYS_CTRL_SCGCUART_UART SYS_CTRL_SCGCUART_UART0 #endif
#define SYS_CTRL_DCGCUART_UART SYS_CTRL_DCGCUART_UART0 #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 #if UART1_RX_PORT >= 0 && UART1_TX_PORT < 0 || \
#define IOC_UARTRXD_UART IOC_UARTRXD_UART0 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 #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 static void
reset(void) reset(uint32_t uart_base)
{ {
uint32_t lchr; uint32_t lchr;
/* Make sure the UART is disabled before trying to configure it */ /* 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 */ /* Clear error status */
REG(UART_BASE | UART_ECR) = 0xFF; REG(uart_base | UART_ECR) = 0xFF;
/* Store LCHR configuration */ /* Store LCHR configuration */
lchr = REG(UART_BASE | UART_LCRH); lchr = REG(uart_base | UART_LCRH);
/* Flush FIFOs by clearing LCHR.FEN */ /* Flush FIFOs by clearing LCHR.FEN */
REG(UART_BASE | UART_LCRH) = 0; REG(uart_base | UART_LCRH) = 0;
/* Restore LCHR configuration */ /* Restore LCHR configuration */
REG(UART_BASE | UART_LCRH) = lchr; REG(uart_base | UART_LCRH) = lchr;
/* UART Enable */ /* UART Enable */
REG(UART_BASE | UART_CTL) |= UART_CTL_UARTEN; REG(uart_base | UART_CTL) |= UART_CTL_UARTEN;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static bool static bool
permit_pm1(void) permit_pm1(void)
{ {
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. */ /* Note: UART_FR.TXFE reads 0 if the UART clock is gated. */
return (REG(SYS_CTRL_RCGCUART) & SYS_CTRL_RCGCUART_UART) == 0 || if((REG(SYS_CTRL_RCGCUART) & regs->sys_ctrl_rcgcuart_uart) != 0 &&
(REG(UART_BASE | UART_FR) & UART_FR_TXFE) != 0; (REG(regs->base | UART_FR) & UART_FR_TXFE) == 0) {
return false;
}
}
return true;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void 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); lpm_register_peripheral(permit_pm1);
/* Enable clock for the UART while Running, in Sleep and Deep Sleep */ /* Enable clock for the UART while Running, in Sleep and Deep Sleep */
REG(SYS_CTRL_RCGCUART) |= SYS_CTRL_RCGCUART_UART; REG(SYS_CTRL_RCGCUART) |= regs->sys_ctrl_rcgcuart_uart;
REG(SYS_CTRL_SCGCUART) |= SYS_CTRL_SCGCUART_UART; REG(SYS_CTRL_SCGCUART) |= regs->sys_ctrl_scgcuart_uart;
REG(SYS_CTRL_DCGCUART) |= SYS_CTRL_DCGCUART_UART; REG(SYS_CTRL_DCGCUART) |= regs->sys_ctrl_dcgcuart_uart;
/* Run on SYS_DIV */ /* 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 * Select the UARTx RX pin by writing to the IOC_UARTRXD_UARTn register
@ -139,91 +271,116 @@ uart_init(void)
* *
* (port << 3) + pin * (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: * Pad Control for the TX pin:
* - Set function to UART0 TX * - Set function to UARTn TX
* - Output Enable * - Output Enable
*/ */
ioc_set_sel(UART_TX_PORT, UART_TX_PIN, IOC_PXX_SEL_UART_TXD); ioc_set_sel(regs->tx.port, regs->tx.pin, regs->ioc_pxx_sel_uart_txd);
ioc_set_over(UART_TX_PORT, UART_TX_PIN, IOC_OVERRIDE_OE); ioc_set_over(regs->tx.port, regs->tx.pin, IOC_OVERRIDE_OE);
/* Set RX and TX pins to peripheral mode */ /* Set RX and TX pins to peripheral mode */
GPIO_PERIPHERAL_CONTROL(UART_TX_PORT_BASE, UART_TX_PIN_MASK); GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->tx.port),
GPIO_PERIPHERAL_CONTROL(UART_RX_PORT_BASE, UART_RX_PIN_MASK); 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: * UART Interrupt Masks:
* Acknowledge RX and RX Timeout * Acknowledge RX and RX Timeout
* Acknowledge Framing, Overrun and Break Errors * Acknowledge Framing, Overrun and Break Errors
*/ */
REG(UART_BASE | UART_IM) = UART_IM_RXIM | UART_IM_RTIM; REG(regs->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_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; UART_IFLS_RXIFLSEL_1_8 | UART_IFLS_TXIFLSEL_1_2;
/* Make sure the UART is disabled before trying to configure it */ /* 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 */ /* 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 */ /* 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 */ /* UART Enable */
REG(UART_BASE | UART_CTL) |= UART_CTL_UARTEN; REG(regs->base | UART_CTL) |= UART_CTL_UARTEN;
/* Enable UART0 Interrupts */ /* Enable UART0 Interrupts */
nvic_interrupt_enable(NVIC_INT_UART); nvic_interrupt_enable(regs->nvic_int);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uart_set_input(int (* input)(unsigned char c)) uart_set_input(uint8_t uart, int (* input)(unsigned char c))
{ {
input_handler = input; if(uart >= UART_INSTANCE_COUNT) {
return;
} }
/*---------------------------------------------------------------------------*/
void
uart_write_byte(uint8_t b)
{
/* Block if the TX FIFO is full */
while(REG(UART_BASE | UART_FR) & UART_FR_TXFF);
REG(UART_BASE | UART_DR) = b; input_handler[uart] = input;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void 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; uint16_t mis;
ENERGEST_ON(ENERGEST_TYPE_IRQ); ENERGEST_ON(ENERGEST_TYPE_IRQ);
uart_base = uart_regs[uart].base;
/* Store the current MIS and clear all flags early, except the RTM flag. /* 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 */ * 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)) { if(mis & (UART_MIS_RXMIS | UART_MIS_RTMIS)) {
while(!(REG(UART_BASE | UART_FR) & UART_FR_RXFE)) { while(!(REG(uart_base | UART_FR) & UART_FR_RXFE)) {
if(input_handler != NULL) { if(input_handler[uart] != NULL) {
input_handler((unsigned char)(REG(UART_BASE | UART_DR) & 0xFF)); input_handler[uart]((unsigned char)(REG(uart_base | UART_DR) & 0xFF));
} else { } else {
/* To prevent an Overrun Error, we need to flush the FIFO even if we /* 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 */ * 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)) { } else if(mis & (UART_MIS_OEMIS | UART_MIS_BEMIS | UART_MIS_FEMIS)) {
/* ISR triggered due to some error condition */ /* ISR triggered due to some error condition */
reset(); reset(uart_base);
} }
ENERGEST_OFF(ENERGEST_TYPE_IRQ); ENERGEST_OFF(ENERGEST_TYPE_IRQ);
} }
/*---------------------------------------------------------------------------*/
#define UART_ISR(u) void uart##u##_isr(void) { uart_isr(u); }
UART_ISR(0)
UART_ISR(1)
/** @} */ /** @} */

View file

@ -47,42 +47,17 @@
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name UART instance count
* @{
*/
#define UART_INSTANCE_COUNT 2
/** @} */
/*---------------------------------------------------------------------------*/
/** \name UART base addresses /** \name UART base addresses
* @{ * @{
*/ */
#define UART_0_BASE 0x4000C000 #define UART_0_BASE 0x4000C000
#define UART_1_BASE 0x4000D000 #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 /** \name UART Register Offsets
@ -356,18 +331,22 @@
*/ */
/** \brief Initialises the UART controller, configures I/O control /** \brief Initialises the UART controller, configures I/O control
* and interrupts */ * and interrupts
void uart_init(void); * \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 /** \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 * \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 /** \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 * \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));
/** @} */ /** @} */

View file

@ -44,7 +44,7 @@
#include "dev/uart.h" #include "dev/uart.h"
#define BAUD2UBR(x) x #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_ */ #endif /* UART1_H_ */

View file

@ -52,8 +52,8 @@
#define set_input(f) usb_serial_set_input(f) #define set_input(f) usb_serial_set_input(f)
#define flush() usb_serial_flush() #define flush() usb_serial_flush()
#else #else
#define write_byte(b) uart_write_byte(b) #define write_byte(b) uart_write_byte(SLIP_ARCH_CONF_UART, b)
#define set_input(f) uart_set_input(f) #define set_input(f) uart_set_input(SLIP_ARCH_CONF_UART, f)
#define flush() #define flush()
#endif #endif

View file

@ -42,7 +42,7 @@
#define CC2538_RF_CONF_AUTOACK 0 #define CC2538_RF_CONF_AUTOACK 0
#define NETSTACK_CONF_RDC stub_rdc_driver #define NETSTACK_CONF_RDC stub_rdc_driver
#define UART_CONF_BAUD_RATE 460800 #define UART0_CONF_BAUD_RATE 460800
#endif /* PROJECT_CONF_H_ */ #endif /* PROJECT_CONF_H_ */

View file

@ -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). 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 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 RF and USB DMA
-------------- --------------

View file

@ -104,20 +104,53 @@ typedef uint32_t rtimer_clock_t;
#define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ #define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */
#endif #endif
#ifndef UART_CONF_BAUD_RATE #ifndef UART0_CONF_BAUD_RATE
#define UART_CONF_BAUD_RATE 115200 /**< Default 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 #endif
#ifndef SLIP_ARCH_CONF_USB #ifndef SLIP_ARCH_CONF_USB
#define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */ #define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */
#endif #endif
#ifndef CC2538_RF_CONF_SNIFFER_USB #ifndef CC2538_RF_CONF_SNIFFER_USB
#define CC2538_RF_CONF_SNIFFER_USB 0 /**< Sniffer out over UART by default */ #define CC2538_RF_CONF_SNIFFER_USB 0 /**< Sniffer out over UART by default */
#endif #endif
#ifndef DBG_CONF_USB #ifndef DBG_CONF_USB
#define DBG_CONF_USB 0 /**< All debugging over UART by default */ #define DBG_CONF_USB 0 /**< All debugging over UART by default */
#endif #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 */ /* Turn off example-provided putchars */
#define SLIP_BRIDGE_CONF_NO_PUTCHAR 1 #define SLIP_BRIDGE_CONF_NO_PUTCHAR 1
#define SLIP_RADIO_CONF_NO_PUTCHAR 1 #define SLIP_RADIO_CONF_NO_PUTCHAR 1
@ -185,8 +218,32 @@ typedef uint32_t rtimer_clock_t;
* this * this
*/ */
#if SLIP_ARCH_CONF_ENABLED #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 #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 */ /* board.h assumes that basic configuration is done */

View file

@ -153,8 +153,9 @@ main(void)
* slip_input_byte instead * slip_input_byte instead
*/ */
#if UART_CONF_ENABLE #if UART_CONF_ENABLE
uart_init(); uart_init(0);
uart_set_input(serial_line_input_byte); uart_init(1);
uart_set_input(SERIAL_LINE_CONF_UART, serial_line_input_byte);
#endif #endif
#if USB_SERIAL_CONF_ENABLE #if USB_SERIAL_CONF_ENABLE

View file

@ -110,22 +110,21 @@
* - CTS: PB0 (Can only be used with UART1) * - CTS: PB0 (Can only be used with UART1)
* - RTS: PD3 (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 UART0_TX_PORT GPIO_A_NUM
#define UART_RX_PIN 0 #define UART0_TX_PIN 1
#define UART_TX_PORT GPIO_A_NUM #define UART1_CTS_PORT GPIO_B_NUM
#define UART_TX_PIN 1 #define UART1_CTS_PIN 0
#define UART_CTS_PORT GPIO_B_NUM #define UART1_RTS_PORT GPIO_D_NUM
#define UART_CTS_PIN 0 #define UART1_RTS_PIN 3
#define UART_RTS_PORT GPIO_D_NUM
#define UART_RTS_PIN 3
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name SmartRF Button configuration /** \name SmartRF Button configuration

View file

@ -81,16 +81,8 @@ void usb_isr(void);
/* Likewise for the UART[01] ISRs */ /* Likewise for the UART[01] ISRs */
#if UART_CONF_ENABLE #if UART_CONF_ENABLE
void uart_isr(void); void uart0_isr(void);
void uart1_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
#else /* UART_CONF_ENABLE */ #else /* UART_CONF_ENABLE */
#define uart0_isr default_handler #define uart0_isr default_handler
#define uart1_isr default_handler #define uart1_isr default_handler