Make the CC2538 UART driver more configurable

* We can now very easily switch between UART0 and UART1 through a define
* We can also configure the UART RX and TX port/pin through defines
This commit is contained in:
George Oikonomou 2013-05-15 12:59:49 +01:00 committed by George Oikonomou
parent 1f76b7d0f9
commit 6c6013b898
4 changed files with 91 additions and 37 deletions

View file

@ -48,49 +48,82 @@
static int (* input_handler)(unsigned char c); static int (* input_handler)(unsigned char c);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*
* 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
#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
#define NVIC_INT_UART NVIC_INT_UART0
#define IOC_PXX_SEL_UART_TXD IOC_PXX_SEL_UART0_TXD
#define IOC_UARTRXD_UART IOC_UARTRXD_UART0
#endif
/*---------------------------------------------------------------------------*/
static void static void
reset(void) reset(void)
{ {
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_0_BASE | UART_CTL) = UART_CTL_TXE | UART_CTL_RXE; REG(UART_BASE | UART_CTL) = UART_CTL_TXE | UART_CTL_RXE;
/* Clear error status */ /* Clear error status */
REG(UART_0_BASE | UART_ECR) = 0xFF; REG(UART_BASE | UART_ECR) = 0xFF;
/* Store LCHR configuration */ /* Store LCHR configuration */
lchr = REG(UART_0_BASE | UART_LCRH); lchr = REG(UART_BASE | UART_LCRH);
/* Flush FIFOs by clearing LCHR.FEN */ /* Flush FIFOs by clearing LCHR.FEN */
REG(UART_0_BASE | UART_LCRH) = 0; REG(UART_BASE | UART_LCRH) = 0;
/* Restore LCHR configuration */ /* Restore LCHR configuration */
REG(UART_0_BASE | UART_LCRH) = lchr; REG(UART_BASE | UART_LCRH) = lchr;
/* UART Enable */ /* UART Enable */
REG(UART_0_BASE | UART_CTL) |= UART_CTL_UARTEN; REG(UART_BASE | UART_CTL) |= UART_CTL_UARTEN;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uart_init(void) uart_init(void)
{ {
/* 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_UART0; REG(SYS_CTRL_RCGCUART) |= SYS_CTRL_RCGCUART_UART;
REG(SYS_CTRL_SCGCUART) |= SYS_CTRL_DCGCUART_UART0; REG(SYS_CTRL_SCGCUART) |= SYS_CTRL_SCGCUART_UART;
REG(SYS_CTRL_DCGCUART) |= SYS_CTRL_DCGCUART_UART0; REG(SYS_CTRL_DCGCUART) |= SYS_CTRL_DCGCUART_UART;
/* Run on SYS_DIV */ /* Run on SYS_DIV */
REG(UART_0_BASE | UART_CC) = 0; REG(UART_BASE | UART_CC) = 0;
/* PA1: UART TX */ /*
REG(IOC_PA1_SEL) = IOC_PXX_SEL_UART0_TXD; * Select the UARTx RX pin by writing to the IOC_UARTRXD_UARTn register
*
* The value to be written will be on of the IOC_INPUT_SEL_Pxn defines from
* ioc.h. The value can also be calculated as:
*
* (port << 3) + pin
*/
REG(IOC_UARTRXD_UART) = (UART_RX_PORT << 3) + UART_RX_PIN;
/* PA0: UART RX */ /*
REG(IOC_UARTRXD_UART0) = IOC_INPUT_SEL_PA0; * Pad Control for the TX pin:
* - Set function to UART0 TX
/* Pad Control: PA1 Output Enable */ * - Output Enable
REG(IOC_PA1_OVER) = IOC_OVERRIDE_OE; */
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);
/* Set PA[1:0] to peripheral mode */ /* Set PA[1:0] to peripheral mode */
REG(GPIO_A_BASE | GPIO_AFSEL) |= (0x00000002 | 0x00000001); REG(GPIO_A_BASE | GPIO_AFSEL) |= (0x00000002 | 0x00000001);
@ -100,27 +133,27 @@ uart_init(void)
* Acknowledge RX and RX Timeout * Acknowledge RX and RX Timeout
* Acknowledge Framing, Overrun and Break Errors * Acknowledge Framing, Overrun and Break Errors
*/ */
REG(UART_0_BASE | UART_IM) = UART_IM_RXIM | UART_IM_RTIM; REG(UART_BASE | UART_IM) = UART_IM_RXIM | UART_IM_RTIM;
REG(UART_0_BASE | UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM; REG(UART_BASE | UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM;
REG(UART_0_BASE | UART_IFLS) = REG(UART_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_0_BASE | UART_CTL) = UART_CTL_TXE | UART_CTL_RXE; REG(UART_BASE | UART_CTL) = UART_CTL_TXE | UART_CTL_RXE;
/* Baud Rate Generation */ /* Baud Rate Generation */
REG(UART_0_BASE | UART_IBRD) = UART_CONF_IBRD; REG(UART_BASE | UART_IBRD) = UART_CONF_IBRD;
REG(UART_0_BASE | UART_FBRD) = UART_CONF_FBRD; REG(UART_BASE | UART_FBRD) = UART_CONF_FBRD;
/* UART Control: 8N1 with FIFOs */ /* UART Control: 8N1 with FIFOs */
REG(UART_0_BASE | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; REG(UART_BASE | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN;
/* UART Enable */ /* UART Enable */
REG(UART_0_BASE | UART_CTL) |= UART_CTL_UARTEN; REG(UART_BASE | UART_CTL) |= UART_CTL_UARTEN;
/* Enable UART0 Interrupts */ /* Enable UART0 Interrupts */
nvic_interrupt_enable(NVIC_INT_UART0); nvic_interrupt_enable(NVIC_INT_UART);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -133,9 +166,9 @@ void
uart_write_byte(uint8_t b) uart_write_byte(uint8_t b)
{ {
/* Block if the TX FIFO is full */ /* Block if the TX FIFO is full */
while(REG(UART_0_BASE | UART_FR) & UART_FR_TXFF); while(REG(UART_BASE | UART_FR) & UART_FR_TXFF);
REG(UART_0_BASE | UART_DR) = b; REG(UART_BASE | UART_DR) = b;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -147,18 +180,18 @@ uart_isr(void)
/* 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_0_BASE | UART_MIS) & 0x0000FFFF; mis = REG(UART_BASE | UART_MIS) & 0x0000FFFF;
REG(UART_0_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_0_BASE | UART_FR) & UART_FR_RXFE)) { while(!(REG(UART_BASE | UART_FR) & UART_FR_RXFE)) {
if(input_handler != NULL) { if(input_handler != NULL) {
input_handler((unsigned char)(REG(UART_0_BASE | UART_DR) & 0xFF)); input_handler((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_0_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)) {

View file

@ -52,6 +52,13 @@
*/ */
#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
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**

View file

@ -111,8 +111,11 @@
* - 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
* @{ * @{
*/ */
#define UART_CONF_BASE UART_0_BASE
#define UART_RX_PORT GPIO_A_NUM #define UART_RX_PORT GPIO_A_NUM
#define UART_RX_PIN 0 #define UART_RX_PIN 0

View file

@ -38,6 +38,7 @@
*/ */
#include "contiki.h" #include "contiki.h"
#include "reg.h" #include "reg.h"
#include "uart.h"
#include <stdint.h> #include <stdint.h>
@ -71,12 +72,22 @@ void usb_isr(void);
#define usb_isr default_handler #define usb_isr default_handler
#endif #endif
/* Likewise for the UART ISR */ /* Likewise for the UART[01] ISRs */
#if UART_CONF_ENABLE #if UART_CONF_ENABLE
void uart_isr(void); void uart_isr(void);
#if UART_BASE==UART_1_BASE
#define uart0_isr default_handler
#define uart1_isr uart_isr
#else #else
#define uart_isr default_handler #define uart0_isr uart_isr
#define uart1_isr default_handler
#endif #endif
#else /* UART_CONF_ENABLE */
#define uart0_isr default_handler
#define uart1_isr default_handler
#endif /* UART_CONF_ENABLE */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Allocate stack space */ /* Allocate stack space */
static unsigned long stack[512]; static unsigned long stack[512];
@ -123,8 +134,8 @@ void(*const vectors[])(void) =
gpio_port_c_isr, /* 18 GPIO Port C */ gpio_port_c_isr, /* 18 GPIO Port C */
gpio_port_d_isr, /* 19 GPIO Port D */ gpio_port_d_isr, /* 19 GPIO Port D */
0, /* 20 none */ 0, /* 20 none */
uart_isr, /* 21 UART0 Rx and Tx */ uart0_isr, /* 21 UART0 Rx and Tx */
default_handler, /* 22 UART1 Rx and Tx */ uart1_isr, /* 22 UART1 Rx and Tx */
default_handler, /* 23 SSI0 Rx and Tx */ default_handler, /* 23 SSI0 Rx and Tx */
default_handler, /* 24 I2C Master and Slave */ default_handler, /* 24 I2C Master and Slave */
0, /* 25 Reserved */ 0, /* 25 Reserved */