mirror of https://github.com/ARMmbed/mbed-os.git
fix bug: I2C timeout due the clos strething by slave on nRFx SoC
Change implementation of timeout to one that is using us_ticker hal. Timeout is now configurable by I2C_TIMEOUT_VALUE_US macro and this value will be imported if will be defined externaly.pull/5187/head
parent
5e437fe5ea
commit
2a0d38eaf6
|
@ -50,10 +50,14 @@
|
||||||
#include "nrf_gpio.h"
|
#include "nrf_gpio.h"
|
||||||
#include "nrf_delay.h"
|
#include "nrf_delay.h"
|
||||||
|
|
||||||
// An arbitrary value used as the counter in loops waiting for given event
|
#include "us_ticker_api.h"
|
||||||
// (e.g. STOPPED), needed to avoid infinite loops (and not involve any timers
|
|
||||||
// or tickers).
|
// An arbitrary value used as the timeout in loops waiting for given event
|
||||||
#define TIMEOUT_VALUE 1000
|
// (e.g. STOPPED), needed to avoid infinite loops.
|
||||||
|
// This value might be defined externally.
|
||||||
|
#ifndef I2C_TIMEOUT_VALUE_US
|
||||||
|
#define I2C_TIMEOUT_VALUE_US 1000000
|
||||||
|
#endif
|
||||||
|
|
||||||
#if DEVICE_I2C_ASYNCH
|
#if DEVICE_I2C_ASYNCH
|
||||||
#define TWI_IDX(obj) ((obj)->i2c.twi_idx)
|
#define TWI_IDX(obj) ((obj)->i2c.twi_idx)
|
||||||
|
@ -371,17 +375,20 @@ int i2c_start(i2c_t *obj)
|
||||||
int i2c_stop(i2c_t *obj)
|
int i2c_stop(i2c_t *obj)
|
||||||
{
|
{
|
||||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||||
|
uint32_t t0;
|
||||||
|
|
||||||
// The current transfer may be suspended (if it is RX), so it must be
|
// The current transfer may be suspended (if it is RX), so it must be
|
||||||
// resumed before the STOP task is triggered.
|
// resumed before the STOP task is triggered.
|
||||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STOP);
|
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STOP);
|
||||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
|
||||||
|
t0 = ticker_read(get_us_ticker_data());
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_STOPPED)) {
|
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_STOPPED)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} while (--remaining_time);
|
} while (((uint32_t)ticker_read(get_us_ticker_data()) - t0) < I2C_TIMEOUT_VALUE_US);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -464,11 +471,15 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
||||||
|
|
||||||
static uint8_t twi_byte_write(NRF_TWI_Type *twi, uint8_t data)
|
static uint8_t twi_byte_write(NRF_TWI_Type *twi, uint8_t data)
|
||||||
{
|
{
|
||||||
|
uint32_t t0;
|
||||||
|
|
||||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
||||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||||
|
|
||||||
nrf_twi_txd_set(twi, data);
|
nrf_twi_txd_set(twi, data);
|
||||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
|
||||||
|
t0 = ticker_read(get_us_ticker_data());
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_TXDSENT)) {
|
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_TXDSENT)) {
|
||||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
||||||
|
@ -478,7 +489,7 @@ static uint8_t twi_byte_write(NRF_TWI_Type *twi, uint8_t data)
|
||||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||||
return 0; // some error occurred
|
return 0; // some error occurred
|
||||||
}
|
}
|
||||||
} while (--remaining_time);
|
} while (((uint32_t)ticker_read(get_us_ticker_data()) - t0) < I2C_TIMEOUT_VALUE_US);
|
||||||
|
|
||||||
return 2; // timeout;
|
return 2; // timeout;
|
||||||
}
|
}
|
||||||
|
@ -500,6 +511,9 @@ static void start_twi_write(NRF_TWI_Type *twi, int address)
|
||||||
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
||||||
{
|
{
|
||||||
twi_info_t *twi_info = TWI_INFO(obj);
|
twi_info_t *twi_info = TWI_INFO(obj);
|
||||||
|
bool timeout = false;
|
||||||
|
uint32_t t0, t1;
|
||||||
|
|
||||||
#if DEVICE_I2C_ASYNCH
|
#if DEVICE_I2C_ASYNCH
|
||||||
if (twi_info->active) {
|
if (twi_info->active) {
|
||||||
return I2C_ERROR_BUS_BUSY;
|
return I2C_ERROR_BUS_BUSY;
|
||||||
|
@ -522,12 +536,16 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
||||||
nrf_twi_event_clear(twi, event);
|
nrf_twi_event_clear(twi, event);
|
||||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_SUSPEND);
|
nrf_twi_task_trigger(twi, NRF_TWI_TASK_SUSPEND);
|
||||||
}
|
}
|
||||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
|
||||||
|
t0 = ticker_read(get_us_ticker_data());
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (nrf_twi_event_check(twi, event)) {
|
if (nrf_twi_event_check(twi, event)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (--remaining_time);
|
t1 = ticker_read(get_us_ticker_data());
|
||||||
|
timeout = (t1 - t0) >= I2C_TIMEOUT_VALUE_US;
|
||||||
|
} while (!timeout);
|
||||||
|
|
||||||
uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(twi);
|
uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(twi);
|
||||||
if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK) {
|
if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK) {
|
||||||
|
@ -537,7 +555,7 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
||||||
return I2C_ERROR_NO_SLAVE;
|
return I2C_ERROR_NO_SLAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (remaining_time ? 0 : I2C_ERROR_BUS_BUSY);
|
return (timeout ? I2C_ERROR_BUS_BUSY : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = length;
|
int result = length;
|
||||||
|
@ -574,13 +592,15 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
||||||
int i2c_byte_read(i2c_t *obj, int last)
|
int i2c_byte_read(i2c_t *obj, int last)
|
||||||
{
|
{
|
||||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||||
|
uint32_t t0;
|
||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
nrf_twi_shorts_set(twi, NRF_TWI_SHORT_BB_STOP_MASK);
|
nrf_twi_shorts_set(twi, NRF_TWI_SHORT_BB_STOP_MASK);
|
||||||
}
|
}
|
||||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||||
|
|
||||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
t0 = ticker_read(get_us_ticker_data());
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_RXDREADY)) {
|
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_RXDREADY)) {
|
||||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_RXDREADY);
|
nrf_twi_event_clear(twi, NRF_TWI_EVENT_RXDREADY);
|
||||||
|
@ -590,7 +610,7 @@ int i2c_byte_read(i2c_t *obj, int last)
|
||||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||||
return I2C_ERROR_NO_SLAVE;
|
return I2C_ERROR_NO_SLAVE;
|
||||||
}
|
}
|
||||||
} while (--remaining_time);
|
} while (((uint32_t)ticker_read(get_us_ticker_data()) - t0) < I2C_TIMEOUT_VALUE_US);
|
||||||
|
|
||||||
return I2C_ERROR_BUS_BUSY;
|
return I2C_ERROR_BUS_BUSY;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue