Showing results for 
Search instead for 
Did you mean: 

STM32H745I I2C Recovery after addressing nonexistent device?

I have I2C working properly, but can't seem to figure out how to recover the bus and get it to working again if I test for the presence of a device that is not on the bus and therefore I2C_Mem_Read() returns HAL_ERROR.  There are other devices on the bus, but HAL_ERROR seems to be latched and calling MX_I2C4_Init() again doesn't undo it and allow a retry.  The project is built with EWARM 9.30.1 and STMCubeMX 6.11.0.


Background:  I know this is working and checked it against an oscilloscope/protocol analyzer; what's happened is that one of my 2 I2C devices is unplugged and I want to recover from the error.

I2CResult = HAL_I2C_Mem_Write(&hi2c4, (0x22<<1)|0x01, 0x0C, 1, ExpanderConfig, 1, 100);

(device is on I2C4 pins, i2c address is 0x22, register address is 0x0C, address size is 1, we are writing 1 byte of ExpanderConfig, an array, and waiting 100ms for timeout)

I2CResult = HAL_I2C_Mem_Read(&hi2c4, 0x47<<1, 0x08, 1, BufConfig,3,100);

(reading on i2c4 pins, i2c address is 0x47, register address is 0x08, address size is 1, BufConfig is a 3 byte array, and we time out in 100ms.)




Cube/HAL is written with certain modes of operation in mind (e.g. "everything works, every I2C device is present, device absence is a fatal hardware error which needs fixing and restart") and may not cover your use case.


ST Employee


Your request has been escalated for further investigation.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
ST Employee

Hi EricChristenson-at-eaton-com


Your post has been reassigned to the online support team for more assistance.




STMicro Support

(Grin) You may be right, but I am an engineer and it can be said that I study failure....

in this case I might just need the bit to disable I2C4 in hardware to reset the AF (Acknowledge Failure) flag.


As an Ex-Philips guy, the clocking out of a jam method seems to be a thing people frequently miss.

Although back in the day you could get buses with devices that were capable of different speeds, and if you had slow devices one also had to consider they might get confused.

On the ST side, you don't need to drive the R/W bit, the peripheral manages that, and I seem to recall there being a function to probe the address space.

The transaction really should abort is the slave doesn't NACK to it's address. The slaves shouldn't get confused, but there are a lot of Kinda-I2C implementations

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I'm not sure we are talking about the jam-requiring-pulsing here. The opening post does not imply that, although we haven't seen nor heard about the waveforms.

I'd bet this is something around Cube/HAL's ways to handle unexpected situations such as address NAK. We've heard that it does return a generic error, but maybe it then requires some specific handling to resolve the situation (an I2C reset through the enable bit, perhaps?)

I'm eager to hear what @Joe WILLIAMS finds out about this issue.


> in this case I might just need the bit to disable I2C4 in hardware to reset the AF (Acknowledge Failure) flag.

I'm not sure what is "AF (Acknowledge Failure) flag".

IMO after NACK you should see the NACKF flag to be set; the RM says how to clear it.


But if you are talking about some Cube/HAL specific flag, you should resort to Cube/HAL manual; or, if it fails to be informative enough, directly to the Cube/HAL sources - it's open source.



In the end, my target I2C device (TUSB320LAI) needs to have its enable pin in the correct state or it won't talk on I2C at all, and none of that depended on the presence or absence of the other device.  It helps to get a little distance, re-run the working hardware example, and have an oscilloscope to check on the words on the bus, and to unmix up the I/O assignments on the two versions of hardware I was using.


In my noise-free environment, sending I2C to a nonexistent device merely results in an error return.  On the next read or write to I2C, everything works as you might expect... the device that exists responds as expected; if you remember to plug in the SDA line, suddenly all devices start to work.