diff --git a/boards/acd52832/include/periph_conf.h b/boards/acd52832/include/periph_conf.h index f10c84fe8723..2695da1c973c 100644 --- a/boards/acd52832/include/periph_conf.h +++ b/boards/acd52832/include/periph_conf.h @@ -54,10 +54,11 @@ extern "C" { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = 4, .mosi = 3, - .miso = 13 + .miso = 13, + .ppi = 0 } }; diff --git a/boards/adafruit-clue/include/periph_conf.h b/boards/adafruit-clue/include/periph_conf.h index ecc68417ce24..0cd987c03e6f 100644 --- a/boards/adafruit-clue/include/periph_conf.h +++ b/boards/adafruit-clue/include/periph_conf.h @@ -79,13 +79,13 @@ static const i2c_conf_t i2c_config[] = { */ static const spi_conf_t spi_config[] = { { /* External connectors */ - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = GPIO_PIN(0, 23), /* D13 */ .mosi = GPIO_PIN(0, 21), /* D15 */ .miso = GPIO_PIN(0, 22), /* D14 */ }, { /* TFT LCD screen */ - .dev = NRF_SPI1, + .dev = NRF_SPIM1, .sclk = GPIO_PIN(0, 14), .mosi = GPIO_PIN(0, 15), .miso = GPIO_PIN(0, 0), diff --git a/boards/arduino-nano-33-ble/include/periph_conf.h b/boards/arduino-nano-33-ble/include/periph_conf.h index 3ec669150a8b..2d2585135220 100644 --- a/boards/arduino-nano-33-ble/include/periph_conf.h +++ b/boards/arduino-nano-33-ble/include/periph_conf.h @@ -73,7 +73,7 @@ static const i2c_conf_t i2c_config[] = { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = GPIO_PIN(0, 13), .mosi = GPIO_PIN(1, 1), .miso = GPIO_PIN(1, 8), diff --git a/boards/common/nrf52/include/cfg_spi_default.h b/boards/common/nrf52/include/cfg_spi_default.h index cfd029ca82ad..bf4ea29f5c4d 100644 --- a/boards/common/nrf52/include/cfg_spi_default.h +++ b/boards/common/nrf52/include/cfg_spi_default.h @@ -32,10 +32,13 @@ extern "C" { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = GPIO_PIN(0, 15), .mosi = GPIO_PIN(0, 13), .miso = GPIO_PIN(0, 14), +#ifdef ERRATA_SPI_SINGLE_BYTE_WORKAROUND + .ppi = 0, +#endif } }; diff --git a/boards/common/particle-mesh/include/periph_conf_common.h b/boards/common/particle-mesh/include/periph_conf_common.h index 195750eb199a..b91368e9440a 100644 --- a/boards/common/particle-mesh/include/periph_conf_common.h +++ b/boards/common/particle-mesh/include/periph_conf_common.h @@ -36,10 +36,10 @@ extern "C" { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = 15, .mosi = 13, - .miso = 14 + .miso = 14, } }; diff --git a/boards/feather-nrf52840/include/periph_conf.h b/boards/feather-nrf52840/include/periph_conf.h index 331611afcf7d..b124cd814538 100644 --- a/boards/feather-nrf52840/include/periph_conf.h +++ b/boards/feather-nrf52840/include/periph_conf.h @@ -58,10 +58,10 @@ static const uart_conf_t uart_config[] = { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = 14, .mosi = 13, - .miso = 15 + .miso = 15, } }; diff --git a/boards/nrf52840dk/include/periph_conf.h b/boards/nrf52840dk/include/periph_conf.h index fe6d7100535c..017838d7754e 100644 --- a/boards/nrf52840dk/include/periph_conf.h +++ b/boards/nrf52840dk/include/periph_conf.h @@ -32,13 +32,13 @@ extern "C" { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = GPIO_PIN(1, 15), .mosi = GPIO_PIN(1, 13), .miso = GPIO_PIN(1, 14), }, { - .dev = NRF_SPI1, + .dev = NRF_SPIM1, .sclk = GPIO_PIN(0, 19), .mosi = GPIO_PIN(0, 20), .miso = GPIO_PIN(0, 21), diff --git a/boards/nrf52dk/include/periph_conf.h b/boards/nrf52dk/include/periph_conf.h index 581f1bd9ffde..c2111f28755a 100644 --- a/boards/nrf52dk/include/periph_conf.h +++ b/boards/nrf52dk/include/periph_conf.h @@ -34,10 +34,11 @@ extern "C" { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = GPIO_PIN(0, 25), .mosi = GPIO_PIN(0, 23), .miso = GPIO_PIN(0, 24), + .ppi = 0, } }; #define SPI_NUMOF ARRAY_SIZE(spi_config) diff --git a/boards/pinetime/include/periph_conf.h b/boards/pinetime/include/periph_conf.h index edba42601862..1066d67a5286 100644 --- a/boards/pinetime/include/periph_conf.h +++ b/boards/pinetime/include/periph_conf.h @@ -37,10 +37,11 @@ extern "C" { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = GPIO_PIN(0, 2), .mosi = GPIO_PIN(0, 3), .miso = GPIO_PIN(0, 4), + .ppi = 0, } }; diff --git a/boards/reel/include/periph_conf.h b/boards/reel/include/periph_conf.h index ddee61cb51b8..fbe1f41d6d41 100644 --- a/boards/reel/include/periph_conf.h +++ b/boards/reel/include/periph_conf.h @@ -58,7 +58,7 @@ static const uart_conf_t uart_config[] = { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = GPIO_PIN(0, 19), .mosi = GPIO_PIN(0, 20), .miso = GPIO_PIN(0, 21), diff --git a/boards/ruuvitag/include/periph_conf.h b/boards/ruuvitag/include/periph_conf.h index 980bcca34afe..a4bc2ac2106b 100644 --- a/boards/ruuvitag/include/periph_conf.h +++ b/boards/ruuvitag/include/periph_conf.h @@ -35,10 +35,11 @@ extern "C" { */ static const spi_conf_t spi_config[] = { { - .dev = NRF_SPI0, + .dev = NRF_SPIM0, .sclk = 29, .mosi = 25, .miso = 28, + .ppi = 0, } }; diff --git a/cpu/nrf51/include/periph_cpu.h b/cpu/nrf51/include/periph_cpu.h index b4137a993b05..79292b9469bc 100644 --- a/cpu/nrf51/include/periph_cpu.h +++ b/cpu/nrf51/include/periph_cpu.h @@ -94,6 +94,16 @@ typedef struct { i2c_speed_t speed; /**< bus speed */ } i2c_conf_t; +/** + * @brief SPI configuration values + */ +typedef struct { + NRF_SPI_Type *dev; /**< SPI device used */ + gpio_t sclk; /**< CLK pin */ + gpio_t mosi; /**< MOSI pin */ + gpio_t miso; /**< MISO pin */ +} spi_conf_t; + #ifdef __cplusplus } #endif diff --git a/cpu/nrf5x_common/periph/spi.c b/cpu/nrf51/periph/spi.c similarity index 96% rename from cpu/nrf5x_common/periph/spi.c rename to cpu/nrf51/periph/spi.c index 06958f7ee442..48fea3424bbb 100644 --- a/cpu/nrf5x_common/periph/spi.c +++ b/cpu/nrf51/periph/spi.c @@ -7,7 +7,7 @@ */ /** - * @ingroup cpu_nrf5x_common + * @ingroup cpu_nrf51 * @ingroup drivers_periph_spi * @{ * @@ -64,10 +64,8 @@ int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) (void) cs; mutex_lock(&locks[bus]); -#ifdef CPU_FAM_NRF51 /* power on the bus (NRF51 only) */ dev(bus)->POWER = 1; -#endif /* configure bus */ dev(bus)->CONFIG = mode; dev(bus)->FREQUENCY = clk; @@ -81,9 +79,7 @@ void spi_release(spi_t bus) { /* power off everything */ dev(bus)->ENABLE = 0; -#ifdef CPU_FAM_NRF51 dev(bus)->POWER = 0; -#endif mutex_unlock(&locks[bus]); } diff --git a/cpu/nrf52/Makefile.dep b/cpu/nrf52/Makefile.dep index ebf5dff9fe3a..2787f51a1b9f 100644 --- a/cpu/nrf52/Makefile.dep +++ b/cpu/nrf52/Makefile.dep @@ -5,5 +5,12 @@ ifneq (,$(filter nrf802154,$(USEMODULE))) USEMODULE += netdev_ieee802154 endif +# The nrf52832 requires gpio IRQ with SPI to work around errata 58 +ifneq (,$(filter nrf52832xxaa,$(CPU_MODEL))) + ifneq (,$(filter periph_spi,$(USEMODULE))) + FEATURES_REQUIRED += periph_gpio_irq + endif +endif + include $(RIOTCPU)/nrf5x_common/Makefile.dep include $(RIOTCPU)/cortexm_common/Makefile.dep diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h index d2e19ca81eec..5a5742324aca 100644 --- a/cpu/nrf52/include/periph_cpu.h +++ b/cpu/nrf52/include/periph_cpu.h @@ -27,6 +27,14 @@ extern "C" { #endif +/** + * @brief Enable the workaround for the SPI single byte transmit errata (No. + * 58 on the nrf52832) + */ +#ifdef CPU_MODEL_NRF52832XXAA +#define ERRATA_SPI_SINGLE_BYTE_WORKAROUND (1) +#endif + /** * @brief System core clock speed, fixed to 64MHz for all NRF52x CPUs */ @@ -54,6 +62,14 @@ extern "C" { */ #define ADC_NUMOF (9U) +/** + * @brief SPI temporary buffer size for storing const data in RAM before + * initiating DMA transfer + */ +#ifndef CONFIG_SPI_MBUF_SIZE +#define CONFIG_SPI_MBUF_SIZE 64 +#endif + /** * @brief nRF52 specific naming of ADC lines (for convenience) */ @@ -180,6 +196,46 @@ typedef struct { } uart_conf_t; #endif +/** + * @brief SPI configuration values + */ +typedef struct { + NRF_SPIM_Type *dev; /**< SPI device used */ + gpio_t sclk; /**< CLK pin */ + gpio_t mosi; /**< MOSI pin */ + gpio_t miso; /**< MISO pin */ +#if ERRATA_SPI_SINGLE_BYTE_WORKAROUND + uint8_t ppi; /**< PPI channel */ +#endif +} spi_conf_t; + + +/** + * @brief Common SPI/I2C interrupt callback + * + * @param arg Opaque context pointer + */ +typedef void (*spi_twi_irq_cb_t)(void *arg); + +/** + * @brief Reqister a SPI IRQ handler for a shared I2C/SPI irq vector + * + * @param bus bus to register the IRQ handler on + * @param cb callback to call on IRQ + * @param arg Argument to pass to the handler + */ +void spi_twi_irq_register_spi(NRF_SPIM_Type *bus, + spi_twi_irq_cb_t cb, void *arg); + +/** + * @brief Reqister a I2C IRQ handler for a shared I2C/SPI irq vector + * + * @param bus bus to register the IRQ handler on + * @param cb callback to call on IRQ + * @param arg Argument to pass to the handler + */ +void spi_twi_irq_register_i2c(NRF_TWIM_Type *bus, + spi_twi_irq_cb_t cb, void *arg); #ifdef __cplusplus } #endif diff --git a/cpu/nrf52/periph/spi.c b/cpu/nrf52/periph/spi.c new file mode 100644 index 000000000000..9376409b3703 --- /dev/null +++ b/cpu/nrf52/periph/spi.c @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2014-2016 Freie Universität Berlin + * Copyright (C) 2020 Inria + * Copyright (C) 2020 Koen Zandberg + * + * 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_nrf52 + * @ingroup drivers_periph_spi + * @{ + * + * @file + * @brief Low-level SPI driver implementation based on the SPIM peripheral + * + * @author Hauke Petersen + * @author Frank Holtz + * @author Jan Wagner + * @author Koen Zandberg + * + * @} + */ + +#include "cpu.h" +#include "mutex.h" +#include "assert.h" +#include "periph/spi.h" +#include "periph/gpio.h" +#include "periph_cpu.h" +#include + +#define RAM_MASK (0x20000000) + +/** + * @brief array holding one pre-initialized mutex for each SPI device + */ +static mutex_t locks[SPI_NUMOF]; + +/** + * @brief array with a busy mutex for each SPI device, used to block the + * thread until the transfer is done + */ +static mutex_t busy[SPI_NUMOF]; + +static uint8_t _mbuf[SPI_NUMOF][CONFIG_SPI_MBUF_SIZE]; + +static void spi_isr_handler(void *arg); + +static inline NRF_SPIM_Type *dev(spi_t bus) +{ + return (NRF_SPIM_Type *)spi_config[bus].dev; +} + +static inline bool _in_ram(const uint8_t *data) +{ + return ((uint32_t)data & RAM_MASK); +} + +#ifdef ERRATA_SPI_SINGLE_BYTE_WORKAROUND +void spi_gpio_handler(void *arg) +{ + spi_t bus = (spi_t)arg; + + /** + * Immediately disable the IRQ, we only care about one PPI event per + * transfer + */ + gpio_irq_disable(spi_config[bus].sclk); +} +#endif + +/** + * @brief Work-around for transmitting 1 byte with SPIM on the nrf52832. + * @warning Must not be used when transmitting multiple bytes. + * @warning After this workaround is used, the user must reset the PPI channel + * and the GPIOTE channel before attempting to transmit multiple bytes. + * + * @param bus The SPI instance that is in use. + */ +static void _setup_workaround_for_ftpan_58(spi_t bus) +{ +#ifdef ERRATA_SPI_SINGLE_BYTE_WORKAROUND + gpio_init_int(spi_config[bus].sclk, GPIO_OUT, GPIO_BOTH, + spi_gpio_handler, (void *)bus); + gpio_irq_disable(spi_config[bus].sclk); + uint8_t channel = gpio_int_get_exti(spi_config[bus].sclk); + assert(channel != 0xff); + + // Stop the spim instance when SCK toggles. + NRF_PPI->CH[spi_config[bus].ppi].EEP = + (uint32_t)&NRF_GPIOTE->EVENTS_IN[channel]; + NRF_PPI->CH[spi_config[bus].ppi].TEP = (uint32_t)&dev(bus)->TASKS_STOP; +#else + (void)bus; +#endif +} + +static void _enable_workaround(spi_t bus) +{ +#ifdef ERRATA_SPI_SINGLE_BYTE_WORKAROUND + /** + * The spim instance cannot be stopped mid-byte, so it will finish + * transmitting the first byte and then stop. Effectively ensuring + * that only 1 byte is transmitted. + */ + NRF_PPI->CHENSET = 1U << spi_config[bus].ppi; + gpio_irq_enable(spi_config[bus].sclk); +#else + (void)bus; +#endif +} + +static void _clear_workaround(spi_t bus) +{ +#ifdef ERRATA_SPI_SINGLE_BYTE_WORKAROUND + NRF_PPI->CHENCLR = 1U << spi_config[bus].ppi; +#else + (void)bus; +#endif +} + +void spi_init(spi_t bus) +{ + assert(bus < SPI_NUMOF); + + /* initialize mutex */ + mutex_init(&locks[bus]); + mutex_init(&busy[bus]); + mutex_lock(&busy[bus]); + /* initialize pins */ + spi_init_pins(bus); +} + +void spi_init_pins(spi_t bus) +{ + gpio_init(spi_config[bus].sclk, GPIO_OUT); + gpio_init(spi_config[bus].mosi, GPIO_OUT); + gpio_init(spi_config[bus].miso, GPIO_IN); + /* select pins for the SPI device */ + SPI_SCKSEL = spi_config[bus].sclk; + SPI_MOSISEL = spi_config[bus].mosi; + SPI_MISOSEL = spi_config[bus].miso; + _setup_workaround_for_ftpan_58(bus); + spi_twi_irq_register_spi(dev(bus), spi_isr_handler, (void *)bus); +} + +int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) +{ + (void)cs; + + mutex_lock(&locks[bus]); + /* configure bus */ + dev(bus)->CONFIG = mode; + dev(bus)->FREQUENCY = clk; + /* enable the bus */ + dev(bus)->ENABLE = SPIM_ENABLE_ENABLE_Enabled; + + return SPI_OK; +} + +void spi_release(spi_t bus) +{ + /* power off everything */ + dev(bus)->ENABLE = 0; + mutex_unlock(&locks[bus]); +} + +static size_t _transfer(spi_t bus, const uint8_t *out_buf, uint8_t *in_buf, + size_t remaining_len) +{ + uint8_t transfer_len = remaining_len > UINT8_MAX ? UINT8_MAX : remaining_len; + const uint8_t *out_mbuf = out_buf; + + /** + * Copy the out buffer in case it resides in flash, EasyDMA only works from + * RAM + */ + if (out_buf && !_in_ram(out_buf)) { + /* The SPI MBUF can be smaller than UINT8_MAX */ + transfer_len = transfer_len > CONFIG_SPI_MBUF_SIZE + ? CONFIG_SPI_MBUF_SIZE : transfer_len; + memcpy(_mbuf[bus], out_buf, transfer_len); + out_mbuf = _mbuf[bus]; + } + + uint8_t out_len = (out_buf) ? transfer_len : 0; + uint8_t in_len = (in_buf) ? transfer_len : 0; + + dev(bus)->TXD.PTR = (uint32_t)out_mbuf; + dev(bus)->RXD.PTR = (uint32_t)in_buf; + + dev(bus)->TXD.MAXCNT = out_len; + dev(bus)->RXD.MAXCNT = in_len; + + /* clear any spurious END events */ + dev(bus)->EVENTS_END = 0; + dev(bus)->TASKS_START = 1; + return transfer_len; +} + +void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, + const void *out, void *in, size_t len) +{ + const uint8_t *out_buf = out; + uint8_t *in_buf = in; + + assert(out_buf || in_buf); + + if (cs != SPI_CS_UNDEF) { + gpio_clear((gpio_t)cs); + } + + /* Enable the workaround when the length is only 1 byte */ + size_t _len = len; + if (_len == 1) { + _enable_workaround(bus); + } + + /* Enable IRQ */ + dev(bus)->INTENSET = SPIM_INTENSET_END_Msk; + + do { + size_t transfer_len = _transfer(bus, out_buf, in_buf, len); + /* Block until the irq releases the mutex, then lock it again for the + * next transfer */ + mutex_lock(&busy[bus]); + out_buf += out_buf ? transfer_len : 0; + in_buf += in_buf ? transfer_len : 0; + len -= transfer_len; + } while (len); + + /* Disable IRQ */ + dev(bus)->INTENCLR = SPIM_INTENCLR_END_Msk; + + /** + * While we could always disable the workaround, only doing this when + * required spares us some cycles by not having to write to volatile + * registers + */ + if (_len == 1) { + _clear_workaround(bus); + } + + if ((cs != SPI_CS_UNDEF) && (!cont)) { + gpio_set((gpio_t)cs); + } +} + +void spi_isr_handler(void *arg) +{ + spi_t bus = (spi_t)arg; + + mutex_unlock(&busy[bus]); + dev(bus)->EVENTS_END = 0; +} diff --git a/cpu/nrf52/spi_twi_irq.c b/cpu/nrf52/spi_twi_irq.c new file mode 100644 index 000000000000..eff84dbb1d85 --- /dev/null +++ b/cpu/nrf52/spi_twi_irq.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2020 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 cpu_nrf52 + * @{ + * + * @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 Koen Zandberg + * + * @} + */ + +#include "cpu.h" +#include "periph_cpu.h" + +/* nRF52811 ISR names */ +#if defined(CPU_MODEL_NRF52811XXAA) + +#define ISR_SPIM0 isr_spi0 +#define ISR_SPIM1 isr_spi1_twi0 + +/* nRF52832 and nRF52840 ISR names */ +#elif (defined(CPU_MODEL_NRF52840XXAA) || defined(CPU_MODEL_NRF52832XXAA)) + +#define ISR_SPIM0 isr_spi0_twi0 +#define ISR_SPIM1 isr_spi1_twi1 + +#else +#error Unknown nrf52 MCU model +#endif + +static spi_twi_irq_cb_t _irq[SPIM_COUNT]; +static void *_irq_arg[SPIM_COUNT]; + +/* I2C and SPI share peripheral addresses */ +static size_t _spi_dev2num(void *dev) +{ + if (dev == NRF_SPIM0) { + return 0; + } + else if (dev == NRF_SPIM1) { + return 1; + } +#ifdef NRF_SPIM2 + else if (dev == NRF_SPIM2) { + return 2; + } +#endif /* NRF_SPIM2 */ +#ifdef NRF_SPIM3 + else if (dev == NRF_SPIM3) { + return 3; + } +#endif /* NRF_SPIM3 */ + else { + assert(false); + return 0; + } +} + +static inline size_t _i2c_dev2num(void *dev) +{ + return _spi_dev2num(dev); +} + +static const IRQn_Type _isr[] = { + SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, + +#ifdef CPU_MODEL_NRF52811XXAA + TWIM0_TWIS0_TWI0_SPIM1_SPIS1_SPI1_IRQn, +#else + SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn, +#endif + +#ifdef NRF_SPIM2 + SPIM2_SPIS2_SPI2_IRQn, +#endif +#ifdef NRF_SPIM3 + SPIM3_IRQn, +#endif /* CPU_MODEL_NRF52840XXAA */ +}; + +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 ISR_SPIM0(void) +{ + _irq[0](_irq_arg[0]); + cortexm_isr_end(); +} + +void ISR_SPIM1(void) +{ + _irq[1](_irq_arg[1]); + cortexm_isr_end(); +} + +#ifdef NRF_SPIM2 +void isr_spi2(void) +{ + _irq[2](_irq_arg[2]); + cortexm_isr_end(); +} +#endif + +#ifdef NRF_SPIM3 +void isr_spi3(void) +{ + _irq[3](_irq_arg[3]); + cortexm_isr_end(); +} +#endif /* NRF_SPIM3 */ diff --git a/cpu/nrf5x_common/include/periph_cpu_common.h b/cpu/nrf5x_common/include/periph_cpu_common.h index ce12170c5eb7..a467eed50dc8 100644 --- a/cpu/nrf5x_common/include/periph_cpu_common.h +++ b/cpu/nrf5x_common/include/periph_cpu_common.h @@ -165,16 +165,6 @@ typedef enum { /** @} */ #endif /* ndef DOXYGEN */ -/** - * @brief SPI configuration values - */ -typedef struct { - NRF_SPI_Type *dev; /**< SPI device used */ - gpio_t sclk; /**< CLK pin */ - gpio_t mosi; /**< MOSI pin */ - gpio_t miso; /**< MISO pin */ -} spi_conf_t; - /** * @name WDT upper and lower bound times in ms * @{ @@ -184,6 +174,16 @@ typedef struct { #define NWDT_TIME_UPPER_LIMIT ((UINT32_MAX >> 15) * US_PER_MS + 1) /** @} */ +/** + * @brief Retrieve the exti(GPIOTE) channel associated with a gpio + * + * @param pin GPIO pin to retrieve the channel for + * + * @return the channel number + * @return 0xff if no channel is found + */ +uint8_t gpio_int_get_exti(gpio_t pin); + #ifdef __cplusplus } #endif diff --git a/cpu/nrf5x_common/periph/gpio.c b/cpu/nrf5x_common/periph/gpio.c index f53a773e5c15..208f76c0592f 100644 --- a/cpu/nrf5x_common/periph/gpio.c +++ b/cpu/nrf5x_common/periph/gpio.c @@ -146,17 +146,21 @@ void gpio_write(gpio_t pin, int value) } #ifdef MODULE_PERIPH_GPIO_IRQ -int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, - gpio_cb_t cb, void *arg) +uint8_t gpio_int_get_exti(gpio_t pin) { - uint8_t _pin_index = 0xff; /* Looking for already known pin in exti table */ for (unsigned int i = 0; i < _gpiote_next_index; i++) { if (_exti_pins[i] == pin) { - _pin_index = i; - break; + return i; } } + return 0xff; +} + +int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, + gpio_cb_t cb, void *arg) +{ + uint8_t _pin_index = gpio_int_get_exti(pin); /* New pin */ if (_pin_index == 0xff) {