Skip to content

Commit

Permalink
Merge pull request #16814 from dylad/pr/cpu/nrf9160_add_twi_and_spi_s…
Browse files Browse the repository at this point in the history
…upport

cpu/nrf9160: add twi and spi support
  • Loading branch information
benpicco authored Sep 8, 2021
2 parents f65f3c7 + 633ddee commit bcaaaec
Show file tree
Hide file tree
Showing 11 changed files with 302 additions and 5 deletions.
2 changes: 2 additions & 0 deletions boards/nrf9160dk/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions boards/nrf9160dk/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -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
31 changes: 31 additions & 0 deletions boards/nrf9160dk/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
* @{
Expand Down
14 changes: 14 additions & 0 deletions cpu/nrf5x_common/periph/Makefile
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

/**
* @ingroup cpu_nrf52
* @ingroup cpu_nrf5x_common
* @{
*
* @file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

/**
* @ingroup cpu_nrf52
* @ingroup cpu_nrf5x_common
* @ingroup drivers_periph_spi
* @{
*
Expand Down
126 changes: 126 additions & 0 deletions cpu/nrf9160/include/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
122 changes: 122 additions & 0 deletions cpu/nrf9160/spi_twi_irq.c
Original file line number Diff line number Diff line change
@@ -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 <dylan.laduranty@mesotic.com>
*
* @}
*/

#include <assert.h>

#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 */
2 changes: 1 addition & 1 deletion pkg/mynewt-core/contrib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pkg/mynewt-core/mynewt-core_os.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ SRC := \
os_cputime_pwr2.c \
#

ifneq (,$(filter nrf%,$(CPU)))
ifneq (,$(filter nrf5%,$(CPU)))
SRC += os_cputime.c
endif

Expand Down
2 changes: 1 addition & 1 deletion pkg/uwb-core/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit bcaaaec

Please sign in to comment.