Rework the 'eeprom erase' path so it's possible to erase an EEPROM that can't be mounted.

Add some bus reset code to the EEPROM read path to maybe help with bus lockup.
This commit is contained in:
px4dev 2012-09-09 00:04:43 -07:00
parent 6caa3038ba
commit 65ecf1b1c1
2 changed files with 42 additions and 15 deletions

View File

@ -138,6 +138,8 @@ struct at24c_dev_s
perf_counter_t perf_reads;
perf_counter_t perf_writes;
perf_counter_t perf_resets;
perf_counter_t perf_read_retries;
};
/************************************************************************************
@ -267,6 +269,7 @@ 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);
@ -274,9 +277,20 @@ static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock,
if (ret >= 0)
break;
/* XXX probably want a bus reset in here and an eventual timeout */
fvdbg("read stall");
usleep(1000);
perf_count(priv->perf_read_retries);
/*
* Kick the bus in case it's stuck.
*/
if (--tries == 0)
{
tries = 50;
up_i2creset(priv->dev);
perf_count(priv->perf_resets);
}
}
startblock++;
@ -480,6 +494,8 @@ FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_dev_s *dev)
priv->perf_reads = perf_alloc(PC_ELAPSED, "EEPROM read");
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");
}
/* Return the implementation-specific state structure as the MTD device */

View File

@ -67,13 +67,16 @@
__EXPORT int eeprom_main(int argc, char *argv[]);
static void eeprom_attach(void);
static void eeprom_start(void);
static void eeprom_erase(void);
static void eeprom_ioctl(unsigned operation);
static void eeprom_save(const char *name);
static void eeprom_load(const char *name);
static bool attached = false;
static bool started = false;
static struct mtd_dev_s *eeprom_mtd;
int eeprom_main(int argc, char *argv[])
{
@ -105,13 +108,8 @@ int eeprom_main(int argc, char *argv[])
static void
eeprom_start(void)
eeprom_attach(void)
{
int ret;
if (started)
errx(1, "EEPROM service already started");
/* find the right I2C */
struct i2c_dev_s *i2c = up_i2cinitialize(PX4_I2C_BUS_ONBOARD);
/* this resets the I2C bus, set correct bus speed again */
@ -121,16 +119,27 @@ eeprom_start(void)
errx(1, "failed to locate I2C bus");
/* start the MTD driver */
struct mtd_dev_s *mtd = at24c_initialize(i2c);
eeprom_mtd = at24c_initialize(i2c);
if (mtd == NULL)
if (eeprom_mtd == NULL)
errx(1, "failed to initialize EEPROM driver");
/* driver is started, even if NXFFS fails to mount */
started = true;
attached = true;
}
static void
eeprom_start(void)
{
int ret;
if (started)
errx(1, "EEPROM already mounted");
if (!attached)
eeprom_attach();
/* start NXFFS */
ret = nxffs_initialize(mtd);
ret = nxffs_initialize(eeprom_mtd);
if (ret < 0)
errx(1, "failed to initialize NXFFS - erase EEPROM to reformat");
@ -141,7 +150,9 @@ eeprom_start(void)
if (ret < 0)
errx(1, "failed to mount /eeprom - erase EEPROM to reformat");
errx(0, "mounted EEPROM at /eeprom");
started = true;
warnx("mounted EEPROM at /eeprom");
exit(0);
}
extern int at24c_nuke(void);
@ -149,8 +160,8 @@ extern int at24c_nuke(void);
static void
eeprom_erase(void)
{
if (!started)
errx(1, "must be started first");
if (!attached)
eeprom_attach();
if (at24c_nuke())
errx(1, "erase failed");