diff --git a/boards/acd52832/include/periph_conf.h b/boards/acd52832/include/periph_conf.h index c17278166f..736bba4082 100644 --- a/boards/acd52832/include/periph_conf.h +++ b/boards/acd52832/include/periph_conf.h @@ -43,9 +43,21 @@ extern "C" { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -#define UART_PIN_RX GPIO_PIN(0, 30) -#define UART_PIN_TX GPIO_PIN(0, 31) +static const uart_conf_t uart_config[] = { + { + .dev = NRF_UARTE0, + .rx_pin = GPIO_PIN(0, 30), + .tx_pin = GPIO_PIN(0, 31), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UARTE0_UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR (isr_uart0) /** @} */ /** diff --git a/boards/airfy-beacon/include/periph_conf.h b/boards/airfy-beacon/include/periph_conf.h index 094916c099..db0b912c31 100644 --- a/boards/airfy-beacon/include/periph_conf.h +++ b/boards/airfy-beacon/include/periph_conf.h @@ -31,13 +31,23 @@ /** * @name UART configuration - * - * The CPU only supports one UART device, so we keep it simple * @{ */ -#define UART_NUMOF (1U) -#define UART_PIN_RX 17 -#define UART_PIN_TX 18 +static const uart_conf_t uart_config[] = { + { /* Mapped to USB virtual COM port */ + .dev = NRF_UART0, + .rx_pin = GPIO_PIN(0, 17), + .tx_pin = GPIO_PIN(0, 18), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR isr_uart0 /** @} */ /** diff --git a/boards/calliope-mini/include/periph_conf.h b/boards/calliope-mini/include/periph_conf.h index 3d77c88048..5c62be7b73 100644 --- a/boards/calliope-mini/include/periph_conf.h +++ b/boards/calliope-mini/include/periph_conf.h @@ -33,10 +33,21 @@ extern "C" { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -/* UART pin configuration */ -#define UART_PIN_RX 25 -#define UART_PIN_TX 24 +static const uart_conf_t uart_config[] = { + { + .dev = NRF_UART0, + .rx_pin = GPIO_PIN(0, 25), + .tx_pin = GPIO_PIN(0, 24), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR isr_uart0 /** @} */ /** diff --git a/boards/dwm1001/include/periph_conf.h b/boards/dwm1001/include/periph_conf.h index 30ce5c8ede..83413e8c42 100644 --- a/boards/dwm1001/include/periph_conf.h +++ b/boards/dwm1001/include/periph_conf.h @@ -20,10 +20,10 @@ #ifndef PERIPH_CONF_H #define PERIPH_CONF_H -#include "periph_cpu.h" #include "cfg_clock_32_1.h" #include "cfg_rtt_default.h" #include "cfg_timer_default.h" +#include "periph_cpu.h" #ifdef __cplusplus extern "C" { @@ -33,9 +33,21 @@ extern "C" { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -#define UART_PIN_RX GPIO_PIN(0, 11) -#define UART_PIN_TX GPIO_PIN(0, 5) +static const uart_conf_t uart_config[] = { + { /* Mapped to USB virtual COM port */ + .dev = NRF_UARTE0, + .rx_pin = GPIO_PIN(0, 11), + .tx_pin = GPIO_PIN(0, 5), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UARTE0_UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR (isr_uart0) /** @} */ /** diff --git a/boards/microbit/include/periph_conf.h b/boards/microbit/include/periph_conf.h index a5fac39602..90c5af1c6f 100644 --- a/boards/microbit/include/periph_conf.h +++ b/boards/microbit/include/periph_conf.h @@ -29,13 +29,24 @@ extern "C" { #endif /** - * @name UART configuration + * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -/* UART pin configuration */ -#define UART_PIN_RX 25 -#define UART_PIN_TX 24 +static const uart_conf_t uart_config[] = { + { /* Mapped to USB virtual COM port */ + .dev = NRF_UART0, + .rx_pin = GPIO_PIN(0, 25), + .tx_pin = GPIO_PIN(0, 24), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR isr_uart0 /** @} */ /** diff --git a/boards/nrf51dk/include/periph_conf.h b/boards/nrf51dk/include/periph_conf.h index 4399bd50b3..acaefceaa9 100644 --- a/boards/nrf51dk/include/periph_conf.h +++ b/boards/nrf51dk/include/periph_conf.h @@ -29,15 +29,24 @@ extern "C" { #endif /** - * @name UART configuration + * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -/* UART pin configuration */ -#define UART_PIN_RX 11 -#define UART_PIN_TX 9 -#define UART_PIN_RTS 8 -#define UART_PIN_CTS 10 +static const uart_conf_t uart_config[] = { + { /* Mapped to USB virtual COM port */ + .dev = NRF_UART0, + .rx_pin = GPIO_PIN(0, 11), + .tx_pin = GPIO_PIN(0, 9), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_PIN(0, 8), + .cts_pin = GPIO_PIN(0, 10), +#endif + .irqn = UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR isr_uart0 /** @} */ /** diff --git a/boards/nrf51dongle/include/periph_conf.h b/boards/nrf51dongle/include/periph_conf.h index a3eee64eb9..e8568cc0ff 100644 --- a/boards/nrf51dongle/include/periph_conf.h +++ b/boards/nrf51dongle/include/periph_conf.h @@ -29,15 +29,24 @@ extern "C" { #endif /** - * @name UART configuration + * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -/* UART pin configuration */ -#define UART_PIN_RX 11 -#define UART_PIN_TX 9 -#define UART_PIN_RTS 8 -#define UART_PIN_CTS 10 +static const uart_conf_t uart_config[] = { + { + .dev = NRF_UART0, + .rx_pin = GPIO_PIN(0, 11), + .tx_pin = GPIO_PIN(0, 9), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_PIN(0, 8), + .cts_pin = GPIO_PIN(0, 10), +#endif + .irqn = UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR isr_uart0 /** @} */ #ifdef __cplusplus diff --git a/boards/nrf52832-mdk/include/periph_conf.h b/boards/nrf52832-mdk/include/periph_conf.h index f98988b054..4d95927b1d 100644 --- a/boards/nrf52832-mdk/include/periph_conf.h +++ b/boards/nrf52832-mdk/include/periph_conf.h @@ -35,9 +35,21 @@ extern "C" { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -#define UART_PIN_RX GPIO_PIN(0, 19) -#define UART_PIN_TX GPIO_PIN(0, 20) +static const uart_conf_t uart_config[] = { + { + .dev = NRF_UARTE0, + .rx_pin = GPIO_PIN(0, 19), + .tx_pin = GPIO_PIN(0, 20), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UARTE0_UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR (isr_uart0) /** @} */ #ifdef __cplusplus diff --git a/boards/nrf52dk/include/periph_conf.h b/boards/nrf52dk/include/periph_conf.h index e0d7991259..4bfe6e9ff2 100644 --- a/boards/nrf52dk/include/periph_conf.h +++ b/boards/nrf52dk/include/periph_conf.h @@ -48,9 +48,21 @@ static const spi_conf_t spi_config[] = { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -#define UART_PIN_RX GPIO_PIN(0, 8) -#define UART_PIN_TX GPIO_PIN(0, 6) +static const uart_conf_t uart_config[] = { + { /* Mapped to USB virtual COM port */ + .dev = NRF_UARTE0, + .rx_pin = GPIO_PIN(0, 8), + .tx_pin = GPIO_PIN(0, 6), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UARTE0_UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR (isr_uart0) /** @} */ #ifdef __cplusplus diff --git a/boards/nrf6310/include/periph_conf.h b/boards/nrf6310/include/periph_conf.h index d87050ddee..bbe0d27efe 100644 --- a/boards/nrf6310/include/periph_conf.h +++ b/boards/nrf6310/include/periph_conf.h @@ -35,14 +35,21 @@ extern "C" { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -#define UART_IRQ_PRIO 1 +static const uart_conf_t uart_config[] = { + { + .dev = NRF_UART0, + .rx_pin = GPIO_PIN(0, 16), + .tx_pin = GPIO_PIN(0, 17), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_PIN(0, 19), + .cts_pin = GPIO_PIN(0, 18), +#endif + .irqn = UART0_IRQn, + }, +}; -/* UART pin configuration */ -#define UART_PIN_RX 16 -#define UART_PIN_TX 17 -#define UART_PIN_RTS 19 -#define UART_PIN_CTS 18 +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR isr_uart0 /** @} */ /** diff --git a/boards/ruuvitag/include/periph_conf.h b/boards/ruuvitag/include/periph_conf.h index ee7390f9ff..9ec026a58d 100644 --- a/boards/ruuvitag/include/periph_conf.h +++ b/boards/ruuvitag/include/periph_conf.h @@ -50,9 +50,21 @@ static const spi_conf_t spi_config[] = { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -#define UART_PIN_RX GPIO_PIN(0, 4) -#define UART_PIN_TX GPIO_PIN(0, 5) +static const uart_conf_t uart_config[] = { + { + .dev = NRF_UARTE0, + .rx_pin = GPIO_PIN(0, 4), + .tx_pin = GPIO_PIN(0, 5), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UARTE0_UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR (isr_uart0) /** @} */ #ifdef __cplusplus diff --git a/boards/thingy52/include/periph_conf.h b/boards/thingy52/include/periph_conf.h index 6e53f6f6c7..559afac802 100644 --- a/boards/thingy52/include/periph_conf.h +++ b/boards/thingy52/include/periph_conf.h @@ -33,9 +33,21 @@ extern "C" { * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -#define UART_PIN_RX GPIO_PIN(0, 2) -#define UART_PIN_TX GPIO_PIN(0, 3) +static const uart_conf_t uart_config[] = { + { + .dev = NRF_UARTE0, + .rx_pin = GPIO_PIN(0, 2), + .tx_pin = GPIO_PIN(0, 3), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UARTE0_UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR (isr_uart0) /** @} */ /** diff --git a/boards/yunjia-nrf51822/include/periph_conf.h b/boards/yunjia-nrf51822/include/periph_conf.h index 119c3bb54b..4da79573e8 100644 --- a/boards/yunjia-nrf51822/include/periph_conf.h +++ b/boards/yunjia-nrf51822/include/periph_conf.h @@ -29,13 +29,24 @@ extern "C" { #endif /** - * @name UART configuration + * @name UART configuration * @{ */ -#define UART_NUMOF (1U) -/* UART pin configuration */ -#define UART_PIN_RX 1 -#define UART_PIN_TX 2 +static const uart_conf_t uart_config[] = { + { /* Mapped to USB virtual COM port */ + .dev = NRF_UART0, + .rx_pin = GPIO_PIN(0, 1), + .tx_pin = GPIO_PIN(0, 2), +#ifdef MODULE_PERIPH_UART_HW_FC + .rts_pin = GPIO_UNDEF, + .cts_pin = GPIO_UNDEF, +#endif + .irqn = UART0_IRQn, + }, +}; + +#define UART_NUMOF ARRAY_SIZE(uart_config) +#define UART_0_ISR isr_uart0 /** @} */ /** diff --git a/cpu/nrf51/include/periph_cpu.h b/cpu/nrf51/include/periph_cpu.h index 371bf353d3..f09ba7dbef 100644 --- a/cpu/nrf51/include/periph_cpu.h +++ b/cpu/nrf51/include/periph_cpu.h @@ -34,7 +34,6 @@ extern "C" { * @brief Redefine some peripheral names to unify them between nRF51 and 52 * @{ */ -#define UART_IRQN (UART0_IRQn) #define SPI_SCKSEL (dev(bus)->PSELSCK) #define SPI_MOSISEL (dev(bus)->PSELMOSI) #define SPI_MISOSEL (dev(bus)->PSELMISO) diff --git a/cpu/nrf52/Kconfig b/cpu/nrf52/Kconfig index f76ad03b7c..af87fb19ca 100644 --- a/cpu/nrf52/Kconfig +++ b/cpu/nrf52/Kconfig @@ -19,19 +19,18 @@ config CPU_FAM_NRF52 select HAS_CPU_NRF52 select HAS_PERIPH_I2C_RECONFIGURE select HAS_PERIPH_SPI_GPIO_MODE + select HAS_PERIPH_UART_NONBLOCKING ## CPU Models config CPU_MODEL_NRF52805XXAA bool select CPU_CORE_CORTEX_M4 select CPU_FAM_NRF52 - select HAS_PERIPH_UART_NONBLOCKING config CPU_MODEL_NRF52810XXAA bool select CPU_CORE_CORTEX_M4 select CPU_FAM_NRF52 - select HAS_PERIPH_UART_NONBLOCKING config CPU_MODEL_NRF52811XXAA bool @@ -39,7 +38,6 @@ config CPU_MODEL_NRF52811XXAA select CPU_FAM_NRF52 select HAS_BLE_PHY_CODED select HAS_RADIO_NRF802154 - select HAS_PERIPH_UART_NONBLOCKING config CPU_MODEL_NRF52820XXAA bool @@ -47,7 +45,6 @@ config CPU_MODEL_NRF52820XXAA select CPU_FAM_NRF52 select HAS_BLE_PHY_CODED select HAS_RADIO_NRF802154 - select HAS_PERIPH_UART_NONBLOCKING config CPU_MODEL_NRF52832XXAA bool @@ -60,7 +57,6 @@ config CPU_MODEL_NRF52833XXAA select CPU_FAM_NRF52 select HAS_BLE_PHY_CODED select HAS_RADIO_NRF802154 - select HAS_PERIPH_UART_NONBLOCKING config CPU_MODEL_NRF52840XXAA bool @@ -68,7 +64,6 @@ config CPU_MODEL_NRF52840XXAA select CPU_FAM_NRF52 select HAS_BLE_PHY_CODED select HAS_RADIO_NRF802154 - select HAS_PERIPH_UART_NONBLOCKING select HAS_PERIPH_HASH_SHA_1 select HAS_PERIPH_HASH_SHA_224 select HAS_PERIPH_HASH_SHA_256 diff --git a/cpu/nrf52/Makefile.features b/cpu/nrf52/Makefile.features index a56403645e..06b9573103 100644 --- a/cpu/nrf52/Makefile.features +++ b/cpu/nrf52/Makefile.features @@ -23,9 +23,9 @@ ifneq (,$(filter nrf52840xxaa,$(CPU_MODEL))) FEATURES_PROVIDED += periph_ecc_ed25519 endif -ifeq (,$(filter nrf52832%,$(CPU_MODEL))) - FEATURES_PROVIDED += periph_uart_nonblocking -endif +# All nRF52 CPUs use UARTE (UART + EasyDMA) for UART, so that can be used +# in non-blocking mode +FEATURES_PROVIDED += periph_uart_nonblocking # The ADC does not depend on any board configuration, so always available FEATURES_PROVIDED += periph_adc diff --git a/cpu/nrf5x_common/include/periph_cpu_common.h b/cpu/nrf5x_common/include/periph_cpu_common.h index a41a36248b..40912952c6 100644 --- a/cpu/nrf5x_common/include/periph_cpu_common.h +++ b/cpu/nrf5x_common/include/periph_cpu_common.h @@ -316,13 +316,16 @@ typedef struct { */ uint8_t gpio_int_get_exti(gpio_t pin); -#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51) /** * @brief Structure for UART configuration data */ typedef struct { +#ifdef UARTE_PRESENT NRF_UARTE_Type *dev; /**< UART with EasyDMA device base * register address */ +#else + NRF_UART_Type *dev; /**< UART device base register address */ +#endif gpio_t rx_pin; /**< RX pin */ gpio_t tx_pin; /**< TX pin */ #ifdef MODULE_PERIPH_UART_HW_FC @@ -339,8 +342,6 @@ typedef struct { #define UART_TXBUF_SIZE (64) #endif -#endif /* ndef CPU_MODEL_NRF52832XXAA && ndef CPU_FAM_NRF51 */ - /** * @brief USBDEV buffers must be word aligned because of DMA restrictions */ @@ -407,9 +408,6 @@ typedef struct { #define SPI_SCKSEL (dev(bus)->PSEL.SCK) /**< Macro for SPI clk */ #define SPI_MOSISEL (dev(bus)->PSEL.MOSI) /**< Macro for SPI mosi */ #define SPI_MISOSEL (dev(bus)->PSEL.MISO) /**< Macro for SPI miso */ -#ifdef CPU_MODEL_NRF52832XXAA -#define UART_IRQN (UARTE0_UART0_IRQn) -#endif /** * @brief SPI configuration values diff --git a/cpu/nrf5x_common/periph/uart.c b/cpu/nrf5x_common/periph/uart.c index 80d7b29ee1..3e30f1622a 100644 --- a/cpu/nrf5x_common/periph/uart.c +++ b/cpu/nrf5x_common/periph/uart.c @@ -28,28 +28,32 @@ * @} */ -#include #include #include +#include "compiler_hints.h" #include "cpu.h" -#include "periph/uart.h" #include "periph/gpio.h" +#include "periph/uart.h" -#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51) -#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 UART_IRQN uart_config[uart].irqn -#define UART_PIN_RX uart_config[uart].rx_pin -#define UART_PIN_TX uart_config[uart].tx_pin -#ifdef MODULE_PERIPH_UART_HW_FC -#define UART_PIN_RTS uart_config[uart].rts_pin -#define UART_PIN_CTS uart_config[uart].cts_pin +#ifdef UARTE_PRESENT +# define PSEL_RXD PSEL.RXD +# define PSEL_TXD PSEL.TXD +# define PSEL_RTS PSEL.RTS +# define PSEL_CTS PSEL.CTS +# define ENABLE_ON UARTE_ENABLE_ENABLE_Enabled +# define ENABLE_OFF UARTE_ENABLE_ENABLE_Disabled +# define UART_TYPE NRF_UARTE_Type +#else +# define PSEL_RXD PSELRXD +# define PSEL_TXD PSELTXD +# define PSEL_RTS PSELRTS +# define PSEL_CTS PSELCTS +# define ENABLE_ON UART_ENABLE_ENABLE_Enabled +# define ENABLE_OFF UART_ENABLE_ENABLE_Disabled +# define UART_TYPE NRF_UART_Type #endif -#define ISR_CTX isr_ctx[uart] + #define RAM_MASK (0x20000000) /** @@ -63,7 +67,9 @@ * @brief Allocate memory for the interrupt context */ static uart_isr_ctx_t isr_ctx[UART_NUMOF]; +#ifdef UARTE_PRESENT static uint8_t rx_buf[UART_NUMOF]; +#endif #ifdef MODULE_PERIPH_UART_NONBLOCKING @@ -81,149 +87,126 @@ static uint8_t uart_tx_rb_buf[UART_NUMOF][UART_TXBUF_SIZE]; */ void uart_isr_handler(void *arg); -static inline NRF_UARTE_Type *dev(uart_t uart) -{ - return uart_config[uart].dev; -} - -#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_NRF52832XXAA && !CPU_FAM_NRF51 */ +/* use an enum to count the number of UART ISR macro names defined by the + * board */ +enum { +#ifdef UART_0_ISR + UART_0_ISR_NUM, +#endif +#ifdef UART_1_ISR + UART_1_ISR_NUM, +#endif + UART_ISR_NUMOF, +}; int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { - if (UART_INVALID) { +/* ensure the ISR names have been defined as needed */ +#if !defined(CPU_NRF53) && !defined(CPU_NRF9160) + static_assert(UART_NUMOF == UART_ISR_NUMOF, "Define(s) of UART ISR name(s) missing"); +#endif + if ((unsigned)uart >= UART_NUMOF) { return UART_NODEV; } - /* remember callback addresses and argument */ - ISR_CTX.rx_cb = rx_cb; - ISR_CTX.arg = arg; + UART_TYPE *dev = uart_config[uart].dev; -#ifdef CPU_FAM_NRF51 - /* power on the UART device */ - NRF_UART0->POWER = 1; + /* remember callback addresses and argument */ + isr_ctx[uart].rx_cb = rx_cb; + isr_ctx[uart].arg = arg; + +#ifndef UARTE_PRESENT + /* only the legacy non-EasyDMA UART needs to be powered on explicitly */ + dev->POWER = 1; #endif /* reset configuration registers */ - REG_CONFIG = 0; + dev->CONFIG = 0; /* configure RX pin */ if (rx_cb) { - gpio_init(UART_PIN_RX, GPIO_IN); - PSEL_RXD = UART_PIN_RX; + gpio_init(uart_config[uart].rx_pin, GPIO_IN); + dev->PSEL_RXD = uart_config[uart].rx_pin; } /* configure TX pin */ - gpio_init(UART_PIN_TX, GPIO_OUT); - PSEL_TXD = UART_PIN_TX; + gpio_init(uart_config[uart].tx_pin, GPIO_OUT); + dev->PSEL_TXD = uart_config[uart].tx_pin; -#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51) /* enable HW-flow control if defined */ #ifdef MODULE_PERIPH_UART_HW_FC - /* set pin mode for RTS and CTS pins */ - if (UART_PIN_RTS != GPIO_UNDEF && UART_PIN_CTS != GPIO_UNDEF) { - gpio_init(UART_PIN_RTS, GPIO_OUT); - gpio_init(UART_PIN_CTS, GPIO_IN); - /* configure RTS and CTS pins to use */ - 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 - dev(uart)->PSEL.RTS = 0xffffffff; /* pin disconnected */ - dev(uart)->PSEL.CTS = 0xffffffff; /* pin disconnected */ -#endif -#else -#ifdef MODULE_PERIPH_UART_HW_FC /* set pin mode for RTS and CTS pins */ - if (UART_PIN_RTS != GPIO_UNDEF && UART_PIN_CTS != GPIO_UNDEF) { - gpio_init(UART_PIN_RTS, GPIO_OUT); - gpio_init(UART_PIN_CTS, GPIO_IN); + if (uart_config[uart].rts_pin != GPIO_UNDEF && uart_config[uart].cts_pin != GPIO_UNDEF) { + gpio_init(uart_config[uart].rts_pin, GPIO_OUT); + gpio_init(uart_config[uart].cts_pin, 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 */ + dev->PSEL_RTS = uart_config[uart].rts_pin; + dev->PSEL_CTS = uart_config[uart].cts_pin; + dev->CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */ } -#else - NRF_UART0->PSELRTS = 0xffffffff; /* pin disconnected */ - NRF_UART0->PSELCTS = 0xffffffff; /* pin disconnected */ -#endif /* MODULE_PERIPH_UART_HW_FC */ + else #endif + { + dev->PSEL_RTS = 0xffffffff; /* pin disconnected */ + dev->PSEL_CTS = 0xffffffff; /* pin disconnected */ + } /* select baudrate */ switch (baudrate) { - case 1200: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200; - break; - case 2400: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400; - break; - case 4800: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800; - break; - case 9600: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600; - break; - case 14400: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400; - break; - case 19200: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200; - break; - case 28800: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800; - break; - case 38400: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400; - break; - case 57600: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600; - break; - case 76800: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800; - break; - case 115200: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200; - break; - case 230400: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400; - break; - case 250000: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000; - break; - case 460800: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800; - break; - case 921600: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600; - break; - case 1000000: - REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M; - break; - default: - return UART_NOBAUD; + case 1200: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200; + break; + case 2400: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400; + break; + case 4800: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800; + break; + case 9600: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600; + break; + case 14400: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400; + break; + case 19200: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200; + break; + case 28800: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800; + break; + case 38400: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400; + break; + case 57600: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600; + break; + case 76800: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800; + break; + case 115200: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200; + break; + case 230400: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400; + break; + case 250000: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000; + break; + case 460800: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800; + break; + case 921600: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600; + break; + case 1000000: + dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M; + break; + default: + return UART_NOBAUD; } /* enable the UART device */ -#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51) - dev(uart)->ENABLE = UARTE_ENABLE_ENABLE_Enabled; -#else - NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled; -#endif + dev->ENABLE = ENABLE_ON; #ifdef MODULE_PERIPH_UART_NONBLOCKING /* set up the TX buffer */ @@ -231,60 +214,60 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) #endif if (rx_cb) { -#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51) - 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; +#ifdef UARTE_PRESENT + dev->RXD.MAXCNT = 1; + dev->RXD.PTR = (uint32_t)&rx_buf[uart]; + dev->INTENSET = UARTE_INTENSET_ENDRX_Msk; + dev->SHORTS |= UARTE_SHORTS_ENDRX_STARTRX_Msk; + dev->TASKS_STARTRX = 1; #else - NRF_UART0->INTENSET = UART_INTENSET_RXDRDY_Msk; - NRF_UART0->TASKS_STARTRX = 1; + dev->INTENSET = UART_INTENSET_RXDRDY_Msk; + dev->TASKS_STARTRX = 1; #endif } if (rx_cb || IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) { #if defined(CPU_NRF53) || defined(CPU_NRF9160) - shared_irq_register_uart(dev(uart), uart_isr_handler, (void *)(uintptr_t)uart); + shared_irq_register_uart(dev, uart_isr_handler, (void *)(uintptr_t)uart); #else - NVIC_EnableIRQ(UART_IRQN); + NVIC_EnableIRQ(uart_config[uart].irqn); #endif } return UART_OK; } -/* nrf52840 || nrf52811 (using EasyDMA) */ -#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51) +/* UART with EasyDMA */ +#ifdef UARTE_PRESENT static void _write_buf(uart_t uart, const uint8_t *data, size_t len) { - dev(uart)->EVENTS_ENDTX = 0; + uart_config[uart].dev->EVENTS_ENDTX = 0; if (IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) { - dev(uart)->INTENSET = UARTE_INTENSET_ENDTX_Msk; + uart_config[uart].dev->INTENSET = UARTE_INTENSET_ENDTX_Msk; } /* set data to transfer to DMA TX pointer */ - dev(uart)->TXD.PTR = (uint32_t)data; - dev(uart)->TXD.MAXCNT = len; + uart_config[uart].dev->TXD.PTR = (uint32_t)data; + uart_config[uart].dev->TXD.MAXCNT = len; /* start transmission */ - dev(uart)->TASKS_STARTTX = 1; + uart_config[uart].dev->TASKS_STARTTX = 1; /* wait for the end of transmission */ if (!IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) { - while (dev(uart)->EVENTS_ENDTX == 0) {} - dev(uart)->TASKS_STOPTX = 1; + while (uart_config[uart].dev->EVENTS_ENDTX == 0) {} + uart_config[uart].dev->TASKS_STOPTX = 1; } } void uart_write(uart_t uart, const uint8_t *data, size_t len) { - assert(uart < UART_NUMOF); + assume((unsigned)uart < UART_NUMOF); #ifdef MODULE_PERIPH_UART_NONBLOCKING for (size_t i = 0; i < len; i++) { /* in IRQ or interrupts disabled */ if (irq_is_in() || __get_PRIMASK()) { if (tsrb_full(&uart_tx_rb[uart])) { /* wait for end of ongoing transmission */ - if (dev(uart)->EVENTS_TXSTARTED) { - while (dev(uart)->EVENTS_ENDTX == 0) {} - dev(uart)->EVENTS_TXSTARTED = 0; + if (uart_config[uart].dev->EVENTS_TXSTARTED) { + while (uart_config[uart].dev->EVENTS_ENDTX == 0) {} + uart_config[uart].dev->EVENTS_TXSTARTED = 0; } /* free one spot in buffer */ tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]); @@ -295,7 +278,7 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len) else { /* if no transmission is ongoing and ring buffer is full free up a spot in the buffer by sending one byte */ - if (!dev(uart)->EVENTS_TXSTARTED && tsrb_full(&uart_tx_rb[uart])) { + if (!uart_config[uart].dev->EVENTS_TXSTARTED && tsrb_full(&uart_tx_rb[uart])) { tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]); _write_buf(uart, &tx_buf[uart], 1); } @@ -304,7 +287,7 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len) } /* if no transmission is ongoing bootstrap the transmission process by setting a single byte to be written */ - if (!dev(uart)->EVENTS_TXSTARTED) { + if (!uart_config[uart].dev->EVENTS_TXSTARTED) { if (!tsrb_empty(&uart_tx_rb[uart])) { tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]); _write_buf(uart, &tx_buf[uart], 1); @@ -334,25 +317,33 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len) void uart_poweron(uart_t uart) { - assert(uart < UART_NUMOF); + assume((unsigned)uart < UART_NUMOF); if (isr_ctx[uart].rx_cb) { - dev(uart)->TASKS_STARTRX = 1; + uart_config[uart].dev->TASKS_STARTRX = 1; } } void uart_poweroff(uart_t uart) { - assert(uart < UART_NUMOF); + assume((unsigned)uart < UART_NUMOF); - dev(uart)->TASKS_STOPRX = 1; + uart_config[uart].dev->TASKS_STOPRX = 1; } int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, uart_stop_bits_t stop_bits) { - - if (stop_bits != UART_STOP_BITS_1 && stop_bits != UART_STOP_BITS_2) { + assume((unsigned)uart < UART_NUMOF); + /* Not all nRF52 MCUs support 2 stop bits, but the vendor header files + * reflect the feature set. */ + switch (stop_bits) { + case UART_STOP_BITS_1: +#ifdef UARTE_CONFIG_STOP_Msk + case UART_STOP_BITS_2: +#endif + break; + default: return UART_NOMODE; } @@ -364,43 +355,43 @@ int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, return UART_NOMODE; } + /* Do not modify hardware flow control */ + uint32_t conf = uart_config[uart].dev->CONFIG & UARTE_CONFIG_HWFC_Msk; + +#ifdef UARTE_CONFIG_STOP_Msk if (stop_bits == UART_STOP_BITS_2) { - dev(uart)->CONFIG |= UARTE_CONFIG_STOP_Msk; - } - else { - dev(uart)->CONFIG &= ~UARTE_CONFIG_STOP_Msk; + conf |= UARTE_CONFIG_STOP_Msk; } +#endif if (parity == UART_PARITY_EVEN) { - dev(uart)->CONFIG |= UARTE_CONFIG_PARITY_Msk; - } - else { - dev(uart)->CONFIG &= ~UARTE_CONFIG_PARITY_Msk; + conf |= UARTE_CONFIG_PARITY_Msk; } + uart_config[uart].dev->CONFIG = conf; return UART_OK; } -static inline void irq_handler(uart_t uart) +static void irq_handler(uart_t uart) { - if (dev(uart)->EVENTS_ENDRX) { - dev(uart)->EVENTS_ENDRX = 0; + if (uart_config[uart].dev->EVENTS_ENDRX) { + uart_config[uart].dev->EVENTS_ENDRX = 0; /* make sure we actually received new data */ - if (dev(uart)->RXD.AMOUNT != 0) { + if (uart_config[uart].dev->RXD.AMOUNT != 0) { /* Process received byte */ isr_ctx[uart].rx_cb(isr_ctx[uart].arg, rx_buf[uart]); } } #ifdef MODULE_PERIPH_UART_NONBLOCKING - if (dev(uart)->EVENTS_ENDTX) { + if (uart_config[uart].dev->EVENTS_ENDTX) { /* reset flags and idsable ISR on EVENTS_ENDTX */ - dev(uart)->EVENTS_ENDTX = 0; - dev(uart)->EVENTS_TXSTARTED = 0; - dev(uart)->INTENCLR = UARTE_INTENSET_ENDTX_Msk; + uart_config[uart].dev->EVENTS_ENDTX = 0; + uart_config[uart].dev->EVENTS_TXSTARTED = 0; + uart_config[uart].dev->INTENCLR = UARTE_INTENSET_ENDTX_Msk; if (tsrb_empty(&uart_tx_rb[uart])) { - dev(uart)->TASKS_STOPTX = 1; + uart_config[uart].dev->TASKS_STOPTX = 1; } else { tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]); _write_buf(uart, &tx_buf[uart], 1); @@ -411,13 +402,13 @@ static inline void irq_handler(uart_t uart) cortexm_isr_end(); } -#else /* nrf51 and nrf52832 etc */ +#else /* UART without EasyDMA*/ void uart_write(uart_t uart, const uint8_t *data, size_t len) { - (void)uart; + assume((unsigned)uart < UART_NUMOF); - NRF_UART0->TASKS_STARTTX = 1; + uart_config[uart].dev->TASKS_STARTTX = 1; for (size_t i = 0; i < len; i++) { /* This section of the function is not thread safe: @@ -430,36 +421,36 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len) while loop. */ /* reset ready flag */ - NRF_UART0->EVENTS_TXDRDY = 0; + uart_config[uart].dev->EVENTS_TXDRDY = 0; /* write data into transmit register */ - NRF_UART0->TXD = data[i]; + uart_config[uart].dev->TXD = data[i]; /* wait for any transmission to be done */ - while (NRF_UART0->EVENTS_TXDRDY == 0) {} + while (uart_config[uart].dev->EVENTS_TXDRDY == 0) {} } - NRF_UART0->TASKS_STOPTX = 1; + uart_config[uart].dev->TASKS_STOPTX = 1; } void uart_poweron(uart_t uart) { - (void)uart; + assume((unsigned)uart < UART_NUMOF); - if (isr_ctx.rx_cb) { - NRF_UART0->TASKS_STARTRX = 1; + if (isr_ctx[uart].rx_cb) { + uart_config[uart].dev->TASKS_STARTRX = 1; } } void uart_poweroff(uart_t uart) { - (void)uart; + assume((unsigned)uart < UART_NUMOF); - NRF_UART0->TASKS_STOPRX = 1; + uart_config[uart].dev->TASKS_STOPRX = 1; } int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, uart_stop_bits_t stop_bits) { - (void)uart; + assume((unsigned)uart < UART_NUMOF); if (stop_bits != UART_STOP_BITS_1) { return UART_NOMODE; @@ -474,29 +465,27 @@ int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, } if (parity == UART_PARITY_EVEN) { - NRF_UART0->CONFIG |= UART_CONFIG_PARITY_Msk; + uart_config[uart].dev->CONFIG |= UART_CONFIG_PARITY_Msk; } else { - NRF_UART0->CONFIG &= ~UART_CONFIG_PARITY_Msk; + uart_config[uart].dev->CONFIG &= ~UART_CONFIG_PARITY_Msk; } return UART_OK; } -static inline void irq_handler(uart_t uart) +static void irq_handler(uart_t uart) { - (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); + if (uart_config[uart].dev->EVENTS_RXDRDY == 1) { + uart_config[uart].dev->EVENTS_RXDRDY = 0; + uint8_t byte = (uint8_t)(uart_config[uart].dev->RXD & 0xff); + isr_ctx[uart].rx_cb(isr_ctx[uart].arg, byte); } cortexm_isr_end(); } -#endif /* !CPU_MODEL_NRF52832XXAA && !CPU_FAM_NRF51 */ +#endif #if defined(CPU_NRF53) || defined(CPU_NRF9160) void uart_isr_handler(void *arg) @@ -519,4 +508,5 @@ void UART_1_ISR(void) irq_handler(UART_DEV(1)); } #endif + #endif /* def CPU_NRF53 || CPU_NRF9160 */