From 8e8f48f75e72dd2dfaa0090c582a249817907d14 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Sat, 15 Dec 2018 16:06:05 +0100 Subject: [PATCH 1/7] cpu/nrf52: add multi UART support for nrf52840 --- cpu/nrf52/include/periph_cpu.h | 15 +++- cpu/nrf5x_common/periph/uart.c | 158 ++++++++++++++++++++------------- 2 files changed, 108 insertions(+), 65 deletions(-) diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h index ad96f21b63..32daa327ee 100644 --- a/cpu/nrf52/include/periph_cpu.h +++ b/cpu/nrf52/include/periph_cpu.h @@ -39,10 +39,12 @@ extern "C" { * @brief Redefine some peripheral names to unify them between nRF51 and 52 * @{ */ -#define UART_IRQN (UARTE0_UART0_IRQn) #define SPI_SCKSEL (dev(bus)->PSEL.SCK) #define SPI_MOSISEL (dev(bus)->PSEL.MOSI) #define SPI_MISOSEL (dev(bus)->PSEL.MISO) +#ifndef CPU_MODEL_NRF52840XXAA +#define UART_IRQN (UARTE0_UART0_IRQn) +#endif /** @} */ /** @@ -155,6 +157,17 @@ typedef struct { uint32_t pin[PWM_CHANNELS]; /**< PWM out pins */ } pwm_conf_t; +#ifdef CPU_MODEL_NRF52840XXAA +/** + * @brief Structure for UART configuration data + */ +typedef struct { + NRF_UART_Type *dev; /**< UART device base register address */ + uint8_t rx_pin; /**< RX pin */ + uint8_t tx_pin; /**< TX pin */ + uint8_t irqn; /**< IRQ channel */ +} uart_conf_t; +#endif #ifdef __cplusplus } diff --git a/cpu/nrf5x_common/periph/uart.c b/cpu/nrf5x_common/periph/uart.c index dc2be7a4ea..f848282805 100644 --- a/cpu/nrf5x_common/periph/uart.c +++ b/cpu/nrf5x_common/periph/uart.c @@ -31,39 +31,51 @@ #include "periph/gpio.h" #ifdef CPU_MODEL_NRF52840XXAA -#define PSEL_RXD NRF_UART0->PSEL.RXD -#define PSEL_TXD NRF_UART0->PSEL.TXD -#define PSEL_RTS NRF_UART0->PSEL.RTS -#define PSEL_CTS NRF_UART0->PSEL.CTS +#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 #else -#define PSEL_RXD NRF_UART0->PSELRXD -#define PSEL_TXD NRF_UART0->PSELTXD -#define PSEL_RTS NRF_UART0->PSELRTS -#define PSEL_CTS NRF_UART0->PSELCTS +#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 #endif /** * @brief Allocate memory for the interrupt context */ -static uart_isr_ctx_t uart_config; +static uart_isr_ctx_t isr_ctx; + +static inline NRF_UART_Type *dev(uart_t uart) +{ +#ifdef CPU_MODEL_NRF52840XXAA + return uart_config[uart].dev; +#else + (void)uart; + return NRF_UART0; +#endif +} int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { - if (uart != 0) { - return UART_NODEV; - } + assert(uart < UART_NUMOF); /* remember callback addresses and argument */ - uart_config.rx_cb = rx_cb; - uart_config.arg = arg; + isr_ctx.rx_cb = rx_cb; + isr_ctx.arg = arg; #ifdef CPU_FAM_NRF51 /* power on the UART device */ - NRF_UART0->POWER = 1; + dev(uart)->POWER = 1; #endif /* reset configuration registers */ - NRF_UART0->CONFIG = 0; + dev(uart)->CONFIG = 0; /* configure RX pin */ if (rx_cb) { @@ -83,7 +95,7 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) /* configure RTS and CTS pins to use */ PSEL_RTS = UART_PIN_RTS; PSEL_CTS = UART_PIN_CTS; - NRF_UART0->CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */ + dev(uart)->CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */ #else PSEL_RTS = 0xffffffff; /* pin disconnected */ PSEL_CTS = 0xffffffff; /* pin disconnected */ @@ -92,64 +104,64 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) /* select baudrate */ switch (baudrate) { case 1200: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200; break; case 2400: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400; break; case 4800: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800; break; case 9600: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600; break; case 14400: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400; break; case 19200: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200; break; case 28800: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800; break; case 38400: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400; break; case 57600: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600; break; case 76800: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800; break; case 115200: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200; break; case 230400: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400; break; case 250000: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000; break; case 460800: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800; break; case 921600: - NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600; + dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600; break; default: return UART_NOBAUD; } /* enable the UART device */ - NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled; + dev(uart)->ENABLE = UART_ENABLE_ENABLE_Enabled; /* enable TX and RX */ - NRF_UART0->TASKS_STARTTX = 1; + dev(uart)->TASKS_STARTTX = 1; if (rx_cb) { - NRF_UART0->TASKS_STARTRX = 1; + dev(uart)->TASKS_STARTRX = 1; /* enable global and receiving interrupt */ NVIC_EnableIRQ(UART_IRQN); - NRF_UART0->INTENSET = UART_INTENSET_RXDRDY_Msk; + dev(uart)->INTENSET = UART_INTENSET_RXDRDY_Msk; } return UART_OK; @@ -157,47 +169,65 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) void uart_write(uart_t uart, const uint8_t *data, size_t len) { - if (uart == 0) { - 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. - In order to avoid an infinite loop in the interrupted thread, - the TXRDY flag must be cleared before writing the data to be - sent and not after. This way, the higher priority thread will - exit this function with the TXRDY flag set, then the interrupted - thread may have not transmitted his data but will still exit the - while loop. - */ + assert(uart < UART_NUMOF); - /* reset ready flag */ - NRF_UART0->EVENTS_TXDRDY = 0; - /* write data into transmit register */ - NRF_UART0->TXD = data[i]; - /* wait for any transmission to be done */ - while (NRF_UART0->EVENTS_TXDRDY == 0) {} - } + 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. + In order to avoid an infinite loop in the interrupted thread, + the TXRDY flag must be cleared before writing the data to be + sent and not after. This way, the higher priority thread will + exit this function with the TXRDY flag set, then the interrupted + thread may have not transmitted his data but will still exit the + while loop. + */ + + /* reset ready flag */ + dev(uart)->EVENTS_TXDRDY = 0; + /* write data into transmit register */ + dev(uart)->TXD = data[i]; + /* wait for any transmission to be done */ + while (dev(uart)->EVENTS_TXDRDY == 0) {} } } void uart_poweron(uart_t uart) { - (void)uart; - NRF_UART0->TASKS_STARTRX = 1; - NRF_UART0->TASKS_STARTTX = 1; + assert(uart < UART_NUMOF); + + dev(uart)->TASKS_STARTRX = 1; + dev(uart)->TASKS_STARTTX = 1; } void uart_poweroff(uart_t uart) { - (void)uart; - NRF_UART0->TASKS_SUSPEND; + assert(uart < UART_NUMOF); + + dev(uart)->TASKS_SUSPEND; } -void isr_uart0(void) +static inline void irq_handler(uart_t uart) { - if (NRF_UART0->EVENTS_RXDRDY == 1) { - NRF_UART0->EVENTS_RXDRDY = 0; - uint8_t byte = (uint8_t)(NRF_UART0->RXD & 0xff); - uart_config.rx_cb(uart_config.arg, byte); + assert(uart < UART_NUMOF); + + 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); } cortexm_isr_end(); } + +#ifdef UART_0_ISR +void UART_0_ISR(void) +{ + irq_handler(UART_DEV(0)); +} +#endif + +#ifdef UART_1_ISR +void UART_1_ISR(void) +{ + irq_handler(UART_DEV(1)); +} +#endif From 1be60741e378f9ebd915d4bb94c61e9a248eb581 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Sat, 15 Dec 2018 16:07:08 +0100 Subject: [PATCH 2/7] boards/nrf52xxxdk: refactor UART config --- .../{periph_conf.h => periph_conf_common.h} | 15 ++---- boards/nrf52840dk/include/periph_conf.h | 52 +++++++++++++++++++ boards/nrf52dk/include/periph_conf.h | 45 ++++++++++++++++ 3 files changed, 100 insertions(+), 12 deletions(-) rename boards/common/nrf52xxxdk/include/{periph_conf.h => periph_conf_common.h} (85%) create mode 100644 boards/nrf52840dk/include/periph_conf.h create mode 100644 boards/nrf52dk/include/periph_conf.h diff --git a/boards/common/nrf52xxxdk/include/periph_conf.h b/boards/common/nrf52xxxdk/include/periph_conf_common.h similarity index 85% rename from boards/common/nrf52xxxdk/include/periph_conf.h rename to boards/common/nrf52xxxdk/include/periph_conf_common.h index ae06e9849a..dc2ef864d5 100644 --- a/boards/common/nrf52xxxdk/include/periph_conf.h +++ b/boards/common/nrf52xxxdk/include/periph_conf_common.h @@ -18,8 +18,8 @@ * */ -#ifndef PERIPH_CONF_H -#define PERIPH_CONF_H +#ifndef PERIPH_CONF_COMMON_H +#define PERIPH_CONF_COMMON_H #include "periph_cpu.h" #include "cfg_clock_32_1.h" @@ -30,15 +30,6 @@ extern "C" { #endif -/** - * @name UART configuration - * @{ - */ -#define UART_NUMOF (1U) -#define UART_PIN_RX GPIO_PIN(0,8) -#define UART_PIN_TX GPIO_PIN(0,6) -/** @} */ - /** * @name SPI configuration * @{ @@ -84,5 +75,5 @@ static const pwm_conf_t pwm_config[] = { } #endif -#endif /* PERIPH_CONF_H */ +#endif /* PERIPH_CONF_COMMON_H */ /** @} */ diff --git a/boards/nrf52840dk/include/periph_conf.h b/boards/nrf52840dk/include/periph_conf.h new file mode 100644 index 0000000000..166b8c5e01 --- /dev/null +++ b/boards/nrf52840dk/include/periph_conf.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2018 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup boards_nrf52840dk + * @{ + * + * @file + * @brief Peripheral configuration for the nRF52840 DK + * + * @author Alexandre Abadie + * + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +#include "periph_conf_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name UART configuration + * @{ + */ +static const uart_conf_t uart_config[] = { + { + .dev = NRF_UART0, + .rx_pin = GPIO_PIN(0,8), + .tx_pin = GPIO_PIN(0,6), + .irqn = UARTE0_UART0_IRQn, + }, +}; + +#define UART_0_ISR (isr_uart0) + +#define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0])) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_CONF_H */ +/** @} */ diff --git a/boards/nrf52dk/include/periph_conf.h b/boards/nrf52dk/include/periph_conf.h new file mode 100644 index 0000000000..23fd01a278 --- /dev/null +++ b/boards/nrf52dk/include/periph_conf.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016-2018 Freie Universität Berlin + * 2018 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup boards_nrf52dk + * @{ + * + * @file + * @brief Peripheral configuration for the nRF52 DK + * + * @author Hauke Petersen + * @author Alexandre Abadie + * + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +#include "periph_conf_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name UART configuration + * @{ + */ +#define UART_NUMOF (1U) +#define UART_PIN_RX GPIO_PIN(0,8) +#define UART_PIN_TX GPIO_PIN(0,6) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_CONF_H */ +/** @} */ From 336851e3bce38956002a1b11e4d62a2eba4cb298 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Sun, 16 Dec 2018 12:09:57 +0100 Subject: [PATCH 3/7] cpu/nrf52: add uart flow control on nrf52840 --- cpu/nrf52/include/periph_cpu.h | 5 +++++ cpu/nrf5x_common/periph/uart.c | 37 +++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h index 32daa327ee..b8a62e70e6 100644 --- a/cpu/nrf52/include/periph_cpu.h +++ b/cpu/nrf52/include/periph_cpu.h @@ -43,6 +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_IRQN (UARTE0_UART0_IRQn) #endif /** @} */ @@ -165,6 +168,8 @@ typedef struct { NRF_UART_Type *dev; /**< UART 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 */ + uint8_t cts_pin; /**< CTS pin - set to GPIO_UNDEF when not using HW flow control */ uint8_t irqn; /**< IRQ channel */ } uart_conf_t; #endif diff --git a/cpu/nrf5x_common/periph/uart.c b/cpu/nrf5x_common/periph/uart.c index f848282805..09e729ad18 100644 --- a/cpu/nrf5x_common/periph/uart.c +++ b/cpu/nrf5x_common/periph/uart.c @@ -38,12 +38,25 @@ #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) #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 +#ifndef UART_PIN_RTS +#define UART_PIN_RTS GPIO_UNDEF +#endif +#ifndef UART_PIN_CTS +#define UART_PIN_CTS GPIO_UNDEF +#endif +#ifndef UART_HWFLOWCTRL +#define UART_HWFLOWCTRL 0 +#endif #endif /** @@ -88,18 +101,18 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) PSEL_TXD = UART_PIN_TX; /* enable HW-flow control if defined */ -#if UART_HWFLOWCTRL - /* set pin mode for RTS and CTS pins */ - gpio_init(UART_PIN_RTS, GPIO_OUT); - gpio_init(UART_PIN_CTS, GPIO_IN); - /* configure RTS and CTS pins to use */ - PSEL_RTS = UART_PIN_RTS; - PSEL_CTS = UART_PIN_CTS; - dev(uart)->CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */ -#else - PSEL_RTS = 0xffffffff; /* pin disconnected */ - PSEL_CTS = 0xffffffff; /* pin disconnected */ -#endif + if (UART_HWFLOWCTRL) { + /* set pin mode for RTS and CTS pins */ + gpio_init(UART_PIN_RTS, GPIO_OUT); + gpio_init(UART_PIN_CTS, GPIO_IN); + /* configure RTS and CTS pins to use */ + PSEL_RTS = UART_PIN_RTS; + PSEL_CTS = UART_PIN_CTS; + dev(uart)->CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */ + } else { + PSEL_RTS = 0xffffffff; /* pin disconnected */ + PSEL_CTS = 0xffffffff; /* pin disconnected */ + } /* select baudrate */ switch (baudrate) { From 190d48c5d3722d8ad1118a3c26a83443893cf942 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Sun, 16 Dec 2018 12:10:23 +0100 Subject: [PATCH 4/7] boards/nrf52840dk: configure uart flow control pins --- boards/nrf52840dk/include/periph_conf.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boards/nrf52840dk/include/periph_conf.h b/boards/nrf52840dk/include/periph_conf.h index 166b8c5e01..443ee952a0 100644 --- a/boards/nrf52840dk/include/periph_conf.h +++ b/boards/nrf52840dk/include/periph_conf.h @@ -35,6 +35,8 @@ static const uart_conf_t uart_config[] = { .dev = NRF_UART0, .rx_pin = GPIO_PIN(0,8), .tx_pin = GPIO_PIN(0,6), + .rts_pin = GPIO_PIN(0,5), + .cts_pin = GPIO_PIN(0,7), .irqn = UARTE0_UART0_IRQn, }, }; From cb8c2b759e107f67bf9bc4fbe685e393fdc826ee Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Mon, 17 Dec 2018 10:08:58 +0100 Subject: [PATCH 5/7] 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 | 112 ++++++++++++++++++++++++--------- 2 files changed, 85 insertions(+), 35 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 + * 2018 Inria * * * This file is subject to the terms and conditions of the GNU Lesser @@ -20,6 +21,7 @@ * @author Timo Ziegler * @author Hauke Petersen * @author Jan Wagner + * @author Alexandre Abadie * * @} */ @@ -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 +#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) { -#ifdef CPU_MODEL_NRF52840XXAA - return uart_config[uart].dev; -#else (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(); } From 72f3f7d4f17415cd3f7da569c55e7bdf1d4881d6 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Mon, 17 Dec 2018 10:09:52 +0100 Subject: [PATCH 6/7] boards/nrf52840dk: add second UART interface This commit also change the STDIO UART to use the UARTE device type (with EasyDMA) --- boards/nrf52840dk/include/periph_conf.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/boards/nrf52840dk/include/periph_conf.h b/boards/nrf52840dk/include/periph_conf.h index 443ee952a0..a3d143d765 100644 --- a/boards/nrf52840dk/include/periph_conf.h +++ b/boards/nrf52840dk/include/periph_conf.h @@ -31,17 +31,26 @@ extern "C" { * @{ */ static const uart_conf_t uart_config[] = { - { - .dev = NRF_UART0, + { /* Mapped to USB virtual COM port */ + .dev = NRF_UARTE0, .rx_pin = GPIO_PIN(0,8), .tx_pin = GPIO_PIN(0,6), .rts_pin = GPIO_PIN(0,5), .cts_pin = GPIO_PIN(0,7), .irqn = UARTE0_UART0_IRQn, }, + { /* Mapped to Arduino D0/D1 pins */ + .dev = NRF_UARTE1, + .rx_pin = GPIO_PIN(1,1), + .tx_pin = GPIO_PIN(1,2), + .rts_pin = (uint8_t)GPIO_UNDEF, + .cts_pin = (uint8_t)GPIO_UNDEF, + .irqn = UARTE1_IRQn, + }, }; #define UART_0_ISR (isr_uart0) +#define UART_1_ISR (isr_uart1) #define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0])) /** @} */ From 93e7d88f7556a3cc50cc8435a1c9c9c4d44f9e83 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Fri, 25 Jan 2019 11:41:21 +0100 Subject: [PATCH 7/7] cpu/nrf5x: reworked and fixed UART driver --- boards/nrf52840dk/include/periph_conf.h | 2 +- cpu/nrf52/include/periph_cpu.h | 3 - cpu/nrf5x_common/periph/uart.c | 241 ++++++++++++++---------- 3 files changed, 140 insertions(+), 106 deletions(-) diff --git a/boards/nrf52840dk/include/periph_conf.h b/boards/nrf52840dk/include/periph_conf.h index a3d143d765..feef124331 100644 --- a/boards/nrf52840dk/include/periph_conf.h +++ b/boards/nrf52840dk/include/periph_conf.h @@ -50,7 +50,7 @@ static const uart_conf_t uart_config[] = { }; #define UART_0_ISR (isr_uart0) -#define UART_1_ISR (isr_uart1) +#define UART_1_ISR (isr_uarte1) #define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0])) /** @} */ diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h index 27843d075e..b684f234bc 100644 --- a/cpu/nrf52/include/periph_cpu.h +++ b/cpu/nrf52/include/periph_cpu.h @@ -43,9 +43,6 @@ 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_IRQN (UARTE0_UART0_IRQn) #endif /** @} */ diff --git a/cpu/nrf5x_common/periph/uart.c b/cpu/nrf5x_common/periph/uart.c index 12ade1daaa..148084071a 100644 --- a/cpu/nrf5x_common/periph/uart.c +++ b/cpu/nrf5x_common/periph/uart.c @@ -33,61 +33,54 @@ #include "periph/gpio.h" #ifdef CPU_MODEL_NRF52840XXAA +#define UART_INVALID (uart >= UART_NUMOF) +#define REG_BAUDRATE dev(uart)->BAUDRATE +#define REG_CONFIG dev(uart)->CONFIG #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 UART_HWFLOWCTRL (uart_config[uart].rts_pin != (uint8_t)GPIO_UNDEF && \ + uart_config[uart].cts_pin != (uint8_t)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 -#ifndef UART_PIN_RTS -#define UART_PIN_RTS GPIO_UNDEF -#endif -#ifndef UART_PIN_CTS -#define UART_PIN_CTS GPIO_UNDEF -#endif -#ifndef UART_HWFLOWCTRL -#define UART_HWFLOWCTRL 0 -#endif -#define ISR_CTX isr_ctx -/** - * @brief Allocate memory for the interrupt context - */ -static uart_isr_ctx_t isr_ctx; -#endif +static uint8_t rx_buf[UART_NUMOF]; -#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 + +#else /* nrf51 and nrf52832 etc */ + +#define UART_INVALID (uart != 0) +#define REG_BAUDRATE NRF_UART0->BAUDRATE +#define REG_CONFIG NRF_UART0->CONFIG +#define PSEL_RXD NRF_UART0->PSELRXD +#define PSEL_TXD NRF_UART0->PSELTXD +#define UART_0_ISR isr_uart0 +#define ISR_CTX isr_ctx + +/** + * @brief Allocate memory for the interrupt context + */ +static uart_isr_ctx_t isr_ctx; + +#endif /* CPU_MODEL_NRF52840XXAA */ + int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { - assert(uart < UART_NUMOF); + if (UART_INVALID) { + return UART_NODEV; + } /* remember callback addresses and argument */ ISR_CTX.rx_cb = rx_cb; @@ -95,11 +88,11 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) #ifdef CPU_FAM_NRF51 /* power on the UART device */ - dev(uart)->POWER = 1; + NRF_UART0->POWER = 1; #endif /* reset configuration registers */ - dev(uart)->CONFIG = 0; + REG_CONFIG = 0; /* configure RX pin */ if (rx_cb) { @@ -111,66 +104,81 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) gpio_init(UART_PIN_TX, GPIO_OUT); PSEL_TXD = UART_PIN_TX; +#ifdef CPU_MODEL_NRF52840XXAA /* enable HW-flow control if defined */ if (UART_HWFLOWCTRL) { /* set pin mode for RTS and CTS pins */ gpio_init(UART_PIN_RTS, GPIO_OUT); gpio_init(UART_PIN_CTS, GPIO_IN); /* configure RTS and CTS pins to use */ - PSEL_RTS = UART_PIN_RTS; - PSEL_CTS = UART_PIN_CTS; - dev(uart)->CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */ + dev(uart)->PSEL.RTS = UART_PIN_RTS; + dev(uart)->PSEL.CTS = UART_PIN_CTS; + REG_CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */ } else { - PSEL_RTS = 0xffffffff; /* pin disconnected */ - PSEL_CTS = 0xffffffff; /* pin disconnected */ + dev(uart)->PSEL.RTS = 0xffffffff; /* pin disconnected */ + dev(uart)->PSEL.CTS = 0xffffffff; /* pin disconnected */ } +#else +#if UART_HWFLOWCTRL + /* set pin mode for RTS and CTS pins */ + gpio_init(UART_PIN_RTS, GPIO_OUT); + gpio_init(UART_PIN_CTS, GPIO_IN); + /* configure RTS and CTS pins to use */ + NRF_UART0->PSELRTS = UART_PIN_RTS; + NRF_UART0->PSELCTS = UART_PIN_CTS; + REG_CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */ +#else + NRF_UART0->PSELRTS = 0xffffffff; /* pin disconnected */ + NRF_UART0->PSELCTS = 0xffffffff; /* pin disconnected */ +#endif +#endif /* select baudrate */ switch (baudrate) { case 1200: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200; break; case 2400: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400; break; case 4800: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800; break; case 9600: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600; break; case 14400: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400; break; case 19200: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200; break; case 28800: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800; break; case 38400: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400; break; case 57600: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600; break; case 76800: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800; break; case 115200: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200; break; case 230400: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400; break; case 250000: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000; break; case 460800: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800; break; case 921600: - dev(uart)->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600; + REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600; break; default: return UART_NOBAUD; @@ -179,33 +187,37 @@ 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*/ - dev(uart)->TASKS_STARTTX = 1; + NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled; + NRF_UART0->TASKS_STARTTX = 1; #endif if (rx_cb) { +#ifdef CPU_MODEL_NRF52840XXAA + dev(uart)->RXD.MAXCNT = 1; + dev(uart)->RXD.PTR = (uint32_t)&rx_buf[uart]; + dev(uart)->INTENSET = UARTE_INTENSET_ENDRX_Msk; + dev(uart)->SHORTS |= UARTE_SHORTS_ENDRX_STARTRX_Msk; dev(uart)->TASKS_STARTRX = 1; +#else + NRF_UART0->INTENSET = UART_INTENSET_RXDRDY_Msk; + NRF_UART0->TASKS_STARTRX = 1; +#endif + /* 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; } + +#ifdef CPU_MODEL_NRF52840XXAA /* nrf52840 (using EasyDMA) */ + 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 */ @@ -215,7 +227,46 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len) dev(uart)->TASKS_STARTTX = 1; /* wait for the end of transmission */ while (dev(uart)->EVENTS_ENDTX == 0) {} -#else +} + +void uart_poweron(uart_t uart) +{ + assert(uart < UART_NUMOF); + + if (isr_ctx[uart].rx_cb) { + NRF_UART0->TASKS_STARTRX = 1; + } +} + +void uart_poweroff(uart_t uart) +{ + assert(uart < UART_NUMOF); + + dev(uart)->TASKS_STOPRX = 1; +} + +static inline void irq_handler(uart_t uart) +{ + if (dev(uart)->EVENTS_ENDRX == 1) { + dev(uart)->EVENTS_ENDRX = 0; + + /* make sure we actually received new data */ + if (dev(uart)->RXD.AMOUNT == 0) { + return; + } + /* Process received byte */ + isr_ctx[uart].rx_cb(isr_ctx[uart].arg, rx_buf[uart]); + } + + cortexm_isr_end(); +} + +#else /* nrf51 and nrf52832 etc */ + +void uart_write(uart_t uart, const uint8_t *data, size_t len) +{ + (void)uart; + 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. @@ -226,61 +277,47 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len) thread may have not transmitted his data but will still exit the while loop. */ - /* reset ready flag */ - dev(uart)->EVENTS_TXDRDY = 0; + NRF_UART0->EVENTS_TXDRDY = 0; /* write data into transmit register */ - dev(uart)->TXD = data[i]; + NRF_UART0->TXD = data[i]; /* wait for any transmission to be done */ - while (dev(uart)->EVENTS_TXDRDY == 0) {} + while (NRF_UART0->EVENTS_TXDRDY == 0) {} } -#endif } void uart_poweron(uart_t uart) { - assert(uart < UART_NUMOF); + (void)uart; - dev(uart)->TASKS_STARTRX = 1; - dev(uart)->TASKS_STARTTX = 1; + NRF_UART0->TASKS_STARTTX = 1; + if (isr_ctx.rx_cb) { + NRF_UART0->TASKS_STARTRX = 1; + } } void uart_poweroff(uart_t uart) { - assert(uart < UART_NUMOF); - -#ifndef CPU_MODEL_NRF52840XXAA - dev(uart)->TASKS_SUSPEND; -#else (void)uart; -#endif + + NRF_UART0->TASKS_SUSPEND; } 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; + (void)uart; + + if (NRF_UART0->EVENTS_RXDRDY == 1) { + NRF_UART0->EVENTS_RXDRDY = 0; + uint8_t byte = (uint8_t)(NRF_UART0->RXD & 0xff); + isr_ctx.rx_cb(isr_ctx.arg, byte); } -#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); - } -#endif + cortexm_isr_end(); } +#endif /* CPU_MODEL_NRF52840XXAA */ + #ifdef UART_0_ISR void UART_0_ISR(void) {