I'm seeing problems with the Chibios I2C driver on the STM32F4 when there is noise
on the I2C data line. If the noise reaches a certain level, the processor "locks up" because
it is continuously servicing an I2C interrupt that never get cleared.
I was able to reduce the likelihood of lockups by adding the following code to
the I2C interrupt handler in os/hal/platforms/STM32/i2c_lld.c as follows:
Code: Select all
static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
I2C_TypeDef *dp = i2cp->i2c;
uint32_t regSR2 = dp->SR2;
uint32_t event = dp->SR1;
size_t t;
// START OF NEW CODE
if (dp->SR1 & I2C_SR1_BERR) { /* Bus error. */
dp->SR1 &= ~I2C_SR1_BERR;
i2cp->errors = I2CD_BUS_ERROR;
wakeup_isr(i2cp, RDY_RESET);
return;
}
// END OF NEW CODE
But this has not solved the problem completely.
Now, the interrupt routine repeatedly follows a different
path through the case statement in the interrupt handler,
as shown below.
Code: Select all
case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
/* Catches BTF event after the end of transmission.*/
if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) {
/* Starts "read after write" operation, LSB = 1 -> receive.*/
i2cp->addr |= 0x01;
dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
dp->CR1 |= I2C_CR1_STOP;
wakeup_isr(i2cp, RDY_OK);
I've checked the values of SR1 and SR2 and they look fine (no error bits set).
I'm using Chibios 2.4.1, but I have copied the I2C driver from 2.5.1
as there seemed to be a few differences that might have influenced this
issue. However, this made no difference to the problem.
I can reproduce this problem reliably using a signal generator connected
to the I2C data line via a diode. I'm injecting a 100ns low pulse every
1ms. The I2C bit rate is set to 27kHz.
I've been tearing my hair out on this one. My only solution so far is to replace
the Chibios I2C driver with a fully software-driven implementation that
bit-bashes GPIO pins directly.
I expect the noise to stop the I2C from achieving successful comms, but
it should not be possible to lock up the processor in this way regardless of
how much noise is present.
Does anyone have any ideas on how to fix this? I'm happy to try any suggestions
as I can reproduce the problem at will within seconds.
Craig