mbed

Fork of mbed-dev by mbed official

Revision:
177:447f873cad2f
Parent:
169:e3b6fe271b81
diff -r af195413fb11 -r 447f873cad2f targets/TARGET_NORDIC/TARGET_NRF5/i2c_api.c
--- 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;
 }