summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenz Meier <lm@qgroundcontrol.org>2014-10-28 11:09:00 +0100
committerLorenz Meier <lm@qgroundcontrol.org>2014-10-28 11:09:00 +0100
commitb492c8ac9ea659e4421554ab4a343357f35bafaa (patch)
treef1c6b9c35d8b40e97819005232d4f9087a256645
parentcb862233badf378aff6c2fe9b55774401b5a79d4 (diff)
parent43089519ddfad745cb27fe702d035253bf6e7bb4 (diff)
downloadnuttx-b492c8ac9ea659e4421554ab4a343357f35bafaa.tar.gz
nuttx-b492c8ac9ea659e4421554ab4a343357f35bafaa.tar.bz2
nuttx-b492c8ac9ea659e4421554ab4a343357f35bafaa.zip
Merge pull request #23 from tridge/pullrequest-i2c-lockup-fix
stm32_i2c: handle more error conditions on I2C bus
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_i2c.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_i2c.c b/nuttx/arch/arm/src/stm32/stm32_i2c.c
index 44978862d..fb8718316 100644
--- a/nuttx/arch/arm/src/stm32/stm32_i2c.c
+++ b/nuttx/arch/arm/src/stm32/stm32_i2c.c
@@ -93,6 +93,9 @@
#include "stm32_i2c.h"
#include "stm32_waste.h"
+// useful when debugging
+// #pragma GCC optimize("O0")
+
/* At least one I2C peripheral must be enabled */
#if defined(CONFIG_STM32_I2C1) || defined(CONFIG_STM32_I2C2) || defined(CONFIG_STM32_I2C3)
@@ -316,6 +319,8 @@ static inline uint32_t stm32_i2c_disablefsmc(FAR struct stm32_i2c_priv_s *priv);
static inline void stm32_i2c_enablefsmc(uint32_t ahbenr);
#endif /* I2C1_FSMC_CONFLICT */
static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv);
+// useful when debugging
+// static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv) __attribute__((optimize("O0")));
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_STM32_I2C1
static int stm32_i2c1_isr(int irq, void *context);
@@ -1262,6 +1267,29 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
// throw away the unexpected byte
stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
}
+ } else if (status & I2C_SR1_TXE) {
+ /* this should never happen, but it does happen
+ occasionally with lots of noise on the bus. It means the
+ peripheral is expecting more data bytes, but we don't have
+ any to give.
+ This has been seen with status=0x70084, reproduced with
+ noise generated by a Jabra wireless headset in close
+ proximity to the I2C lines
+ */
+ stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, 0);
+ } else if (status & I2C_SR1_BTF) {
+ /*
+ we should have handled all cases where this could happen
+ above, but just to ensure it gets acked, lets clear it here
+ */
+ stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
+ } else if (status & I2C_SR1_STOPF) {
+ /*
+ we should never get this, as we are a master not a
+ slave. Write CR1 with its current value to clear the
+ error
+ */
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, 0, 0);
}
/* Do we have more bytes to send, enable/disable buffer interrupts