[HAL][NRF51822] enable I/O mapping and peripheral dynamic assignment for I2C and SPI

pull/662/head
Yihui Xiong 2014-11-04 17:26:32 +08:00
parent 3e4e9ade0d
commit d00caad8c9
3 changed files with 95 additions and 55 deletions

View File

@ -17,18 +17,13 @@
#include "i2c_api.h"
#include "cmsis.h"
#include "pinmap.h"
#include "mbed_error.h"
static const PinMap PinMap_I2C_SDA[] = {
{p22, I2C_0, 1},
{p13, I2C_1, 2},
{NC, NC, 0}
};
static const PinMap PinMap_I2C_SCL[] = {
{p20, I2C_0, 1},
{p15, I2C_1, 2},
{NC, NC, 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
volatile i2c_spi_peripheral_t i2c0_spi0_peripheral = {0, 0, 0, 0};
volatile i2c_spi_peripheral_t i2c1_spi1_peripheral = {0, 0, 0, 0};
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)
{
// determine the SPI to use
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);
NRF_TWI_Type *i2c;
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->sda = sda;
obj->i2c->EVENTS_ERROR = 0;

View File

@ -25,6 +25,16 @@
extern "C" {
#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 {
NRF_UART_Type *uart;
int index;
@ -33,6 +43,7 @@ struct serial_s {
struct spi_s {
NRF_SPI_Type *spi;
NRF_SPIS_Type *spis;
uint8_t peripheral;
};
struct port_s {
@ -54,6 +65,7 @@ struct i2c_s {
PinName scl;
int freq;
uint8_t address_set;
uint8_t peripheral;
};
struct analogin_s {

View File

@ -20,48 +20,55 @@
#include "pinmap.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
volatile uint8_t m_tx_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)
{
// determine the SPI to use
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
SPIName spi = (SPIName)pinmap_merge(spi_data, spi_cntl);
//SPIName
SPIName spi;
if (ssel == NC && 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) {
// The SPI with the same pins is already initialized
spi = SPI_0;
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) {
obj->spi = (NRF_SPI_Type *)spi;
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->spis = (NRF_SPIS_Type *)spi;
}
MBED_ASSERT((int)obj->spi != NC || (int)obj->spis != NC);
// pin out the spi pins
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)