1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/nrf5x: clean up periph_uart

- nRF51: Use `uart_conf_t` for consistency with nRF52
- nRF52832: Use UARTE (UART with EasyDMA) over UART (without DMA), as
  done for all other nRF52 family members
- use `UARTE_PRESENT` to detect whether an UARTE can be used, rather
  than family names
This commit is contained in:
Marian Buschsieweke 2023-11-22 15:27:59 +01:00
parent cd897ebb99
commit 63faa5f162
No known key found for this signature in database
GPG Key ID: 77AA882EC78084E6
18 changed files with 397 additions and 275 deletions

View File

@ -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)
/** @} */
/**

View File

@ -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
/** @} */
/**

View File

@ -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
/** @} */
/**

View File

@ -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)
/** @} */
/**

View File

@ -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
/** @} */
/**

View File

@ -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
/** @} */
/**

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
/** @} */
/**

View File

@ -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

View File

@ -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)
/** @} */
/**

View File

@ -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
/** @} */
/**

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -28,28 +28,32 @@
* @}
*/
#include <assert.h>
#include <stdint.h>
#include <string.h>
#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 */