cpu/nrf9160: add TWI and SPI support
This commit is contained in:
parent
a59974cf69
commit
1beda0f1e4
@ -1,3 +1,17 @@
|
|||||||
MODULE = nrf5x_common_periph
|
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
|
include $(RIOTMAKE)/periph.mk
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup cpu_nrf52
|
* @ingroup cpu_nrf5x_common
|
||||||
* @{
|
* @{
|
||||||
*
|
*
|
||||||
* @file
|
* @file
|
||||||
@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup cpu_nrf52
|
* @ingroup cpu_nrf5x_common
|
||||||
* @ingroup drivers_periph_spi
|
* @ingroup drivers_periph_spi
|
||||||
* @{
|
* @{
|
||||||
*
|
*
|
||||||
@ -81,7 +81,133 @@ typedef struct {
|
|||||||
#define UART_BAUDRATE_BAUDRATE_Baud460800 UARTE_BAUDRATE_BAUDRATE_Baud460800
|
#define UART_BAUDRATE_BAUDRATE_Baud460800 UARTE_BAUDRATE_BAUDRATE_Baud460800
|
||||||
#define UART_BAUDRATE_BAUDRATE_Baud921600 UARTE_BAUDRATE_BAUDRATE_Baud921600
|
#define UART_BAUDRATE_BAUDRATE_Baud921600 UARTE_BAUDRATE_BAUDRATE_Baud921600
|
||||||
#define UART_BAUDRATE_BAUDRATE_Baud1M UARTE_BAUDRATE_BAUDRATE_Baud1M
|
#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 */
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
122
cpu/nrf9160/spi_twi_irq.c
Normal file
122
cpu/nrf9160/spi_twi_irq.c
Normal file
@ -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 */
|
||||||
Loading…
x
Reference in New Issue
Block a user