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_delay.h"
|
||||
|
||||
// An arbitrary value used as the counter in loops waiting for given event
|
||||
// (e.g. STOPPED), needed to avoid infinite loops (and not involve any timers
|
||||
// or tickers).
|
||||
#define TIMEOUT_VALUE 1000
|
||||
#include "us_ticker_api.h"
|
||||
|
||||
// An arbitrary value used as the timeout in loops waiting for given event
|
||||
// (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
|
||||
#define TWI_IDX(obj) ((obj)->i2c.twi_idx)
|
||||
|
@ -371,17 +375,20 @@ int i2c_start(i2c_t *obj)
|
|||
int i2c_stop(i2c_t *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
|
||||
// resumed before the STOP task is triggered.
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STOP);
|
||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
||||
|
||||
t0 = ticker_read(get_us_ticker_data());
|
||||
|
||||
do {
|
||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_STOPPED)) {
|
||||
return 0;
|
||||
}
|
||||
} while (--remaining_time);
|
||||
} while (((uint32_t)ticker_read(get_us_ticker_data()) - t0) < I2C_TIMEOUT_VALUE_US);
|
||||
|
||||
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)
|
||||
{
|
||||
uint32_t t0;
|
||||
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||
|
||||
nrf_twi_txd_set(twi, data);
|
||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
||||
|
||||
t0 = ticker_read(get_us_ticker_data());
|
||||
|
||||
do {
|
||||
if (nrf_twi_event_check(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);
|
||||
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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
bool timeout = false;
|
||||
uint32_t t0, t1;
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
if (twi_info->active) {
|
||||
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_task_trigger(twi, NRF_TWI_TASK_SUSPEND);
|
||||
}
|
||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
||||
|
||||
t0 = ticker_read(get_us_ticker_data());
|
||||
|
||||
do {
|
||||
if (nrf_twi_event_check(twi, event)) {
|
||||
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);
|
||||
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 (remaining_time ? 0 : I2C_ERROR_BUS_BUSY);
|
||||
return (timeout ? I2C_ERROR_BUS_BUSY : 0);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||
uint32_t t0;
|
||||
|
||||
if (last) {
|
||||
nrf_twi_shorts_set(twi, NRF_TWI_SHORT_BB_STOP_MASK);
|
||||
}
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
|
||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
||||
t0 = ticker_read(get_us_ticker_data());
|
||||
|
||||
do {
|
||||
if (nrf_twi_event_check(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);
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue