mbed
Fork of mbed-dev by
Diff: targets/TARGET_NORDIC/TARGET_NRF5/i2c_api.c
- Revision:
- 177:447f873cad2f
- Parent:
- 169:e3b6fe271b81
--- a/targets/TARGET_NORDIC/TARGET_NRF5/i2c_api.c Wed Oct 11 12:45:49 2017 +0100 +++ b/targets/TARGET_NORDIC/TARGET_NRF5/i2c_api.c Wed Oct 25 14:53:38 2017 +0100 @@ -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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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_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 @@ 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; }