mirror of https://github.com/ARMmbed/mbed-os.git
[HAL][NRF51822] enable I/O mapping and peripheral dynamic assignment for I2C and SPI
parent
3e4e9ade0d
commit
d00caad8c9
55
libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/i2c_api.c
Normal file → Executable file
55
libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/i2c_api.c
Normal file → Executable file
|
@ -17,18 +17,13 @@
|
||||||
#include "i2c_api.h"
|
#include "i2c_api.h"
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
|
#include "mbed_error.h"
|
||||||
|
|
||||||
static const PinMap PinMap_I2C_SDA[] = {
|
// nRF51822's I2C_0 and SPI_0 (I2C_1, SPI_1 and SPIS1) share the same address.
|
||||||
{p22, I2C_0, 1},
|
// They can't be used at the same time. So we use two global variable to track the usage.
|
||||||
{p13, I2C_1, 2},
|
// See nRF51822 address information at nRF51822_PS v2.0.pdf - Table 15 Peripheral instance reference
|
||||||
{NC, NC, 0}
|
volatile i2c_spi_peripheral_t i2c0_spi0_peripheral = {0, 0, 0, 0};
|
||||||
};
|
volatile i2c_spi_peripheral_t i2c1_spi1_peripheral = {0, 0, 0, 0};
|
||||||
|
|
||||||
static const PinMap PinMap_I2C_SCL[] = {
|
|
||||||
{p20, I2C_0, 1},
|
|
||||||
{p15, I2C_1, 2},
|
|
||||||
{NC, NC, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
void i2c_interface_enable(i2c_t *obj)
|
void i2c_interface_enable(i2c_t *obj)
|
||||||
{
|
{
|
||||||
|
@ -58,14 +53,40 @@ void twi_master_init(i2c_t *obj, PinName sda, PinName scl, int frequency)
|
||||||
|
|
||||||
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
||||||
{
|
{
|
||||||
// determine the SPI to use
|
NRF_TWI_Type *i2c;
|
||||||
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
|
|
||||||
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
|
|
||||||
I2CName i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
|
|
||||||
obj->i2c = (NRF_TWI_Type *)i2c;
|
|
||||||
|
|
||||||
MBED_ASSERT((int)obj->i2c != NC);
|
if (i2c0_spi0_peripheral.usage == I2C_SPI_PERIPHERAL_FOR_I2C &&
|
||||||
|
i2c0_spi0_peripheral.sda_mosi == (uint8_t)sda &&
|
||||||
|
i2c0_spi0_peripheral.scl_miso == (uint8_t)scl) {
|
||||||
|
// The I2C with the same pins is already initialized
|
||||||
|
i2c = (NRF_TWI_Type *)I2C_0;
|
||||||
|
obj->peripheral = 0x1;
|
||||||
|
} else if (i2c1_spi1_peripheral.usage == I2C_SPI_PERIPHERAL_FOR_I2C &&
|
||||||
|
i2c1_spi1_peripheral.sda_mosi == (uint8_t)sda &&
|
||||||
|
i2c1_spi1_peripheral.scl_miso == (uint8_t)scl) {
|
||||||
|
// The I2C with the same pins is already initialized
|
||||||
|
i2c = (NRF_TWI_Type *)I2C_1;
|
||||||
|
obj->peripheral = 0x2;
|
||||||
|
} else if (i2c0_spi0_peripheral.usage == 0) {
|
||||||
|
i2c0_spi0_peripheral.usage = I2C_SPI_PERIPHERAL_FOR_I2C;
|
||||||
|
i2c0_spi0_peripheral.sda_mosi = (uint8_t)sda;
|
||||||
|
i2c0_spi0_peripheral.scl_miso = (uint8_t)scl;
|
||||||
|
|
||||||
|
i2c = (NRF_TWI_Type *)I2C_0;
|
||||||
|
obj->peripheral = 0x1;
|
||||||
|
} else if (i2c1_spi1_peripheral.usage == 0) {
|
||||||
|
i2c1_spi1_peripheral.usage = I2C_SPI_PERIPHERAL_FOR_I2C;
|
||||||
|
i2c1_spi1_peripheral.sda_mosi = (uint8_t)sda;
|
||||||
|
i2c1_spi1_peripheral.scl_miso = (uint8_t)scl;
|
||||||
|
|
||||||
|
i2c = (NRF_TWI_Type *)I2C_1;
|
||||||
|
obj->peripheral = 0x2;
|
||||||
|
} else {
|
||||||
|
// No available peripheral
|
||||||
|
error("No available I2C");
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->i2c = i2c;
|
||||||
obj->scl = scl;
|
obj->scl = scl;
|
||||||
obj->sda = sda;
|
obj->sda = sda;
|
||||||
obj->i2c->EVENTS_ERROR = 0;
|
obj->i2c->EVENTS_ERROR = 0;
|
||||||
|
|
12
libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/objects.h
Normal file → Executable file
12
libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/objects.h
Normal file → Executable file
|
@ -25,6 +25,16 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define I2C_SPI_PERIPHERAL_FOR_I2C 1
|
||||||
|
#define I2C_SPI_PERIPHERAL_FOR_SPI 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t usage; // I2C: 1, SPI: 2
|
||||||
|
uint8_t sda_mosi;
|
||||||
|
uint8_t scl_miso;
|
||||||
|
uint8_t sclk;
|
||||||
|
} i2c_spi_peripheral_t;
|
||||||
|
|
||||||
struct serial_s {
|
struct serial_s {
|
||||||
NRF_UART_Type *uart;
|
NRF_UART_Type *uart;
|
||||||
int index;
|
int index;
|
||||||
|
@ -33,6 +43,7 @@ struct serial_s {
|
||||||
struct spi_s {
|
struct spi_s {
|
||||||
NRF_SPI_Type *spi;
|
NRF_SPI_Type *spi;
|
||||||
NRF_SPIS_Type *spis;
|
NRF_SPIS_Type *spis;
|
||||||
|
uint8_t peripheral;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct port_s {
|
struct port_s {
|
||||||
|
@ -54,6 +65,7 @@ struct i2c_s {
|
||||||
PinName scl;
|
PinName scl;
|
||||||
int freq;
|
int freq;
|
||||||
uint8_t address_set;
|
uint8_t address_set;
|
||||||
|
uint8_t peripheral;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct analogin_s {
|
struct analogin_s {
|
||||||
|
|
81
libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/spi_api.c
Normal file → Executable file
81
libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/spi_api.c
Normal file → Executable file
|
@ -20,48 +20,55 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "mbed_error.h"
|
#include "mbed_error.h"
|
||||||
|
|
||||||
static const PinMap PinMap_SPI_SCLK[] = {
|
|
||||||
{SPI_PSELSCK0, SPI_0, 0x01},
|
|
||||||
{SPI_PSELSCK1, SPI_1, 0x02},
|
|
||||||
{SPIS_PSELSCK, SPIS, 0x03},
|
|
||||||
{NC, NC, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_SPI_MOSI[] = {
|
|
||||||
{SPI_PSELMOSI0, SPI_0, 0x01},
|
|
||||||
{SPI_PSELMOSI1, SPI_1, 0x02},
|
|
||||||
{SPIS_PSELMOSI, SPIS, 0x03},
|
|
||||||
{NC, NC, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_SPI_MISO[] = {
|
|
||||||
{SPI_PSELMISO0, SPI_0, 0x01},
|
|
||||||
{SPI_PSELMISO1, SPI_1, 0x02},
|
|
||||||
{SPIS_PSELMISO, SPIS, 0x03},
|
|
||||||
{NC, NC, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_SPI_SSEL[] = {
|
|
||||||
{SPIS_PSELSS, SPIS, 0x03},
|
|
||||||
{NC, NC, 0}
|
|
||||||
};
|
|
||||||
// {SPI_PSELSS0 , SPI_0, 0x01},
|
|
||||||
#define SPIS_MESSAGE_SIZE 1
|
#define SPIS_MESSAGE_SIZE 1
|
||||||
volatile uint8_t m_tx_buf[SPIS_MESSAGE_SIZE] = {0};
|
volatile uint8_t m_tx_buf[SPIS_MESSAGE_SIZE] = {0};
|
||||||
volatile uint8_t m_rx_buf[SPIS_MESSAGE_SIZE] = {0};
|
volatile uint8_t m_rx_buf[SPIS_MESSAGE_SIZE] = {0};
|
||||||
|
|
||||||
|
// nRF51822's I2C_0 and SPI_0 (I2C_1, SPI_1 and SPIS1) share the same address.
|
||||||
|
// They can't be used at the same time. So we use two global variable to track the usage.
|
||||||
|
// See nRF51822 address information at nRF51822_PS v2.0.pdf - Table 15 Peripheral instance reference
|
||||||
|
extern volatile i2c_spi_peripheral_t i2c0_spi0_peripheral; // from i2c_api.c
|
||||||
|
extern volatile i2c_spi_peripheral_t i2c1_spi1_peripheral;
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
||||||
{
|
{
|
||||||
// determine the SPI to use
|
SPIName spi;
|
||||||
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
|
|
||||||
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
|
if (ssel == NC && i2c0_spi0_peripheral.usage == I2C_SPI_PERIPHERAL_FOR_SPI &&
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
i2c0_spi0_peripheral.sda_mosi == (uint8_t)mosi &&
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
i2c0_spi0_peripheral.scl_miso == (uint8_t)miso &&
|
||||||
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
|
i2c0_spi0_peripheral.sclk == (uint8_t)sclk) {
|
||||||
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
|
// The SPI with the same pins is already initialized
|
||||||
SPIName spi = (SPIName)pinmap_merge(spi_data, spi_cntl);
|
spi = SPI_0;
|
||||||
//SPIName
|
obj->peripheral = 0x1;
|
||||||
|
} else if (ssel == NC && i2c1_spi1_peripheral.usage == I2C_SPI_PERIPHERAL_FOR_SPI &&
|
||||||
|
i2c1_spi1_peripheral.sda_mosi == (uint8_t)mosi &&
|
||||||
|
i2c1_spi1_peripheral.scl_miso == (uint8_t)miso &&
|
||||||
|
i2c1_spi1_peripheral.sclk == (uint8_t)sclk) {
|
||||||
|
// The SPI with the same pins is already initialized
|
||||||
|
spi = SPI_1;
|
||||||
|
obj->peripheral = 0x2;
|
||||||
|
} else if (i2c1_spi1_peripheral.usage == 0) {
|
||||||
|
i2c1_spi1_peripheral.usage = I2C_SPI_PERIPHERAL_FOR_SPI;
|
||||||
|
i2c1_spi1_peripheral.sda_mosi = (uint8_t)mosi;
|
||||||
|
i2c1_spi1_peripheral.scl_miso = (uint8_t)miso;
|
||||||
|
i2c1_spi1_peripheral.sclk = (uint8_t)sclk;
|
||||||
|
|
||||||
|
spi = SPI_1;
|
||||||
|
obj->peripheral = 0x2;
|
||||||
|
} else if (i2c0_spi0_peripheral.usage == 0) {
|
||||||
|
i2c0_spi0_peripheral.usage = I2C_SPI_PERIPHERAL_FOR_SPI;
|
||||||
|
i2c0_spi0_peripheral.sda_mosi = (uint8_t)mosi;
|
||||||
|
i2c0_spi0_peripheral.scl_miso = (uint8_t)miso;
|
||||||
|
i2c0_spi0_peripheral.sclk = (uint8_t)sclk;
|
||||||
|
|
||||||
|
spi = SPI_0;
|
||||||
|
obj->peripheral = 0x1;
|
||||||
|
} else {
|
||||||
|
// No available peripheral
|
||||||
|
error("No available SPI");
|
||||||
|
}
|
||||||
|
|
||||||
if (ssel==NC) {
|
if (ssel==NC) {
|
||||||
obj->spi = (NRF_SPI_Type *)spi;
|
obj->spi = (NRF_SPI_Type *)spi;
|
||||||
obj->spis = (NRF_SPIS_Type *)NC;
|
obj->spis = (NRF_SPIS_Type *)NC;
|
||||||
|
@ -69,7 +76,6 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
|
||||||
obj->spi = (NRF_SPI_Type *)NC;
|
obj->spi = (NRF_SPI_Type *)NC;
|
||||||
obj->spis = (NRF_SPIS_Type *)spi;
|
obj->spis = (NRF_SPIS_Type *)spi;
|
||||||
}
|
}
|
||||||
MBED_ASSERT((int)obj->spi != NC || (int)obj->spis != NC);
|
|
||||||
|
|
||||||
// pin out the spi pins
|
// pin out the spi pins
|
||||||
if (ssel != NC) { //slave
|
if (ssel != NC) { //slave
|
||||||
|
@ -146,7 +152,8 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void spi_free(spi_t *obj) {
|
void spi_free(spi_t *obj)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void spi_disable(spi_t *obj, int slave)
|
static inline void spi_disable(spi_t *obj, int slave)
|
||||||
|
|
Loading…
Reference in New Issue