summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-10-02 13:28:22 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-10-02 13:44:36 +0200
commit1a21831b3c8ed7925dbbfb3c3b04d90d5a16845d (patch)
tree2507abaa75b6057d5a19dfbdfd13fae9de33affd /cpukit
parent8ca15e26ba98f172ee1396f34269ca664925427d (diff)
downloadrtems-1a21831b3c8ed7925dbbfb3c3b04d90d5a16845d.tar.bz2
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.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/dev/i2c/eeprom.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/cpukit/dev/i2c/eeprom.c b/cpukit/dev/i2c/eeprom.c
index 74f2d8c9aa..97e0f55684 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;