diff options
author | Andrew Tridgell <tridge@samba.org> | 2014-10-28 18:36:34 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2014-10-28 21:01:53 +1100 |
commit | 43089519ddfad745cb27fe702d035253bf6e7bb4 (patch) | |
tree | f1c6b9c35d8b40e97819005232d4f9087a256645 /nuttx/arch/arm/src/stm32/stm32_i2c.c | |
parent | cb862233badf378aff6c2fe9b55774401b5a79d4 (diff) | |
download | nuttx-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.
Diffstat (limited to 'nuttx/arch/arm/src/stm32/stm32_i2c.c')
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_i2c.c | 28 |
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 |