-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Mbed OS 5
Target UBLOX_EVK_NINA_B1
Toolchain GCC_ARM
The Nordic RF52 SoC uses digital 'TWI' control blocks to control both I2C and SPI. When declaring an I2C object, the Nordic platform code in targets/TARGET_NORDIC/TARGET_NRF5/i2c_api.c uses the method "i2c_init" to allocate the first available TWI by examining previously-allocated I2C instances. Similar code is used in the SPI drivers (spi_api.c) where previously-allocated SPI instances are checked.
This approach fails when allocating a mixture of I2C and SPI instances since both _init methods then consider TWI0 to be available and allocate it to both the I2C and SPI interfaces. This leads to unpredictable results when the interfaces are used.
If you only have a single I2C and SPI instance, it's possible to work around this by forcing one of the allocators to allocate TWI1 (example code below) but the correct fix would be to implement a central allocator which would be used for both types of interface.
diff --git a/targets/TARGET_NORDIC/TARGET_NRF5/i2c_api.c b/targets/TARGET_NORDIC/TARGET_NRF5/i2c_api.c
index 66063b4..ca551d4 100644
--- a/targets/TARGET_NORDIC/TARGET_NRF5/i2c_api.c
+++ b/targets/TARGET_NORDIC/TARGET_NRF5/i2c_api.c
@@ -283,6 +283,7 @@ static void twi_clear_bus(twi_info_t *twi_info)
}
}
+#define I2C_TWI 1
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
{
int i;
@@ -290,7 +291,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
if (m_twi_info[i].initialized &&
m_twi_info[i].pselsda == (uint32_t)sda &&
m_twi_info[i].pselscl == (uint32_t)scl) {
- TWI_IDX(obj) = i;
+ TWI_IDX(obj) = I2C_TWI;
TWI_INFO(obj)->frequency = NRF_TWI_FREQ_100K;
i2c_reset(obj);
return;
@@ -299,7 +300,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
for (i = 0; i < TWI_COUNT; ++i) {
if (!m_twi_info[i].initialized) {
- TWI_IDX(obj) = i;
+ TWI_IDX(obj) = I2C_TWI;
twi_info_t *twi_info = TWI_INFO(obj);
twi_info->initialized = true;
Copying @MarceloSalazar by request