From 55e08de21c1ab235073db2e3da090163b661633e Mon Sep 17 00:00:00 2001
From: UncleRus <unclerus@gmail.com>
Date: Fri, 21 Apr 2017 17:53:13 +0500
Subject: [PATCH] Fix for counter overflow in delays based on
 sdk_system_get_time()

---
 extras/hmc5883l/hmc5883l.c     |  6 ++++--
 extras/sdio/sdio.c             | 23 +++++++++++++----------
 extras/ultrasonic/ultrasonic.c | 10 ++++++----
 3 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/extras/hmc5883l/hmc5883l.c b/extras/hmc5883l/hmc5883l.c
index ac1bcf2..265258d 100644
--- a/extras/hmc5883l/hmc5883l.c
+++ b/extras/hmc5883l/hmc5883l.c
@@ -38,6 +38,8 @@
 
 #define MEASUREMENT_TIMEOUT 6000
 
+#define timeout_expired(start, len) ((uint32_t)(sdk_system_get_time() - (start)) >= (len))
+
 static const float gain_values [] = {
     [HMC5883L_GAIN_1370] = 0.73,
     [HMC5883L_GAIN_1090] = 0.92,
@@ -156,10 +158,10 @@ bool hmc5883l_get_raw_data(hmc5883l_raw_data_t *data)
         // overwrite mode register for measurement
         hmc5883l_set_operating_mode(current_mode);
         // wait for data
-        uint32_t timeout = sdk_system_get_time() + MEASUREMENT_TIMEOUT;
+        uint32_t start = sdk_system_get_time();
         while (!hmc5883l_data_is_ready())
         {
-            if (sdk_system_get_time() >= timeout)
+            if (timeout_expired(start, MEASUREMENT_TIMEOUT))
                 return false;
         }
     }
diff --git a/extras/sdio/sdio.c b/extras/sdio/sdio.c
index 573d038..e601416 100644
--- a/extras/sdio/sdio.c
+++ b/extras/sdio/sdio.c
@@ -141,6 +141,8 @@ static uint16_t crc_ccitt(const uint8_t *data, size_t n)
 #define spi_skip_word()   do { spi_read_byte(); spi_read_byte(); } while(0)
 #define spi_skip_dword()  do { spi_read_byte(); spi_read_byte(); spi_read_byte(); spi_read_byte(); } while(0)
 
+#define timeout_expired(start, len) ((uint32_t)(sdk_system_get_time() - (start)) >= (len))
+
 inline static uint16_t spi_write_word(uint16_t word)
 {
     return (spi_transfer_8(BUS, word >> 8) << 8) | spi_transfer_8(BUS, word);
@@ -154,9 +156,10 @@ inline static void spi_read_bytes(uint8_t *dst, size_t size)
 
 static bool wait()
 {
-    uint32_t stop = sdk_system_get_time() + IO_TIMEOUT_US;
+
+    uint32_t start = sdk_system_get_time();
     while (spi_read_byte() != 0xff)
-        if (sdk_system_get_time() >= stop)
+        if (timeout_expired(start, IO_TIMEOUT_US))
             return false;
     return true;
 }
@@ -208,11 +211,11 @@ inline static sdio_error_t set_error(sdio_card_t *card, sdio_error_t err)
 
 static sdio_error_t read_data(sdio_card_t *card, uint8_t *dst, size_t size)
 {
-    uint32_t timeout = sdk_system_get_time() + IO_TIMEOUT_US;
+    uint32_t start = sdk_system_get_time();
 
     while (true)
     {
-        if (sdk_system_get_time() >= timeout)
+        if (timeout_expired(start, IO_TIMEOUT_US))
             return set_error(card, SDIO_ERR_TIMEOUT);
 
         uint8_t b = spi_read_byte();
@@ -269,7 +272,7 @@ sdio_error_t sdio_init(sdio_card_t *card, uint8_t cs_pin, uint32_t high_freq_div
     spi_set_settings(BUS, &s);
     gpio_enable(card->cs_pin, GPIO_OUTPUT);
 
-    uint32_t timeout = sdk_system_get_time() + INIT_TIMEOUT_US;
+    uint32_t start = sdk_system_get_time();
 
     spi_cs_low(card);
     spi_cs_high(card);
@@ -279,7 +282,7 @@ sdio_error_t sdio_init(sdio_card_t *card, uint8_t cs_pin, uint32_t high_freq_div
     // Set card to the SPI idle mode
     while (command(card, CMD0, 0) != BV(R1_IDLE_STATE))
     {
-        if (sdk_system_get_time() >= timeout)
+        if (timeout_expired(start, INIT_TIMEOUT_US))
             return set_error(card, SDIO_ERR_TIMEOUT);
     }
 
@@ -300,7 +303,7 @@ sdio_error_t sdio_init(sdio_card_t *card, uint8_t cs_pin, uint32_t high_freq_div
             break;
         }
 
-        if (sdk_system_get_time() >= timeout)
+        if (timeout_expired(start, INIT_TIMEOUT_US))
             return set_error(card, SDIO_ERR_TIMEOUT);
     }
 
@@ -311,13 +314,13 @@ sdio_error_t sdio_init(sdio_card_t *card, uint8_t cs_pin, uint32_t high_freq_div
         {
             card->type = SDIO_TYPE_MMC;
             while (command(card, CMD1, 0))
-                if (sdk_system_get_time() >= timeout)
+                if (timeout_expired(start, INIT_TIMEOUT_US))
                     return set_error(card, SDIO_ERR_TIMEOUT);
         }
         else
         {
             while (app_command(card, ACMD41, 0))
-                if (sdk_system_get_time() >= timeout)
+                if (timeout_expired(start, INIT_TIMEOUT_US))
                     return set_error(card, SDIO_ERR_TIMEOUT);
         }
 
@@ -328,7 +331,7 @@ sdio_error_t sdio_init(sdio_card_t *card, uint8_t cs_pin, uint32_t high_freq_div
     {
         // SD2 or SDHC
         while (app_command(card, ACMD41, BV(30)) != 0)
-            if (sdk_system_get_time() >= timeout)
+            if (timeout_expired(start, INIT_TIMEOUT_US))
                 return set_error(card, SDIO_ERR_TIMEOUT);
     }
     // read OCR
diff --git a/extras/ultrasonic/ultrasonic.c b/extras/ultrasonic/ultrasonic.c
index f6a21f6..21ae493 100644
--- a/extras/ultrasonic/ultrasonic.c
+++ b/extras/ultrasonic/ultrasonic.c
@@ -15,6 +15,8 @@
 #define PING_TIMEOUT 6000
 #define ROUNDTRIP 58
 
+#define timeout_expired(start, len) ((uint32_t)(sdk_system_get_time() - (start)) >= (len))
+
 void ultrasoinc_init(const ultrasonic_sensor_t *dev)
 {
     gpio_enable(dev->trigger_pin, GPIO_OUTPUT);
@@ -36,21 +38,21 @@ int32_t ultrasoinc_measure_cm(const ultrasonic_sensor_t *dev, uint32_t max_dista
         return ULTRASONIC_ERROR_PING;
 
     // Wait for echo
-    uint32_t timeout = sdk_system_get_time() + PING_TIMEOUT;
+    uint32_t start = sdk_system_get_time();
     while (!gpio_read(dev->echo_pin))
     {
-        if (sdk_system_get_time() >= timeout)
+        if (timeout_expired(start, PING_TIMEOUT))
             return ULTRASONIC_ERROR_PING_TIMEOUT;
     }
 
     // got echo, measuring
     uint32_t echo_start = sdk_system_get_time();
     uint32_t time = echo_start;
-    timeout = echo_start + max_distance * ROUNDTRIP;
+    uint32_t meas_timeout = echo_start + max_distance * ROUNDTRIP;
     while (gpio_read(dev->echo_pin))
     {
         time = sdk_system_get_time();
-        if (time >= timeout)
+        if (timeout_expired(echo_start, meas_timeout))
             return ULTRASONIC_ERROR_ECHO_TIMEOUT;
     }