diff --git a/boards/nrf9160dk/Kconfig b/boards/nrf9160dk/Kconfig index 055ce2813f89..ac242952d2bc 100644 --- a/boards/nrf9160dk/Kconfig +++ b/boards/nrf9160dk/Kconfig @@ -11,5 +11,7 @@ config BOARD_NRF9160DK bool default y select CPU_MODEL_NRF9160 + select HAS_PERIPH_I2C + select HAS_PERIPH_SPI select HAS_PERIPH_TIMER select HAS_PERIPH_UART diff --git a/boards/nrf9160dk/Makefile.features b/boards/nrf9160dk/Makefile.features index 614e821745b0..d26460513e1c 100644 --- a/boards/nrf9160dk/Makefile.features +++ b/boards/nrf9160dk/Makefile.features @@ -2,5 +2,7 @@ CPU_MODEL = nrf9160 CPU = nrf9160 # Put defined MCU peripherals here (in alphabetical order) +FEATURES_PROVIDED += periph_i2c +FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart diff --git a/boards/nrf9160dk/include/periph_conf.h b/boards/nrf9160dk/include/periph_conf.h index 720988d9a818..af6381cf4909 100644 --- a/boards/nrf9160dk/include/periph_conf.h +++ b/boards/nrf9160dk/include/periph_conf.h @@ -28,6 +28,37 @@ extern "C" { #endif +/** + * @name I2C configuration + * @{ + */ +static const i2c_conf_t i2c_config[] = { + { + .dev = NRF_TWIM3_S, + .scl = GPIO_PIN(0, 31), + .sda = GPIO_PIN(0, 30), + .speed = I2C_SPEED_NORMAL + } +}; +#define I2C_NUMOF ARRAY_SIZE(i2c_config) +/** @} */ + +/** + * @name SPI configuration + * @{ + */ +static const spi_conf_t spi_config[] = { + { + .dev = NRF_SPIM2_S, + .sclk = GPIO_PIN(0, 13), + .mosi = GPIO_PIN(0, 11), + .miso = GPIO_PIN(0, 12), + } +}; + +#define SPI_NUMOF ARRAY_SIZE(spi_config) +/** @} */ + /** * @name Timer configuration * @{ diff --git a/cpu/nrf5x_common/periph/Makefile b/cpu/nrf5x_common/periph/Makefile index d6d99b059d21..d297d3c6790f 100644 --- a/cpu/nrf5x_common/periph/Makefile +++ b/cpu/nrf5x_common/periph/Makefile @@ -1,3 +1,17 @@ MODULE = nrf5x_common_periph +# Select the specific implementation for `periph_i2c` +ifneq (,$(filter periph_i2c,$(USEMODULE))) + ifneq (,$(filter $(CPU_FAM),nrf52 nrf9160)) + SRC += i2c_nrf52_nrf9160.c + endif +endif + +# Select the specific implementation for `periph_spi` +ifneq (,$(filter periph_spi,$(USEMODULE))) + ifneq (,$(filter $(CPU_FAM),nrf52 nrf9160)) + SRC += spi_nrf52_nrf9160.c + endif +endif + include $(RIOTMAKE)/periph.mk diff --git a/cpu/nrf52/periph/i2c.c b/cpu/nrf5x_common/periph/i2c_nrf52_nrf9160.c similarity index 99% rename from cpu/nrf52/periph/i2c.c rename to cpu/nrf5x_common/periph/i2c_nrf52_nrf9160.c index fffa535115a2..9b77127d0337 100644 --- a/cpu/nrf52/periph/i2c.c +++ b/cpu/nrf5x_common/periph/i2c_nrf52_nrf9160.c @@ -9,7 +9,7 @@ */ /** - * @ingroup cpu_nrf52 + * @ingroup cpu_nrf5x_common * @{ * * @file diff --git a/cpu/nrf52/periph/spi.c b/cpu/nrf5x_common/periph/spi_nrf52_nrf9160.c similarity index 99% rename from cpu/nrf52/periph/spi.c rename to cpu/nrf5x_common/periph/spi_nrf52_nrf9160.c index 3482d5ae176a..97d902b886a5 100644 --- a/cpu/nrf52/periph/spi.c +++ b/cpu/nrf5x_common/periph/spi_nrf52_nrf9160.c @@ -9,7 +9,7 @@ */ /** - * @ingroup cpu_nrf52 + * @ingroup cpu_nrf5x_common * @ingroup drivers_periph_spi * @{ * diff --git a/cpu/nrf9160/include/periph_cpu.h b/cpu/nrf9160/include/periph_cpu.h index 2f21a8ed3334..a0576bc217f7 100644 --- a/cpu/nrf9160/include/periph_cpu.h +++ b/cpu/nrf9160/include/periph_cpu.h @@ -81,7 +81,133 @@ typedef struct { #define UART_BAUDRATE_BAUDRATE_Baud460800 UARTE_BAUDRATE_BAUDRATE_Baud460800 #define UART_BAUDRATE_BAUDRATE_Baud921600 UARTE_BAUDRATE_BAUDRATE_Baud921600 #define UART_BAUDRATE_BAUDRATE_Baud1M UARTE_BAUDRATE_BAUDRATE_Baud1M + +/** + * @brief Override I2C speed settings + * @{ + */ +#define HAVE_I2C_SPEED_T +typedef enum { + I2C_SPEED_LOW = 0xff, /**< not supported */ + I2C_SPEED_NORMAL = TWIM_FREQUENCY_FREQUENCY_K100, /**< 100kbit/s */ + I2C_SPEED_FAST = TWIM_FREQUENCY_FREQUENCY_K400, /**< 400kbit/s */ + I2C_SPEED_FAST_PLUS = 0xfe, /**< not supported */ + I2C_SPEED_HIGH = 0xfd, /**< not supported */ +} i2c_speed_t; +/** @} */ + #endif /* ndef DOXYGEN */ + +/** + * @brief I2C (TWI) configuration options + */ +typedef struct { + NRF_TWIM_Type *dev; /**< TWIM hardware device */ + gpio_t scl; /**< SCL pin */ + gpio_t sda; /**< SDA pin */ + i2c_speed_t speed; /**< Bus speed */ +} i2c_conf_t; +/** @} */ + +/** + * @name Use shared I2C functions + * @{ + */ +#define PERIPH_I2C_NEED_READ_REG +#define PERIPH_I2C_NEED_WRITE_REG +/** @} */ + +/** + * @name Define macros for sda and scl pin to be able to reinitialize them + * @{ + */ +#define i2c_pin_sda(dev) i2c_config[dev].sda +#define i2c_pin_scl(dev) i2c_config[dev].scl +/** @} */ + +/** + * @brief Defines macros for SPI pins initialization + * @{ + */ +#define SPI_SCKSEL (dev(bus)->PSEL.SCK) +#define SPI_MOSISEL (dev(bus)->PSEL.MOSI) +#define SPI_MISOSEL (dev(bus)->PSEL.MISO) +/** @} */ + +/** + * @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 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 */ +} spi_conf_t; + +#ifndef DOXYGEN +/** + * @brief Override SPI mode values + * @{ + */ +#define HAVE_SPI_MODE_T +typedef enum { + SPI_MODE_0 = 0, /**< CPOL=0, CPHA=0 */ + SPI_MODE_1 = SPIM_CONFIG_CPHA_Msk, /**< CPOL=0, CPHA=1 */ + SPI_MODE_2 = SPIM_CONFIG_CPOL_Msk, /**< CPOL=1, CPHA=0 */ + SPI_MODE_3 = (SPIM_CONFIG_CPOL_Msk | SPIM_CONFIG_CPHA_Msk) /**< CPOL=1, CPHA=1 */ +} spi_mode_t; +/** @} */ + +/** + * @brief Override SPI clock values + * @{ + */ +#define HAVE_SPI_CLK_T +typedef enum { + SPI_CLK_100KHZ = SPIM_FREQUENCY_FREQUENCY_K125, /**< 100KHz */ + SPI_CLK_400KHZ = SPIM_FREQUENCY_FREQUENCY_K500, /**< 400KHz */ + SPI_CLK_1MHZ = SPIM_FREQUENCY_FREQUENCY_M1, /**< 1MHz */ + SPI_CLK_5MHZ = SPIM_FREQUENCY_FREQUENCY_M4, /**< 5MHz */ + SPI_CLK_10MHZ = SPIM_FREQUENCY_FREQUENCY_M8 /**< 10MHz */ +} spi_clk_t; +/** @} */ +#endif /* ndef DOXYGEN */ + +/** + * @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/nrf9160/spi_twi_irq.c b/cpu/nrf9160/spi_twi_irq.c new file mode 100644 index 000000000000..8aad154a9f38 --- /dev/null +++ b/cpu/nrf9160/spi_twi_irq.c @@ -0,0 +1,122 @@ +/* + * 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 "periph_cpu.h" +#include "periph_conf.h" + +static spi_twi_irq_cb_t _irq[TWIM_COUNT]; +static void *_irq_arg[TWIM_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]); +} + +/* 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 */ diff --git a/pkg/mynewt-core/contrib/Makefile b/pkg/mynewt-core/contrib/Makefile index 0bb65a903ff0..c16f097dad58 100644 --- a/pkg/mynewt-core/contrib/Makefile +++ b/pkg/mynewt-core/contrib/Makefile @@ -3,7 +3,7 @@ MODULE = mynewt-core # exclude submodule sources from *.c wildcard source selection SRC := $(filter-out nrf5x_isr.c cputime.c,$(wildcard *.c)) -ifneq (,$(filter nrf%,$(CPU))) +ifneq (,$(filter nrf5%,$(CPU))) SRC += nrf5x_isr.c else SRC += cputime.c diff --git a/pkg/mynewt-core/mynewt-core_os.mk b/pkg/mynewt-core/mynewt-core_os.mk index 8077bdeabe9e..6bfbccbb1b53 100644 --- a/pkg/mynewt-core/mynewt-core_os.mk +++ b/pkg/mynewt-core/mynewt-core_os.mk @@ -8,7 +8,7 @@ SRC := \ os_cputime_pwr2.c \ # -ifneq (,$(filter nrf%,$(CPU))) +ifneq (,$(filter nrf5%,$(CPU))) SRC += os_cputime.c endif diff --git a/pkg/uwb-core/Makefile.dep b/pkg/uwb-core/Makefile.dep index b4f0c0355a93..fd59855a7a8d 100644 --- a/pkg/uwb-core/Makefile.dep +++ b/pkg/uwb-core/Makefile.dep @@ -25,7 +25,7 @@ endif ifneq (,$(filter uwb-core_dpl,$(USEMODULE))) USEPKG += mynewt-core USEMODULE += mynewt-core_os - ifneq (,$(filter nrf%,$(CPU))) + ifneq (,$(filter nrf5%,$(CPU))) USEMODULE += mynewt-core_nrf5x_hal endif endif