From 72c93a9743d64b6d50ef380b6f9de15ccc2c0b32 Mon Sep 17 00:00:00 2001 From: Dylan Laduranty Date: Wed, 5 Jul 2023 14:43:41 +0200 Subject: [PATCH] cpu/nrfxx: introduce shared serial IRQ For now, nRF53 and nRF9160 will shared UART/I2C/SPI IRQs, nRF52 will reuse the same callback but will keep its own file to avoid breakage. This can be continue in a followup PR Signed-off-by: Dylan Laduranty --- cpu/nrf52/spi_twi_irq.c | 14 +- cpu/nrf5x_common/Kconfig | 5 + cpu/nrf5x_common/shared_irq/Kconfig | 11 + cpu/nrf5x_common/shared_irq/Makefile | 7 + .../shared_irq/shared_serial_irq.c | 209 ++++++++++++++++++ cpu/nrf9160/spi_twi_irq.c | 155 ------------- 6 files changed, 239 insertions(+), 162 deletions(-) create mode 100644 cpu/nrf5x_common/shared_irq/Kconfig create mode 100644 cpu/nrf5x_common/shared_irq/Makefile create mode 100644 cpu/nrf5x_common/shared_irq/shared_serial_irq.c delete mode 100644 cpu/nrf9160/spi_twi_irq.c diff --git a/cpu/nrf52/spi_twi_irq.c b/cpu/nrf52/spi_twi_irq.c index 30083c16a9..daa7036362 100644 --- a/cpu/nrf52/spi_twi_irq.c +++ b/cpu/nrf52/spi_twi_irq.c @@ -57,7 +57,7 @@ #define SPIM_COUNT 2 #endif -static spi_twi_irq_cb_t _irq[SPIM_COUNT]; +static shared_irq_cb_t _irq[SPIM_COUNT]; static void *_irq_arg[SPIM_COUNT]; static mutex_t _locks[SPIM_COUNT]; @@ -123,8 +123,8 @@ static const IRQn_Type _isr[] = { #endif /* CPU_MODEL_NRF52840XXAA */ }; -void spi_twi_irq_register_spi(NRF_SPIM_Type *bus, - spi_twi_irq_cb_t cb, void *arg) +void shared_irq_register_spi(NRF_SPIM_Type *bus, + shared_irq_cb_t cb, void *arg) { size_t num = _spi_dev2num(bus); @@ -133,8 +133,8 @@ void spi_twi_irq_register_spi(NRF_SPIM_Type *bus, NVIC_EnableIRQ(_isr[num]); } -void spi_twi_irq_register_i2c(NRF_TWIM_Type *bus, - spi_twi_irq_cb_t cb, void *arg) +void shared_irq_register_i2c(NRF_TWIM_Type *bus, + shared_irq_cb_t cb, void *arg) { size_t num = _i2c_dev2num(bus); @@ -145,7 +145,7 @@ void spi_twi_irq_register_i2c(NRF_TWIM_Type *bus, } void nrf5x_i2c_acquire(NRF_TWIM_Type *bus, - spi_twi_irq_cb_t cb, void *arg) + shared_irq_cb_t cb, void *arg) { size_t num = _i2c_dev2num(bus); mutex_lock(&_locks[num]); @@ -154,7 +154,7 @@ void nrf5x_i2c_acquire(NRF_TWIM_Type *bus, } void nrf5x_spi_acquire(NRF_SPIM_Type *bus, - spi_twi_irq_cb_t cb, void *arg) + shared_irq_cb_t cb, void *arg) { size_t num = _spi_dev2num(bus); mutex_lock(&_locks[num]); diff --git a/cpu/nrf5x_common/Kconfig b/cpu/nrf5x_common/Kconfig index 3da9d1aaa6..b6bf0b38eb 100644 --- a/cpu/nrf5x_common/Kconfig +++ b/cpu/nrf5x_common/Kconfig @@ -53,6 +53,11 @@ config HAS_VDD_LC_FILTER_REG1 Indicates that a board is equipped with an external LC filter circuit attached to the CPUs voltage regulator stage 1. +config MODULE_NRF_SHARED_SERIAL_IRQ + bool + depends on CPU_FAM_NRF53 || CPU_FAM_NRF9160 + help + Indicates that the MCU used shared IRQ for UART/I2C/SPI. config MODULE_CPU_COMMON bool diff --git a/cpu/nrf5x_common/shared_irq/Kconfig b/cpu/nrf5x_common/shared_irq/Kconfig new file mode 100644 index 0000000000..8be2b0cb67 --- /dev/null +++ b/cpu/nrf5x_common/shared_irq/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Mesotic SAS +# +# 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. +# + +config MODULE_NRF_SHARED_SERIAL_IRQ + bool + depends on TEST_KCONFIG + default y diff --git a/cpu/nrf5x_common/shared_irq/Makefile b/cpu/nrf5x_common/shared_irq/Makefile new file mode 100644 index 0000000000..4584e068d0 --- /dev/null +++ b/cpu/nrf5x_common/shared_irq/Makefile @@ -0,0 +1,7 @@ +MODULE = nrf_shared_serial_irq + +SRC_FILE = shared_serial_irq.c + +SRCS += $(SRC_FILE) + +include $(RIOTBASE)/Makefile.base diff --git a/cpu/nrf5x_common/shared_irq/shared_serial_irq.c b/cpu/nrf5x_common/shared_irq/shared_serial_irq.c new file mode 100644 index 0000000000..8b389c6b19 --- /dev/null +++ b/cpu/nrf5x_common/shared_irq/shared_serial_irq.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2023 Mesotic SAS + * + * 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 cpu_nrf5x_common + * @{ + * + * @file + * @brief Shared IRQ handling between UART, SPI and TWI peripherals + * on the nRF53/9160 devices + * + * I2C is called TWI (Two Wire Interface) in Nordic's documentation + * + * @author Dylan Laduranty + * + * @} + */ + +#include + +#include "cpu.h" +#include "mutex.h" +#include "periph_cpu.h" +#include "periph_conf.h" + +static shared_irq_cb_t _irq[SPIM_COUNT]; +static void *_irq_arg[SPIM_COUNT]; + +static mutex_t _locks[SPIM_COUNT]; + +/* UART, I2C and SPI share peripheral addresses */ +static size_t _spi_dev2num(void *dev) +{ + if (dev == NRF_SPIM0_S) { + return 0; + } + else if (dev == NRF_SPIM1_S) { + return 1; + } + else if (dev == NRF_SPIM2_S) { + return 2; + } + else if (dev == NRF_SPIM3_S) { + return 3; + } +#ifdef NRF_SPIM4_S + else if (dev == NRF_SPIM4_S) { + return 4; + } +#endif + else { + assert(false); + return 0; + } +} + +static inline size_t _i2c_dev2num(void *dev) +{ + if (dev == NRF_SPIM0_S) { + return 0; + } + else if (dev == NRF_SPIM1_S) { + return 1; + } + else if (dev == NRF_SPIM2_S) { + return 2; + } + else if (dev == NRF_SPIM3_S) { + return 3; + } + else { + assert(false); + return 0; + } +} + +static inline size_t _uart_dev2num(void *dev) +{ + /* I2C and UART have the same amount of instances */ + return _i2c_dev2num(dev); +} + +#ifdef CPU_MODEL_NRF5340_APP +static const IRQn_Type _isr[] = { +SERIAL0_IRQn, +SERIAL1_IRQn, +SERIAL2_IRQn, +SERIAL3_IRQn, +SPIM4_IRQn +}; +#define SERIAL0_ISR isr_serial0 +#define SERIAL1_ISR isr_serial1 +#define SERIAL2_ISR isr_serial2 +#define SERIAL3_ISR isr_serial3 +#define SERIAL4_ISR isr_spim4 +#elif defined(CPU_NRF9160) +static const IRQn_Type _isr[] = { +UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQn, +UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQn, +UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQn, +UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQn +}; +#define SERIAL0_ISR isr_uarte0_spim0_spis0_twim0_twis0 +#define SERIAL1_ISR isr_uarte1_spim1_spis1_twim1_twis1 +#define SERIAL2_ISR isr_uarte2_spim2_spis2_twim2_twis2 +#define SERIAL3_ISR isr_uarte3_spim3_spis3_twim3_twis3 +#else +#error "Missing shared IRQ configuration for this MCU."asm +#endif + +void shared_irq_register_spi(NRF_SPIM_Type *bus, + shared_irq_cb_t cb, void *arg) +{ + size_t num = _spi_dev2num(bus); + + _irq[num] = cb; + _irq_arg[num] = arg; + NVIC_EnableIRQ(_isr[num]); +} + +void shared_irq_register_i2c(NRF_TWIM_Type *bus, + shared_irq_cb_t cb, void *arg) +{ + size_t num = _i2c_dev2num(bus); + + _irq[num] = cb; + _irq_arg[num] = arg; + + NVIC_EnableIRQ(_isr[num]); +} + +void shared_irq_register_uart(NRF_UARTE_Type *bus, + shared_irq_cb_t cb, void *arg) +{ + size_t num = _uart_dev2num(bus); + + _irq[num] = cb; + _irq_arg[num] = arg; + + NVIC_EnableIRQ(_isr[num]); +} + +void nrf5x_i2c_acquire(NRF_TWIM_Type *bus, + shared_irq_cb_t cb, void *arg) +{ + size_t num = _i2c_dev2num(bus); + mutex_lock(&_locks[num]); + _irq[num] = cb; + _irq_arg[num] = arg; +} + +void nrf5x_spi_acquire(NRF_SPIM_Type *bus, + shared_irq_cb_t cb, void *arg) +{ + size_t num = _spi_dev2num(bus); + mutex_lock(&_locks[num]); + _irq[num] = cb; + _irq_arg[num] = arg; +} + +void nrf5x_i2c_release(NRF_TWIM_Type *bus) +{ + size_t num = _i2c_dev2num(bus); + mutex_unlock(&_locks[num]); +} + +void nrf5x_spi_release(NRF_SPIM_Type *bus) +{ + size_t num = _spi_dev2num(bus); + mutex_unlock(&_locks[num]); +} + +/* ISR Routines */ +void SERIAL0_ISR(void) +{ + _irq[0](_irq_arg[0]); + cortexm_isr_end(); +} + +void SERIAL1_ISR(void) +{ + _irq[1](_irq_arg[1]); + cortexm_isr_end(); +} + +void SERIAL2_ISR(void) +{ + _irq[2](_irq_arg[2]); + cortexm_isr_end(); +} + +void SERIAL3_ISR(void) +{ + _irq[3](_irq_arg[3]); + cortexm_isr_end(); +} + +#ifdef SERIAL4_ISR +void serial4_isr(void) +{ + _irq[4](_irq_arg[4]); + cortexm_isr_end(); +} +#endif diff --git a/cpu/nrf9160/spi_twi_irq.c b/cpu/nrf9160/spi_twi_irq.c deleted file mode 100644 index ee98dfea06..0000000000 --- a/cpu/nrf9160/spi_twi_irq.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2021 Mesotic SAS - * - * 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 cpu_nrf9160 - * @{ - * - * @file - * @brief Shared IRQ handling between SPI and TWI peripherals on the nRF52 - * devices - * - * I2C is called TWI (Two Wire Interface) in the datasheets from Nordic - * - * @author Dylan Laduranty - * - * @} - */ - -#include - -#include "cpu.h" -#include "mutex.h" -#include "periph_cpu.h" -#include "periph_conf.h" - -static spi_twi_irq_cb_t _irq[TWIM_COUNT]; -static void *_irq_arg[TWIM_COUNT]; - -static mutex_t _locks[SPIM_COUNT]; - -#if TWIM_COUNT != SPIM_COUNT -#error Possible configuration issue, please update this file -#endif - -/* I2C and SPI share peripheral addresses */ -static size_t _spi_dev2num(void *dev) -{ - if (dev == NRF_SPIM0_S) { - return 0; - } - else if (dev == NRF_SPIM1_S) { - return 1; - } - else if (dev == NRF_SPIM2_S) { - return 2; - } - else if (dev == NRF_SPIM3_S) { - return 3; - } - else { - assert(false); - return 0; - } -} - -static inline size_t _i2c_dev2num(void *dev) -{ - return _spi_dev2num(dev); -} - -static const IRQn_Type _isr[] = { -UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQn, -UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQn, -UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQn, -UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQn -}; - -void spi_twi_irq_register_spi(NRF_SPIM_Type *bus, - spi_twi_irq_cb_t cb, void *arg) -{ - size_t num = _spi_dev2num(bus); - - _irq[num] = cb; - _irq_arg[num] = arg; - NVIC_EnableIRQ(_isr[num]); -} - -void spi_twi_irq_register_i2c(NRF_TWIM_Type *bus, - spi_twi_irq_cb_t cb, void *arg) -{ - size_t num = _i2c_dev2num(bus); - - _irq[num] = cb; - _irq_arg[num] = arg; - - NVIC_EnableIRQ(_isr[num]); -} - -void nrf5x_i2c_acquire(NRF_TWIM_Type *bus, - spi_twi_irq_cb_t cb, void *arg) -{ - size_t num = _i2c_dev2num(bus); - mutex_lock(&_locks[num]); - _irq[num] = cb; - _irq_arg[num] = arg; -} - -void nrf5x_spi_acquire(NRF_SPIM_Type *bus, - spi_twi_irq_cb_t cb, void *arg) -{ - size_t num = _spi_dev2num(bus); - mutex_lock(&_locks[num]); - _irq[num] = cb; - _irq_arg[num] = arg; -} - -void nrf5x_i2c_release(NRF_TWIM_Type *bus) -{ - size_t num = _i2c_dev2num(bus); - mutex_unlock(&_locks[num]); -} - -void nrf5x_spi_release(NRF_SPIM_Type *bus) -{ - size_t num = _spi_dev2num(bus); - mutex_unlock(&_locks[num]); -} - -/* Check if UART driver doesn't already use the same IRQ */ -#ifndef UART_0_ISR -void isr_uarte0_spim0_spis0_twim0_twis0(void) -{ - _irq[0](_irq_arg[0]); - cortexm_isr_end(); -} -#endif /* ndef UART_0_ISR */ - -#ifndef UART_1_ISR -void isr_uarte1_spim1_spis1_twim1_twis1(void) -{ - _irq[1](_irq_arg[1]); - cortexm_isr_end(); -} -#endif /* ndef UART_1_ISR */ - -#ifndef UART_2_ISR -void isr_uarte2_spim2_spis2_twim2_twis2(void) -{ - _irq[2](_irq_arg[2]); - cortexm_isr_end(); -} -#endif /* ndef UART_2_ISR */ - -#ifndef UART_3_ISR -void isr_uarte3_spim3_spis3_twim3_twis3(void) -{ - _irq[3](_irq_arg[3]); - cortexm_isr_end(); -} -#endif /* ndef UART_3_ISR */