aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpx4dev <px4@purgatory.org>2012-08-22 22:25:10 -0700
committerpx4dev <px4@purgatory.org>2012-08-22 22:25:10 -0700
commita0b9c056d78604397a407c86e3ad13d19fed372a (patch)
treeff66a4211a5e236286880c22bbb523bf9936aaff
parenta3b78163c3bbcc64a7aa5ada6a0f62670b7fd1cc (diff)
downloadpx4-firmware-a0b9c056d78604397a407c86e3ad13d19fed372a.tar.gz
px4-firmware-a0b9c056d78604397a407c86e3ad13d19fed372a.tar.bz2
px4-firmware-a0b9c056d78604397a407c86e3ad13d19fed372a.zip
Add a bus reset on I2C error. Also add a mechanism for automated retries of operations.
-rw-r--r--apps/drivers/device/i2c.cpp50
-rw-r--r--apps/drivers/device/i2c.h6
2 files changed, 37 insertions, 19 deletions
diff --git a/apps/drivers/device/i2c.cpp b/apps/drivers/device/i2c.cpp
index 8489db4bb..e403ce42b 100644
--- a/apps/drivers/device/i2c.cpp
+++ b/apps/drivers/device/i2c.cpp
@@ -53,6 +53,7 @@ I2C::I2C(const char *name,
CDev(name, devname, irq),
// public
// protected
+ _retries(0),
// private
_bus(bus),
_address(address),
@@ -117,33 +118,44 @@ I2C::transfer(uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len
struct i2c_msg_s msgv[2];
unsigned msgs;
int ret;
+ unsigned tries;
-// debug("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len);
+ do {
+ // debug("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len);
- msgs = 0;
+ msgs = 0;
- if (send_len > 0) {
- msgv[msgs].addr = _address;
- msgv[msgs].flags = 0;
- msgv[msgs].buffer = send;
- msgv[msgs].length = send_len;
- msgs++;
- }
+ if (send_len > 0) {
+ msgv[msgs].addr = _address;
+ msgv[msgs].flags = 0;
+ msgv[msgs].buffer = send;
+ msgv[msgs].length = send_len;
+ msgs++;
+ }
- if (recv_len > 0) {
- msgv[msgs].addr = _address;
- msgv[msgs].flags = I2C_M_READ;
- msgv[msgs].buffer = recv;
- msgv[msgs].length = recv_len;
- msgs++;
- }
+ if (recv_len > 0) {
+ msgv[msgs].addr = _address;
+ msgv[msgs].flags = I2C_M_READ;
+ msgv[msgs].buffer = recv;
+ msgv[msgs].length = recv_len;
+ msgs++;
+ }
+
+ if (msgs == 0)
+ return -EINVAL;
- if (msgs == 0)
- return -EINVAL;
+ ret = I2C_TRANSFER(_dev, &msgv[0], msgs);
- ret = I2C_TRANSFER(_dev, &msgv[0], msgs);
+ if (ret == OK)
+ break;
+
+ // reset the I2C bus to unwedge on error
+ up_i2creset(_dev);
+
+ } while (tries++ < _retries);
return ret;
+
}
} // namespace device \ No newline at end of file
diff --git a/apps/drivers/device/i2c.h b/apps/drivers/device/i2c.h
index d84f7bd09..7c5a14d6b 100644
--- a/apps/drivers/device/i2c.h
+++ b/apps/drivers/device/i2c.h
@@ -53,6 +53,12 @@ class __EXPORT I2C : public CDev
protected:
/**
+ * The number of times a read or write operation will be retried on
+ * error.
+ */
+ unsigned _retries;
+
+ /**
* @ Constructor
*
* @param name Driver name