AnsweredAssumed Answered

STM32F429 I2C not generating the correct number of clock pulses

Question asked by peeters.bram on Nov 30, 2016

I am running into a problem that the STM32F429 I2C peripheral sporadically does not generate enough clock pulses.

I use the HAL_I2C_Master_Transmit_IT function with 2 bytes payload (0x42, 0x77).

I have made mixed signal plots to illustrate the problem, see
It shows for a good and a bad transmission the following:
Analog 1/2: I2C clk/data on
D0: I2C_MasterTransmit_RXNE + I2C_MasterRecieve_BTF
D1: I2C_MasterTransmit_TXE
D2: I2C_MasterTransmit_BTF
D3: HAL_I2C_ER_IRQHandler + I2C_ITError

I also added the I2C registers after the problem occurs. It seems that from the point of view of the I2C block, the transaction is still ongoing though it is not generating any clocks anymore....

A correct transmission looks like:
- [IRQ] itsource : 0000072A    sr1: 00000001 (SB)   sr2:00000003 (MSL & BSY)

- [IRQ] itsource : 0000072A    sr1: 00000082 (TXE & ADDR)   sr2:00000007 (TRA & MSL & BSY)
  I2C_Master_ADDR (clears addr bit)
  I2C_MasterTransmit_TXE (with eg 2 bytes payload left)

(Remark: unclear why at this time BTF is not set here)

- [IRQ] itsource : 0000072A    sr1: 00000080 (TXE)   sr2:00000007
  I2C_MasterTransmit_TXE (with eg 1 bytes payload left)

- [IRQ] itsource : 0000072A    sr1: 00000080 (TXE)   sr2:00000007
  I2C_MasterTransmit_TXE (with eg 0 bytes payload left -> disables buf irq)

- [IRQ] itsource : 0000032A    sr1: 00000084 (TXE & BTF)   sr2:00000007
  I2C_MasterTransmit_BTF (with eg 0 bytes payload left -> generate stop)

Note: since the first 2 TXE's happen right after one another, their pulses are merged into one pulse on D1)

In an incorrect transmission the last IRQ never occurs, which is logical i guess because not all the bits of the last byte are shifted out.

For a while i though maybe the early 'stop' was caused by some SW problem triggering a STOP condition (hence tracing error cases on D3), but the ref manual states on p851:

"1: Stop generation after the current byte transferor after the current Start condition is sent."

So there seems to be no way to stop a transmission in the middle of a byte.
So the conclusion seems to be that there is a HW bug in the I2C block causing this because there is no way to do this in SW ?

Other suggestions ?
Since the device i am addressing seems to get in ACK mode (it keeps the data line low) the only way to recover from this is to switch the I2C lines to gpio mode and bit bag an extra clock ....