aboutsummaryrefslogtreecommitdiff
path: root/apps/systemcmds
diff options
context:
space:
mode:
authorpx4dev <px4@purgatory.org>2012-09-09 11:14:54 -0700
committerpx4dev <px4@purgatory.org>2012-09-09 11:14:54 -0700
commita9c4fabda6cccb15912348ac5061827a6cb38304 (patch)
treeb74b6486a320907a7a333b274eb8dceeb09b5fb0 /apps/systemcmds
parent65ecf1b1c184e56dab4f168c89a2b4c23dfe5cb0 (diff)
downloadpx4-firmware-a9c4fabda6cccb15912348ac5061827a6cb38304.tar.gz
px4-firmware-a9c4fabda6cccb15912348ac5061827a6cb38304.tar.bz2
px4-firmware-a9c4fabda6cccb15912348ac5061827a6cb38304.zip
Change the EEPROM read/write timeout behavior so that we can get actual errors rather than just hanging forever.
Diffstat (limited to 'apps/systemcmds')
-rw-r--r--apps/systemcmds/eeprom/24xxxx_mtd.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/apps/systemcmds/eeprom/24xxxx_mtd.c b/apps/systemcmds/eeprom/24xxxx_mtd.c
index 1b8c59f77..c83362ca8 100644
--- a/apps/systemcmds/eeprom/24xxxx_mtd.c
+++ b/apps/systemcmds/eeprom/24xxxx_mtd.c
@@ -119,6 +119,13 @@
# define CONFIG_AT24XX_MTD_BLOCKSIZE AT24XX_PAGESIZE
#endif
+/* The AT24 does not respond on the bus during write cycles, so we depend on a long
+ * timeout to detect problems. The max program time is typically ~5ms.
+ */
+#ifndef CONFIG_AT24XX_WRITE_TIMEOUT_MS
+# define CONFIG_AT24XX_WRITE_TIMEOUT_MS 20
+#endif
+
/************************************************************************************
* Private Types
************************************************************************************/
@@ -140,6 +147,8 @@ struct at24c_dev_s
perf_counter_t perf_writes;
perf_counter_t perf_resets;
perf_counter_t perf_read_retries;
+ perf_counter_t perf_read_errors;
+ perf_counter_t perf_write_errors;
};
/************************************************************************************
@@ -262,6 +271,7 @@ static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock,
while (blocksleft-- > 0)
{
uint16_t offset = startblock * priv->pagesize;
+ unsigned tries = CONFIG_AT24XX_WRITE_TIMEOUT_MS;
addr[1] = offset & 0xff;
addr[0] = (offset >> 8) & 0xff;
@@ -269,7 +279,6 @@ static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock,
for (;;)
{
- unsigned tries = 50;
perf_begin(priv->perf_reads);
ret = I2C_TRANSFER(priv->dev, &msgv[0], 2);
@@ -279,18 +288,19 @@ static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock,
fvdbg("read stall");
usleep(1000);
- perf_count(priv->perf_read_retries);
- /*
- * Kick the bus in case it's stuck.
+ /* We should normally only be here on the first read after
+ * a write.
+ *
+ * XXX maybe do special first-read handling with optional
+ * bus reset as well?
*/
+ perf_count(priv->perf_read_retries);
if (--tries == 0)
{
- tries = 50;
- up_i2creset(priv->dev);
- perf_count(priv->perf_resets);
+ perf_count(priv->perf_read_errors);
+ return ERROR;
}
-
}
startblock++;
@@ -350,6 +360,7 @@ static ssize_t at24c_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t
while (blocksleft-- > 0)
{
uint16_t offset = startblock * priv->pagesize;
+ unsigned tries = CONFIG_AT24XX_WRITE_TIMEOUT_MS;
buf[1] = offset & 0xff;
buf[0] = (offset >> 8) & 0xff;
@@ -365,9 +376,17 @@ static ssize_t at24c_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t
if (ret >= 0)
break;
- /* XXX probably want a bus reset in here and an eventual timeout */
fvdbg("write stall");
usleep(1000);
+
+ /* We expect to see a number of retries per write cycle as we
+ * poll for write completion.
+ */
+ if (--tries == 0)
+ {
+ perf_count(priv->perf_write_errors);
+ return ERROR;
+ }
}
startblock++;
@@ -496,6 +515,8 @@ FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_dev_s *dev)
priv->perf_writes = perf_alloc(PC_ELAPSED, "EEPROM write");
priv->perf_resets = perf_alloc(PC_COUNT, "EEPROM reset");
priv->perf_read_retries = perf_alloc(PC_COUNT, "EEPROM read retries");
+ priv->perf_read_errors = perf_alloc(PC_COUNT, "EEPROM read errors");
+ priv->perf_write_errors = perf_alloc(PC_COUNT, "EEPROM write errors");
}
/* Return the implementation-specific state structure as the MTD device */