[rtems commit] i2c: Fix EEPROM driver program timeout handling

Sebastian Huber sebh at rtems.org
Mon Oct 2 11:46:58 UTC 2017


Module:    rtems
Branch:    4.11
Commit:    1a21831b3c8ed7925dbbfb3c3b04d90d5a16845d
Changeset: http://git.rtems.org/rtems/commit/?id=1a21831b3c8ed7925dbbfb3c3b04d90d5a16845d

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Oct  2 13:28:22 2017 +0200

i2c: Fix EEPROM driver program timeout handling

The RTEMS_MILLISECONDS_TO_TICKS() macro doesn't round up. Do not use it
to calculate the program timeout in ticks. Check program done condition
after the timeout check to account for pre-emptions.

Close #3162.

---

 cpukit/dev/i2c/eeprom.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/cpukit/dev/i2c/eeprom.c b/cpukit/dev/i2c/eeprom.c
index 74f2d8c..97e0f55 100644
--- a/cpukit/dev/i2c/eeprom.c
+++ b/cpukit/dev/i2c/eeprom.c
@@ -39,7 +39,7 @@ typedef struct {
   uint32_t size;
   uint16_t i2c_address_mask;
   uint16_t i2c_address_shift;
-  rtems_interval program_timeout;
+  rtems_interval program_timeout_in_ticks;
 } eeprom;
 
 static uint16_t eeprom_i2c_addr(eeprom *dev, uint32_t off)
@@ -172,6 +172,7 @@ static ssize_t eeprom_write(
     int err;
     ssize_t m;
     rtems_interval timeout;
+    bool before;
 
     eeprom_set_addr(dev, off, addr);
     err = i2c_bus_transfer(dev->base.bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
@@ -179,11 +180,16 @@ static ssize_t eeprom_write(
       return err;
     }
 
-    timeout = rtems_clock_tick_later(dev->program_timeout);
+    timeout = rtems_clock_tick_later(dev->program_timeout_in_ticks);
 
     do {
+      before = rtems_clock_tick_before(timeout);
+
       m = eeprom_read(&dev->base, &in[0], cur, off);
-    } while (m != cur && rtems_clock_tick_before(timeout));
+      if (m == cur) {
+        break;
+      }
+    } while (before);
 
     if (m != cur) {
       return -ETIMEDOUT;
@@ -226,6 +232,7 @@ int i2c_dev_register_eeprom(
 )
 {
   uint32_t extra_address;
+  uint32_t ms_per_tick;
   eeprom *dev;
 
   if (address_bytes > EEPROM_MAX_ADDRESS_BYTES) {
@@ -261,7 +268,9 @@ int i2c_dev_register_eeprom(
   dev->address_bytes = address_bytes;
   dev->page_size = page_size_in_bytes;
   dev->size = size_in_bytes;
-  dev->program_timeout = RTEMS_MILLISECONDS_TO_TICKS(program_timeout_in_ms);
+  ms_per_tick = rtems_configuration_get_milliseconds_per_tick();
+  dev->program_timeout_in_ticks = (program_timeout_in_ms + ms_per_tick - 1)
+    / ms_per_tick + 1;
 
   if (extra_address != 0) {
     dev->i2c_address_mask = extra_address - 1;



More information about the vc mailing list