aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Caudle <stephen@caudle.info>2015-07-23 23:39:51 -0400
committerStephen Caudle <stephen@caudle.info>2015-08-10 22:44:44 -0400
commite2da880b5fcf9c200123035f675753f5488ffecc (patch)
tree7d52835cd2c2feee6c93ab82412ea6a9821d3087
parentab80aabfd48b50e122f6ff43adeedd1af4a5a607 (diff)
downloadChibiOS-Contrib-e2da880b5fcf9c200123035f675753f5488ffecc.tar.gz
ChibiOS-Contrib-e2da880b5fcf9c200123035f675753f5488ffecc.tar.bz2
ChibiOS-Contrib-e2da880b5fcf9c200123035f675753f5488ffecc.zip
Cleanup nRF51 serial driver
Use values from bitfields header. Also convert notify1 function to be non-blocking, which seems to be how most of the other serial drivers are implemented.
-rw-r--r--demos/NRF51/RT-WVSHARE_BLE400/main.c4
-rw-r--r--os/hal/ports/NRF51/NRF51822/serial_lld.c188
-rw-r--r--os/hal/ports/NRF51/NRF51822/serial_lld.h22
3 files changed, 140 insertions, 74 deletions
diff --git a/demos/NRF51/RT-WVSHARE_BLE400/main.c b/demos/NRF51/RT-WVSHARE_BLE400/main.c
index 4f5e49d..d0b18cc 100644
--- a/demos/NRF51/RT-WVSHARE_BLE400/main.c
+++ b/demos/NRF51/RT-WVSHARE_BLE400/main.c
@@ -39,8 +39,8 @@ int main(void) {
SerialConfig serial_config = {
.speed = 38400,
- .tx_pin = UART_TX,
- .rx_pin = UART_RX,
+ .tx_pad = UART_TX,
+ .rx_pad = UART_RX,
};
/*
diff --git a/os/hal/ports/NRF51/NRF51822/serial_lld.c b/os/hal/ports/NRF51/NRF51822/serial_lld.c
index 1783b92..bc4a9b6 100644
--- a/os/hal/ports/NRF51/NRF51822/serial_lld.c
+++ b/os/hal/ports/NRF51/NRF51822/serial_lld.c
@@ -32,9 +32,6 @@
/* Driver local definitions. */
/*===========================================================================*/
-#define INVALID_BAUDRATE 0xFFFFFFFF
-#define INVALID_PIN 0xFF
-
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
@@ -53,8 +50,8 @@ SerialDriver SD1;
*/
static const SerialConfig default_config = {
.speed = 38400,
- .tx_pin = INVALID_PIN,
- .rx_pin = INVALID_PIN,
+ .tx_pad = NRF51_SERIAL_PAD_DISCONNECTED,
+ .rx_pad = NRF51_SERIAL_PAD_DISCONNECTED,
};
/*===========================================================================*/
@@ -64,27 +61,62 @@ static const SerialConfig default_config = {
/*
* @brief Maps a baudrate speed to a BAUDRATE register value.
*/
-static uint32_t regval_from_baudrate(uint32_t speed)
+
+/**
+ * @brief Common UART configuration.
+ *
+ */
+static void configure_uart(const SerialConfig *config)
{
- switch (speed) {
- case 1200: return 0x0004F000;
- case 2400: return 0x0009D000;
- case 4800: return 0x0013B000;
- case 9600: return 0x00275000;
- case 14400: return 0x003B0000;
- case 19200: return 0x004EA000;
- case 28800: return 0x0075F000;
- case 38400: return 0x009D5000;
- case 57600: return 0x00EBF000;
- case 76800: return 0x013A9000;
- case 115200: return 0x01D7E000;
- case 230400: return 0x03AFB000;
- case 250000: return 0x04000000;
- case 460800: return 0x075F7000;
- case 921600: return 0x0EBEDFA4;
- case 1000000: return 0x10000000;
+ /* TODO: Add support for CTS/RTS! */
+ uint32_t speed = UART_BAUDRATE_BAUDRATE_Baud250000;
+
+ switch (config->speed) {
+ case 1200: speed = UART_BAUDRATE_BAUDRATE_Baud1200; break;
+ case 2400: speed = UART_BAUDRATE_BAUDRATE_Baud2400; break;
+ case 4800: speed = UART_BAUDRATE_BAUDRATE_Baud4800; break;
+ case 9600: speed = UART_BAUDRATE_BAUDRATE_Baud9600; break;
+ case 14400: speed = UART_BAUDRATE_BAUDRATE_Baud14400; break;
+ case 19200: speed = UART_BAUDRATE_BAUDRATE_Baud19200; break;
+ case 28800: speed = UART_BAUDRATE_BAUDRATE_Baud28800; break;
+ case 38400: speed = UART_BAUDRATE_BAUDRATE_Baud38400; break;
+ case 57600: speed = UART_BAUDRATE_BAUDRATE_Baud57600; break;
+ case 76800: speed = UART_BAUDRATE_BAUDRATE_Baud76800; break;
+ case 115200: speed = UART_BAUDRATE_BAUDRATE_Baud115200; break;
+ case 230400: speed = UART_BAUDRATE_BAUDRATE_Baud230400; break;
+ case 250000: speed = UART_BAUDRATE_BAUDRATE_Baud250000; break;
+ case 460800: speed = UART_BAUDRATE_BAUDRATE_Baud460800; break;
+ case 921600: speed = UART_BAUDRATE_BAUDRATE_Baud921600; break;
+ case 1000000: speed = UART_BAUDRATE_BAUDRATE_Baud1M; break;
+ default: osalDbgAssert(0, "invalid baudrate"); break;
+ };
+
+ /* Configure PINs */
+ if (config->tx_pad != NRF51_SERIAL_PAD_DISCONNECTED) {
+ palSetPadMode(IOPORT1, config->tx_pad, PAL_MODE_OUTPUT_PUSHPULL);
+ NRF_UART0->PSELTXD = config->tx_pad;
+ }
+ if (config->rx_pad != NRF51_SERIAL_PAD_DISCONNECTED) {
+ palSetPadMode(IOPORT1, config->rx_pad, PAL_MODE_INPUT);
+ NRF_UART0->PSELRXD = config->rx_pad;
+ }
+
+ NRF_UART0->BAUDRATE = speed;
+ NRF_UART0->CONFIG = (UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos);
+ NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled;
+ NRF_UART0->EVENTS_RXDRDY = 0;
+ NRF_UART0->EVENTS_TXDRDY = 0;
+
+ NRF_UART0->CONFIG &= ~(UART_CONFIG_HWFC_Enabled << UART_CONFIG_HWFC_Pos);
+
+ NRF_UART0->PSELRTS = NRF51_SERIAL_PAD_DISCONNECTED;
+ NRF_UART0->PSELCTS = NRF51_SERIAL_PAD_DISCONNECTED;
+
+ if (config->rx_pad != NRF51_SERIAL_PAD_DISCONNECTED) {
+ while (NRF_UART0->EVENTS_RXDRDY != 0) {
+ (void)NRF_UART0->RXD;
+ }
}
- return INVALID_BAUDRATE;
}
@@ -94,16 +126,25 @@ static uint32_t regval_from_baudrate(uint32_t speed)
#if NRF51_SERIAL_USE_UART0 || defined(__DOXYGEN__)
static void notify1(io_queue_t *qp)
{
+ SerialDriver *sdp = &SD1;
+
(void)qp;
- msg_t b = oqGetI(&SD1.oqueue);
- if (b < Q_OK) {
- chnAddFlagsI(&SD1, CHN_OUTPUT_EMPTY);
+ if (NRF_UART0->PSELTXD == NRF51_SERIAL_PAD_DISCONNECTED)
return;
+
+ if (!sdp->tx_busy) {
+ msg_t b = chOQGetI(&sdp->oqueue);
+
+ if (b < Q_OK) {
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ NRF_UART0->TASKS_STOPTX = 1;
+ return;
+ }
+ sdp->tx_busy = 1;
+ NRF_UART0->TASKS_STARTTX = 1;
+ NRF_UART0->TXD = b;
}
- SD1.thread = chThdGetSelfX();
- NRF_UART0->TXD = b;
- chEvtWaitAny((eventmask_t) 1);
}
#endif
@@ -117,24 +158,49 @@ OSAL_IRQ_HANDLER(Vector48) {
OSAL_IRQ_PROLOGUE();
- if (NRF_UART0->EVENTS_RXDRDY) {
+ SerialDriver *sdp = &SD1;
+ uint32_t isr = NRF_UART0->INTENSET;
+
+ if ((NRF_UART0->EVENTS_RXDRDY != 0) && (isr & UART_INTENSET_RXDRDY_Msk)) {
+ // Clear UART RX event flag
NRF_UART0->EVENTS_RXDRDY = 0;
+
osalSysLockFromISR();
- if (iqIsEmptyI(&SD1.iqueue))
- chnAddFlagsI(&SD1, CHN_INPUT_AVAILABLE);
- if (iqPutI(&SD1.iqueue, NRF_UART0->RXD) < Q_OK)
- chnAddFlagsI(&SD1, SD_OVERRUN_ERROR);
+ if (chIQIsEmptyI(&sdp->iqueue))
+ chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
+ if (chIQPutI(&sdp->iqueue, NRF_UART0->RXD) < Q_OK)
+ chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
osalSysUnlockFromISR();
}
- if (NRF_UART0->EVENTS_TXDRDY) {
+ if ((NRF_UART0->EVENTS_TXDRDY != 0) && (isr & UART_INTENSET_TXDRDY_Msk)) {
+ msg_t b;
+
+ // Clear UART TX event flag.
NRF_UART0->EVENTS_TXDRDY = 0;
+
osalSysLockFromISR();
- chEvtSignalI(SD1.thread, (eventmask_t) 1);
+ b = chOQGetI(&sdp->oqueue);
osalSysUnlockFromISR();
+
+ if (b < Q_OK) {
+ osalSysLockFromISR();
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ osalSysUnlockFromISR();
+ NRF_UART0->TASKS_STOPTX = 1;
+ sdp->tx_busy = 0;
+ } else {
+ sdp->tx_busy = 1;
+ NRF_UART0->TXD = b;
+ }
}
/* TODO: Error handling for EVENTS_ERROR */
+ if ((NRF_UART0->EVENTS_ERROR != 0) && (isr & UART_INTENSET_ERROR_Msk)) {
+ // Clear UART ERROR event flag.
+ NRF_UART0->EVENTS_ERROR = 0;
+ }
+
OSAL_IRQ_EPILOGUE();
}
@@ -168,45 +234,31 @@ void sd_lld_init(void) {
*/
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
- if (config == NULL) {
+ if (config == NULL)
config = &default_config;
- }
+
+ osalDbgAssert(
+ (config->rx_pad < TOTAL_GPIO_PADS) || (config->tx_pad < TOTAL_GPIO_PADS),
+ "must configure at least an RX or TX pad");
if (sdp->state == SD_STOP) {
#if NRF51_SERIAL_USE_UART0 == TRUE
if (sdp == &SD1) {
- uint32_t regval;
-
- /* TODO: Add support for CTS/RTS! */
-
- /* Configure PINs */
- NRF_UART0->PSELRTS = ~0;
- NRF_UART0->PSELCTS = ~0;
- if (config->tx_pin != INVALID_PIN) {
- palSetPadMode(IOPORT1, config->tx_pin, PAL_MODE_OUTPUT_PUSHPULL);
- NRF_UART0->PSELTXD = config->tx_pin;
- }
- if (config->rx_pin != INVALID_PIN) {
- palSetPadMode(IOPORT1, config->rx_pin, PAL_MODE_INPUT);
- NRF_UART0->PSELRXD = config->rx_pin;
- }
+ configure_uart(config);
- regval = regval_from_baudrate(config->speed);
- osalDbgAssert(regval != INVALID_BAUDRATE, "invalid baudrate speed");
- NRF_UART0->BAUDRATE = regval;
+ // Enable UART interrupt
+ NRF_UART0->INTENCLR = (uint32_t)-1;
+ NRF_UART0->INTENSET = UART_INTENSET_ERROR_Msk;
+ if (config->rx_pad != NRF51_SERIAL_PAD_DISCONNECTED)
+ NRF_UART0->INTENSET |= UART_INTENSET_RXDRDY_Msk;
+ if (config->tx_pad != NRF51_SERIAL_PAD_DISCONNECTED)
+ NRF_UART0->INTENSET |= UART_INTENSET_TXDRDY_Msk;
- /* Enable interrupts for RX, TX and ERROR */
- NRF_UART0->INTENSET = 0x284;
+ nvicEnableVector(UART0_IRQn, NRF51_SERIAL_UART0_PRIORITY);
- NRF_UART0->EVENTS_RXDRDY = 0;
- NRF_UART0->EVENTS_TXDRDY = 0;
-
- nvicEnableVector(UART0_IRQn, 12);
-
- NRF_UART0->ENABLE = 4;
- NRF_UART0->TASKS_STARTRX = 1;
- NRF_UART0->TASKS_STARTTX = 1;
+ if (config->rx_pad != NRF51_SERIAL_PAD_DISCONNECTED)
+ NRF_UART0->TASKS_STARTRX = 1;
}
#endif
@@ -229,9 +281,9 @@ void sd_lld_stop(SerialDriver *sdp) {
#if NRF51_SERIAL_USE_UART0 == TRUE
if (&SD1 == sdp) {
nvicDisableVector(UART0_IRQn);
+ NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Disabled;
}
#endif
-
}
}
diff --git a/os/hal/ports/NRF51/NRF51822/serial_lld.h b/os/hal/ports/NRF51/NRF51822/serial_lld.h
index 62f1302..8da3998 100644
--- a/os/hal/ports/NRF51/NRF51822/serial_lld.h
+++ b/os/hal/ports/NRF51/NRF51822/serial_lld.h
@@ -40,13 +40,25 @@
* @{
*/
/**
- * @brief USART1 driver enable switch.
- * @details If set to @p TRUE the support for USART1 is included.
+ * @brief SD1 driver enable switch.
+ * @details If set to @p TRUE the support for SD1 is included.
* @note The default is @p FALSE.
*/
#if !defined(NRF51_SERIAL_USE_UART0) || defined(__DOXYGEN__)
#define NRF51_SERIAL_USE_UART0 FALSE
#endif
+
+/**
+ * @brief UART0 interrupt priority level setting.
+ */
+#if !defined(NRF51_SERIAL_UART0_PRIORITY) || defined(__DOXYGEN__)
+#define NRF51_SERIAL_UART0_PRIORITY 12
+#endif
+
+/* Value indicating that no pad is connected to this UART register. */
+#define NRF51_SERIAL_PAD_DISCONNECTED 0xFFFFFFFFU
+#define NRF51_SERIAL_INVALID_BAUDRATE 0xFFFFFFFFU
+
/** @} */
/*===========================================================================*/
@@ -71,8 +83,8 @@ typedef struct {
*/
uint32_t speed;
/* End of the mandatory fields.*/
- uint8_t tx_pin;
- uint8_t rx_pin;
+ uint32_t tx_pad;
+ uint32_t rx_pad;
} SerialConfig;
/**
@@ -90,6 +102,8 @@ typedef struct {
uint8_t ib[SERIAL_BUFFERS_SIZE]; \
/* Output circular buffer.*/ \
uint8_t ob[SERIAL_BUFFERS_SIZE]; \
+ /* 1 if port is busy transmitting, 0 otherwise. */ \
+ uint8_t tx_busy; \
/* End of the mandatory fields.*/ \
thread_t *thread;