summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2014-10-28 18:36:34 +1100
committerAndrew Tridgell <tridge@samba.org>2014-10-28 21:01:53 +1100
commit43089519ddfad745cb27fe702d035253bf6e7bb4 (patch)
treef1c6b9c35d8b40e97819005232d4f9087a256645
parentcb862233badf378aff6c2fe9b55774401b5a79d4 (diff)
downloadnuttx-43089519ddfad745cb27fe702d035253bf6e7bb4.tar.gz
nuttx-43089519ddfad745cb27fe702d035253bf6e7bb4.tar.bz2
nuttx-43089519ddfad745cb27fe702d035253bf6e7bb4.zip
stm32_i2c: handle more error conditions on I2C bus
this fixes a I2C ISR storm condition where status=0x70084, which can happen with some specific types of noise on the I2C bus. This was reproduced by playing 80s rock through a Jabra wireless headset close to the I2C cables.
-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