From affb0aec45c9c17cbb5f853be67313d0230e75f6 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Mon, 9 Jul 2018 12:51:58 -0700 Subject: [PATCH] Change NRF52 series UART to only use one SWI channel This fixes conflicts with the SoftDevice. --- targets/TARGET_NORDIC/TARGET_NRF5x/README.md | 7 +- .../TARGET_NRF5x/TARGET_NRF52/mbed_lib.json | 12 +- .../TARGET_NRF5x/TARGET_NRF52/serial_api.c | 105 ++++++++++-------- 3 files changed, 64 insertions(+), 60 deletions(-) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/README.md b/targets/TARGET_NORDIC/TARGET_NRF5x/README.md index 7dd4c278552..fb2f9cc8407 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/README.md +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/README.md @@ -143,9 +143,9 @@ The table must be placed in a C compilation file. Because each DMA buffer must be at least 5 bytes deep, each buffer is automatically flushed after a certain idle period to ensure low latency and correctness. This idle timeout is implemented using 2 of the 4 channels on RTC instance 2. This leaves RTC0 for the SoftDevice and RTC1 for Mbed tickers. -#### SWI2, SWI3, SWI4, and SWI5 +#### SWI0 -To minimize the time spend in the highest priority interrupt handler all callbacks to the user provided IRQ handlers are deferred through Software Interrupts running at lowest priority. SWI 2-5 are reserved by the serial implementation. +To minimize the time spend in the highest priority interrupt handler all callbacks to the user provided IRQ handlers are deferred through Software Interrupts running at lowest priority. SWI0 is reserved by the serial implementation. #### Asserts @@ -156,13 +156,14 @@ The SDK file `mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/librari The assert handler is defined in mbed-os/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp : assert_nrf_callback() which forwards assert failures to thye mbed error() handler. - #### Limitations * The UARTE hardware only supports 8-bit, None/Even parity, and 1 stop bit. * The asynchronous read and write implementation currently only support 255 byte transfers. * The EasyDMA hardware can only read from RAM, which means all Tx buffers must reside in RAM. If a Tx buffer residing in flash is passed to the asynchronous write function, the function will try to copy the Tx buffer to a temporary internal buffer and transmit the data from there. * It is not possible to do an asynchronous write from flash and receive non-asynchronously at the same time since the non-asynchronous receive buffer is being used as the temporary transmission buffer. + * The driver will flush the DMA buffer after a configurable timeout. During this process the UART will be halted and therefor unable to receive data. Hardware flow control should be enabled to avoid missing any data during this window. + ## SoftDevice diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/mbed_lib.json b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/mbed_lib.json index 7272b1cf3e2..22e54bacbaf 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/mbed_lib.json +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/mbed_lib.json @@ -18,11 +18,13 @@ "value": 8 } }, + "macros": [ + "SWI_DISABLE0" + ], "target_overrides": { "DELTA_DFBM_NQ620": { "target.macros_add": [ "CONFIG_GPIO_AS_PINRESET", - "SWI_DISABLE0", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_20", @@ -45,7 +47,6 @@ "MTB_LAIRD_BL652": { "target.macros_add": [ "CONFIG_GPIO_AS_PINRESET", - "SWI_DISABLE0", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_20", @@ -67,7 +68,6 @@ "MTB_UBLOX_NINA_B1": { "target.macros_add": [ "CONFIG_GPIO_AS_PINRESET", - "SWI_DISABLE0", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_20", @@ -87,7 +87,6 @@ "NRF52_DK": { "target.macros_add": [ "CONFIG_GPIO_AS_PINRESET", - "SWI_DISABLE0", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_20", @@ -108,7 +107,6 @@ "RBLAB_BLENANO2": { "target.macros_add": [ "CONFIG_GPIO_AS_PINRESET", - "SWI_DISABLE0", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_20", @@ -128,7 +126,6 @@ "UBLOX_EVA_NINA": { "target.macros_add": [ "CONFIG_GPIO_AS_PINRESET", - "SWI_DISABLE0", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_20", @@ -148,7 +145,6 @@ "UBLOX_EVK_NINA_B1": { "target.macros_add": [ "CONFIG_GPIO_AS_PINRESET", - "SWI_DISABLE0", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_20", @@ -169,7 +165,6 @@ "VBLUNO52": { "target.macros_add": [ "CONFIG_GPIO_AS_PINRESET", - "SWI_DISABLE0", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_20", @@ -190,7 +185,6 @@ "NRF52840_DK": { "target.macros_add": [ "CONFIG_GPIO_AS_PINRESET", - "SWI_DISABLE0", "NRF52_ERRATA_20" ], "target.console-uart-flow-control": "RTSCTS" diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/serial_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/serial_api.c index 2d4de63d983..7f7c968cbb3 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/serial_api.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/serial_api.c @@ -122,14 +122,6 @@ */ #define RTC_FREQUENCY 32768 -/** - * SWI IRQ numbers - */ -#define UARTE0_SWI_TX_IRQ SWI2_EGU2_IRQn -#define UARTE0_SWI_RX_IRQ SWI3_EGU3_IRQn -#define UARTE1_SWI_TX_IRQ SWI4_EGU4_IRQn -#define UARTE1_SWI_RX_IRQ SWI5_EGU5_IRQn - /*** * _______ _ __ * |__ __| | | / _| @@ -238,6 +230,14 @@ NRF_ATFIFO_DEF(nordic_nrf5_uart_fifo_0, uint8_t, UART0_FIFO_BUFFER_SIZE); NRF_ATFIFO_DEF(nordic_nrf5_uart_fifo_1, uint8_t, UART1_FIFO_BUFFER_SIZE); #endif +/** + * SWI IRQ mask. + */ +static uint8_t nordic_nrf5_uart_swi_mask_tx_0 = 0; +static uint8_t nordic_nrf5_uart_swi_mask_rx_0 = 0; +static uint8_t nordic_nrf5_uart_swi_mask_tx_1 = 0; +static uint8_t nordic_nrf5_uart_swi_mask_rx_1 = 0; + /** * Global variables expected by mbed_retarget.cpp for STDOUT. */ @@ -411,16 +411,6 @@ static void nordic_nrf5_uart_callback_handler(uint32_t instance) } } -static void nordic_nrf5_uart_swi_rx_0(void) -{ - nordic_nrf5_uart_callback_handler(0); -} - -static void nordic_nrf5_uart_swi_rx_1(void) -{ - nordic_nrf5_uart_callback_handler(1); -} - /** * @brief SWI interrupt handler for when the Tx buffer has been transmitted. * @@ -477,33 +467,55 @@ static void nordic_nrf5_uart_event_handler_endtx_asynch(int instance) } #endif -static void nordic_nrf5_uart_swi_tx_0(void) +static void nordic_nrf5_uart_swi0(void) { + if (nordic_nrf5_uart_swi_mask_tx_0) { + + nordic_nrf5_uart_swi_mask_tx_0 = 0; + #if DEVICE_SERIAL_ASYNCH - if (nordic_nrf5_uart_state[0].tx_asynch) { + if (nordic_nrf5_uart_state[0].tx_asynch) { - nordic_nrf5_uart_event_handler_endtx_asynch(0); - } else + nordic_nrf5_uart_event_handler_endtx_asynch(0); + } else #endif - { - nordic_nrf5_uart_event_handler_endtx(0); + { + nordic_nrf5_uart_event_handler_endtx(0); + } } -} + + if (nordic_nrf5_uart_swi_mask_rx_0) { + + nordic_nrf5_uart_swi_mask_rx_0 = 0; + + nordic_nrf5_uart_callback_handler(0); + } + #if UART1_ENABLED -static void nordic_nrf5_uart_swi_tx_1(void) -{ + if (nordic_nrf5_uart_swi_mask_tx_1) { + + nordic_nrf5_uart_swi_mask_tx_1 = 0; + #if DEVICE_SERIAL_ASYNCH - if (nordic_nrf5_uart_state[1].tx_asynch) { + if (nordic_nrf5_uart_state[1].tx_asynch) { - nordic_nrf5_uart_event_handler_endtx_asynch(1); - } else + nordic_nrf5_uart_event_handler_endtx_asynch(1); + } else #endif - { - nordic_nrf5_uart_event_handler_endtx(1); + { + nordic_nrf5_uart_event_handler_endtx(1); + } + } + + if (nordic_nrf5_uart_swi_mask_rx_1) { + + nordic_nrf5_uart_swi_mask_rx_1 = 0; + + nordic_nrf5_uart_callback_handler(1); } -} #endif +} /** * @brief Trigger Tx SWI. @@ -514,12 +526,14 @@ static void nordic_swi_tx_trigger(int instance) { if (instance == 0) { - NVIC_SetPendingIRQ(UARTE0_SWI_TX_IRQ); + nordic_nrf5_uart_swi_mask_tx_0 = 1; + NVIC_SetPendingIRQ(SWI0_EGU0_IRQn); } #if UART1_ENABLED else if (instance == 1) { - NVIC_SetPendingIRQ(UARTE1_SWI_TX_IRQ); + nordic_nrf5_uart_swi_mask_tx_1 = 1; + NVIC_SetPendingIRQ(SWI0_EGU0_IRQn); } #endif } @@ -533,12 +547,16 @@ static void nordic_swi_rx_trigger(int instance) { if (instance == 0) { - NVIC_SetPendingIRQ(UARTE0_SWI_RX_IRQ); + nordic_nrf5_uart_swi_mask_rx_0 = 1; + NVIC_SetPendingIRQ(SWI0_EGU0_IRQn); } +#if UART1_ENABLED else if (instance == 1) { - NVIC_SetPendingIRQ(UARTE1_SWI_RX_IRQ); + nordic_nrf5_uart_swi_mask_rx_1 = 1; + NVIC_SetPendingIRQ(SWI0_EGU0_IRQn); } +#endif } /*** @@ -990,17 +1008,8 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) nrf_rtc_task_trigger(NRF_RTC2, NRF_RTC_TASK_START); /* Enable interrupts for SWI. */ - NVIC_SetVector(UARTE0_SWI_TX_IRQ, (uint32_t) nordic_nrf5_uart_swi_tx_0); - NVIC_SetVector(UARTE0_SWI_RX_IRQ, (uint32_t) nordic_nrf5_uart_swi_rx_0); - nrf_drv_common_irq_enable(UARTE0_SWI_TX_IRQ, APP_IRQ_PRIORITY_LOWEST); - nrf_drv_common_irq_enable(UARTE0_SWI_RX_IRQ, APP_IRQ_PRIORITY_LOWEST); - -#if UART1_ENABLED - NVIC_SetVector(UARTE1_SWI_TX_IRQ, (uint32_t) nordic_nrf5_uart_swi_tx_1); - NVIC_SetVector(UARTE1_SWI_RX_IRQ, (uint32_t) nordic_nrf5_uart_swi_rx_1); - nrf_drv_common_irq_enable(UARTE1_SWI_TX_IRQ, APP_IRQ_PRIORITY_LOWEST); - nrf_drv_common_irq_enable(UARTE1_SWI_RX_IRQ, APP_IRQ_PRIORITY_LOWEST); -#endif + NVIC_SetVector(SWI0_EGU0_IRQn, (uint32_t) nordic_nrf5_uart_swi0); + nrf_drv_common_irq_enable(SWI0_EGU0_IRQn, APP_IRQ_PRIORITY_LOWEST); /* Initialize FIFO buffer for UARTE0. */ NRF_ATFIFO_INIT(nordic_nrf5_uart_fifo_0);