From cb8c2b759e107f67bf9bc4fbe685e393fdc826ee Mon Sep 17 00:00:00 2001 From: Alexandre Abadie <alexandre.abadie@inria.fr> Date: Mon, 17 Dec 2018 10:08:58 +0100 Subject: [PATCH] cpu/nrf52: use UARTE device type for nrf52840 This requires to implement the use of EasyDMA for this kind of peripheral --- cpu/nrf52/include/periph_cpu.h | 8 +-- cpu/nrf5x_common/periph/uart.c | 110 ++++++++++++++++++++++++--------- 2 files changed, 84 insertions(+), 34 deletions(-) diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h index b8a62e70e6..27843d075e 100644 --- a/cpu/nrf52/include/periph_cpu.h +++ b/cpu/nrf52/include/periph_cpu.h @@ -43,9 +43,9 @@ extern "C" { #define SPI_MOSISEL (dev(bus)->PSEL.MOSI) #define SPI_MISOSEL (dev(bus)->PSEL.MISO) #ifndef CPU_MODEL_NRF52840XXAA -#define UART_PIN_RTS GPIO_UNDEF -#define UART_PIN_CTS GPIO_UNDEF -#define UART_HWFLOWCTRL 0 +#define UART_PIN_RTS (GPIO_UNDEF) +#define UART_PIN_CTS (GPIO_UNDEF) +#define UART_HWFLOWCTRL (0) #define UART_IRQN (UARTE0_UART0_IRQn) #endif /** @} */ @@ -165,7 +165,7 @@ typedef struct { * @brief Structure for UART configuration data */ typedef struct { - NRF_UART_Type *dev; /**< UART device base register address */ + NRF_UARTE_Type *dev; /**< UART with EasyDMA device base register address */ uint8_t rx_pin; /**< RX pin */ uint8_t tx_pin; /**< TX pin */ uint8_t rts_pin; /**< RTS pin - set to GPIO_UNDEF when not using HW flow control */ diff --git a/cpu/nrf5x_common/periph/uart.c b/cpu/nrf5x_common/periph/uart.c index 09e729ad18..12ade1daaa 100644 --- a/cpu/nrf5x_common/periph/uart.c +++ b/cpu/nrf5x_common/periph/uart.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2014-2017 Freie Universität Berlin * 2015 Jan Wagner <mail@jwagner.eu> + * 2018 Inria * * * This file is subject to the terms and conditions of the GNU Lesser @@ -20,6 +21,7 @@ * @author Timo Ziegler <timo.ziegler@fu-berlin.de> * @author Hauke Petersen <hauke.petersen@fu-berlin.de> * @author Jan Wagner <mail@jwagner.eu> + * @author Alexandre Abadie <alexandre.abadie@inria.fr> * * @} */ @@ -31,56 +33,65 @@ #include "periph/gpio.h" #ifdef CPU_MODEL_NRF52840XXAA -#define PSEL_RXD dev(uart)->PSEL.RXD -#define PSEL_TXD dev(uart)->PSEL.TXD -#define PSEL_RTS dev(uart)->PSEL.RTS -#define PSEL_CTS dev(uart)->PSEL.CTS -#define UART_IRQN uart_config[uart].irqn -#define UART_PIN_RX uart_config[uart].rx_pin -#define UART_PIN_TX uart_config[uart].tx_pin -#define UART_PIN_RTS uart_config[uart].rts_pin -#define UART_PIN_CTS uart_config[uart].cts_pin -#define UART_HWFLOWCTRL (uart_config[uart].rts_pin != GPIO_UNDEF && \ - uart_config[uart].cts_pin != GPIO_UNDEF) +#define PSEL_RXD dev(uart)->PSEL.RXD +#define PSEL_TXD dev(uart)->PSEL.TXD +#define PSEL_RTS dev(uart)->PSEL.RTS +#define PSEL_CTS dev(uart)->PSEL.CTS +#define UART_IRQN uart_config[uart].irqn +#define UART_PIN_RX uart_config[uart].rx_pin +#define UART_PIN_TX uart_config[uart].tx_pin +#define UART_PIN_RTS uart_config[uart].rts_pin +#define UART_PIN_CTS uart_config[uart].cts_pin +#define UART_HWFLOWCTRL (uart_config[uart].rts_pin != GPIO_UNDEF && \ + uart_config[uart].cts_pin != GPIO_UNDEF) +#define ISR_CTX isr_ctx[uart] +/** + * @brief Allocate memory for the interrupt context + */ +static uart_isr_ctx_t isr_ctx[UART_NUMOF]; #else -#define PSEL_RXD dev(uart)->PSELRXD -#define PSEL_TXD dev(uart)->PSELTXD -#define PSEL_RTS dev(uart)->PSELRTS -#define PSEL_CTS dev(uart)->PSELCTS -#define UART_0_ISR isr_uart0 +#define PSEL_RXD dev(uart)->PSELRXD +#define PSEL_TXD dev(uart)->PSELTXD +#define PSEL_RTS dev(uart)->PSELRTS +#define PSEL_CTS dev(uart)->PSELCTS +#define UART_0_ISR isr_uart0 #ifndef UART_PIN_RTS -#define UART_PIN_RTS GPIO_UNDEF +#define UART_PIN_RTS GPIO_UNDEF #endif #ifndef UART_PIN_CTS -#define UART_PIN_CTS GPIO_UNDEF +#define UART_PIN_CTS GPIO_UNDEF #endif #ifndef UART_HWFLOWCTRL -#define UART_HWFLOWCTRL 0 +#define UART_HWFLOWCTRL 0 #endif -#endif - +#define ISR_CTX isr_ctx /** * @brief Allocate memory for the interrupt context */ static uart_isr_ctx_t isr_ctx; +#endif -static inline NRF_UART_Type *dev(uart_t uart) -{ #ifdef CPU_MODEL_NRF52840XXAA +static inline NRF_UARTE_Type *dev(uart_t uart) +{ return uart_config[uart].dev; +} +static uint8_t rx_buf[UART_NUMOF]; #else +static inline NRF_UART_Type *dev(uart_t uart) +{ (void)uart; - return NRF_UART0; -#endif + return NRF_UART0; } +#endif int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { assert(uart < UART_NUMOF); /* remember callback addresses and argument */ - isr_ctx.rx_cb = rx_cb; - isr_ctx.arg = arg; + ISR_CTX.rx_cb = rx_cb; + ISR_CTX.arg = arg; #ifdef CPU_FAM_NRF51 /* power on the UART device */ @@ -166,15 +177,25 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) } /* enable the UART device */ +#ifdef CPU_MODEL_NRF52840XXAA + dev(uart)->ENABLE = UARTE_ENABLE_ENABLE_Enabled; + dev(uart)->RXD.MAXCNT = 1; + dev(uart)->RXD.PTR = (uint32_t)&rx_buf[uart]; +#else dev(uart)->ENABLE = UART_ENABLE_ENABLE_Enabled; - /* enable TX and RX */ + /* enable TX and RX*/ dev(uart)->TASKS_STARTTX = 1; +#endif if (rx_cb) { dev(uart)->TASKS_STARTRX = 1; /* enable global and receiving interrupt */ NVIC_EnableIRQ(UART_IRQN); +#ifdef CPU_MODEL_NRF52840XXAA + dev(uart)->INTENSET = UARTE_INTENSET_RXDRDY_Msk; +#else dev(uart)->INTENSET = UART_INTENSET_RXDRDY_Msk; +#endif } return UART_OK; @@ -184,6 +205,17 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len) { assert(uart < UART_NUMOF); +#ifdef CPU_MODEL_NRF52840XXAA /* nrf52840 uses EasyDMA to transmit data */ + /* reset endtx flag */ + dev(uart)->EVENTS_ENDTX = 0; + /* set data to transfer to DMA TX pointer */ + dev(uart)->TXD.PTR = (uint32_t)data; + dev(uart)->TXD.MAXCNT = len; + /* start transmission */ + dev(uart)->TASKS_STARTTX = 1; + /* wait for the end of transmission */ + while (dev(uart)->EVENTS_ENDTX == 0) {} +#else for (size_t i = 0; i < len; i++) { /* This section of the function is not thread safe: - another thread may mess up with the uart at the same time. @@ -202,6 +234,7 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len) /* wait for any transmission to be done */ while (dev(uart)->EVENTS_TXDRDY == 0) {} } +#endif } void uart_poweron(uart_t uart) @@ -216,18 +249,35 @@ void uart_poweroff(uart_t uart) { assert(uart < UART_NUMOF); +#ifndef CPU_MODEL_NRF52840XXAA dev(uart)->TASKS_SUSPEND; +#else + (void)uart; +#endif } static inline void irq_handler(uart_t uart) { assert(uart < UART_NUMOF); - +#ifdef CPU_MODEL_NRF52840XXAA /* nrf52840 uses EasyDMA to receive data */ + if (dev(uart)->EVENTS_RXDRDY == 1) { + dev(uart)->EVENTS_RXDRDY = 0; + /* RXRDY doesn't mean that received byte is in RAM + so wait for ENDRX event */ + while(dev(uart)->EVENTS_ENDRX == 0) {} + dev(uart)->EVENTS_ENDRX = 0; + /* Process received byte */ + ISR_CTX.rx_cb(ISR_CTX.arg, rx_buf[uart]); + /* Restart RX task */ + dev(uart)->TASKS_STARTRX = 1; + } +#else if (dev(uart)->EVENTS_RXDRDY == 1) { dev(uart)->EVENTS_RXDRDY = 0; uint8_t byte = (uint8_t)(dev(uart)->RXD & 0xff); - isr_ctx.rx_cb(isr_ctx.arg, byte); + ISR_CTX.rx_cb(ISR_CTX.arg, byte); } +#endif cortexm_isr_end(); } -- GitLab