2025-10-09 5:32 AM
Hello, ewryone!
I'm working on a project with a custom STM32F405 board. My project utilizes two independent I2C buses, both configured for Fast Mode (400 kHz):
Most of the time, everything works fine. However, sometimes HAL_I2C_Master_Transmit starts to return a HAL_BUSY status on both lines independently. In both cases, it gets stuck in I2C_WaitOnFlagUntilTimeout waiting on the BUSY flag.
In these situations, the I2C SDA line is always high while the SCL line is low. I tried switching the SCL GPIO from Alternate Function mode to an output and forcing it to a high level. But when I switch it back to Alternate Function (I2C SCL) mode, it immediately goes low again. I also tried disconnecting all the slave devices, and the SCL line was still held low. Therefore, I think it is a problem with the I2C master peripheral in my STM32F4.
So, the question is: what is happening here, and how can I fix this problem?
2025-10-09 6:06 AM
When you try to force the output high, is the pin still in open-drain mode? If it is, and the pin is still low, a slave is to blame, not the master.
Could be a slave device still holding the line low or could be the master has gotten into a bad state. If it's a slave, there is no recovery apart from power cycle. If it's the master, you can reset the entire I2C peripheral using the HAL_RCC_I2Cx_FORCE/RELEASE_RESET macros and then reset the software state machine.
2025-10-09 6:21 AM
@TDK wrote:When you try to force the output high, is the pin still in open-drain mode?
I tried both open-drain and push-pull modes, and the pin was high in both cases.
I also tried to reset the slaves by power-cycling them, but that didn't help.
@TDK wrote:then reset the software state machine
What 'software state machine' did you mean? Are you referring to the internal HAL state machine or my own software logic?
2025-10-09 7:31 AM
> I tried both open-drain and push-pull modes, and the pin was high in both cases.
Then it's probably the master. The STM32F4's I2C peripheral is a bear. I wouldn't be surprised if it occasionally gets into a weird state. In this case, if SCL is low, it's probably waiting for a new byte to be sent or for a stop condition to be generated.
> What 'software state machine' did you mean?
The HAL handle. Probably setting its state to *_RESET and then re-initializing would do it.