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:
parent
db754a57d7
commit
d93d129da6
|
@ -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
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
--------------
|
--------------
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue