cancel
Showing results for 
Search instead for 
Did you mean: 

Can't reset I2C in STM32F407 to release I2C lines

Marco Hess
Associate II
Posted on January 12, 2017 at 08:18

I am using an STM32F407 on a customer board and have trouble with the I2C handling.

I am using the latest HAL HAL_I2C_MasterTransmitIT and HAL_I2C_MasterReceiveIT to poll data from a sensor.

The problem is that after a while the I2C lines lock up (both SDA and SCL low) and the 

HAL_I2C_MasterTransmitIT returns errors.

I do detect the error and try to handle the problem by deinit the I2C. I then reconfigure the I/O to software handle some clocking that release SDA if it is stuck by a slave on the bus. At that point I can see that the lines go high again so it is the I2C peripheral in the STM that is pulling it low ( I can also see that on the scope with the low level slightly above ground while when the lines are pulled by a slave device, the go lower).

I then 

reinit the I2C peripheral but as soon as the I2C is activated and connected to the I/O lines, the SDA and SCL are pulled low again.

So I can't seem to reset the I2C without restarting the whole chip.

Is there a other way to properly reset the I2C?

Also, what can be causing this lockup in the first place?

#stm32-i2c-master
21 REPLIES 21
AvaTar
Lead
Posted on January 12, 2017 at 09:33

Also, what can be causing this lockup in the first place?

A lock-up of the slave device. I would check that the communication sequences match that of the slave's datasheet. That might require a scope or logic analyzer to pin down the critical sequence and/or transition. Perhaps even a timing issue or an ignored clock stretch.

Is there a other way to properly reset the I2C?

If you can't find an issue with your software (I2C master), you might have a problem. I guess your (undisclosed) I2C slave does not have a reset pin - they usually have not. A stopgap solution would be to power-cycle the I2C slave via a GPIO pin of the master.

'Older' I2C devices had been more or less combinatorial devices, but more recent ones contain quite state machines. When you abort a communication sequence, you are lost in the woods.

Posted on January 12, 2017 at 10:13

You can reset the STM32's I2C module by setting and then clearing the respective I2CxRST bit in RCC_APByRSTR.

Maybe even easier, you can use the SWRST bit in I2C_CR1.

JW

Posted on January 13, 2017 at 00:26

Thanks for the reply

meyer.frank

. I pretty much ruled out that it is the slave (a LIDAR Lite sensor) is causing this problem. When the bus is locked up, I pulled the slave off and the lines remained low, so it is pretty clear that the master is the one holding on to the bus. I also implemented a reset function that software clocks the CLK line to help clear the bus if it is the slave is the one holding on.

The problem I have is that during my reset operation, just the deinit and init of the I2C does not clear the bus lines

I can power cycle the slaves but I don't think the slaves are the problem.

Thanks for the response.

Posted on January 13, 2017 at 01:01

Hi

Waclawek.Jan

,

That was the type of answer I was hoping for. Thanks!

Found the SWRST bit in the I2C_CR1 register and when I assert that bit just before I deinit the I2C, I can see it clears the bus lines so it seems to reset the I2C.

So my reset functions now clears the I2C peripheral, bus lines are back up. HAL driver reports no errors and status ready.

However, the next time it does a write operation, it locks up completely.HAL_I2C_MasterTransmitIT reports OK and thenthe SDA goes low for the start followed by the CLK also going low. However,both SDA and CLK now stay low until the timeout hits (20ms).

Again on the scope I can see from the low level on the SDA/SCL lines that is is the master holding them low. If it is the slave the level would be lower.

When I detect the timeout, I do my reset function again and that clears the SDA/CLK lines and then at the next write attempt the lines go low and stay low again.

So on my scope, I have this nice 1ms positive pulse repeating every 20ms :( and communications does not recover.

I as able to trace on Saleae Logic the transactions leading up to the point of failure.It seams that the master just stops clocking and locks up in the middle of the operation.

0690X000006061FQAQ.png

After this, the bus stays high for 30ms or so and then both SCK and SDA go low. Then I hit a timeout and I start doing the resets resulting in the 20ms pulse train.

0690X000006060WQAQ.png

So I am still stuck :(

Bit banging looks awfully good now :(

Any further suggestions?

S.Ma
Principal
Posted on January 13, 2017 at 03:35

I2C bus error recovery usually can happen when slave sends 0x00 and master resets during transmission, or in bus glitches. Bitbang 9 stop bits or more to get both lined raised in order to free the bus and be able to do a start bit again. Unless of a permanent clock stretching by slave, you can be sure of a turnaround bit within 9 clock periods. Smbus has clock stretch timeout as improvement feature. All the best!

Posted on January 13, 2017 at 11:18

Want a suggestion? Drop Cube and write your own code.

You can also try the other reset method I mentioned (through APBxRSTR in RCC).

JW

Posted on January 13, 2017 at 12:06

Your first post sounded as the issue is probably on the slave side.

I pulled the slave off and the lines remained low, ...

I guess you are aware that the pull-up resistors must 'stay in place' while pulling the slave, else you measure something else ...

BTW, I would second Jan's suggestion to drop Cube.

For the F407, you still have the SPL available, which exhibits much less 'instabilities'. Or go directly to the Ref.Manual, without library.

Posted on January 13, 2017 at 12:08

Tried the RCC reset also and both with the SWRST. Still same problem :-(. I2C peripheral in the STM locks up hard after the reset on a first error.

When I look at that first image that I posted above, it looks like it clocked 8 bits and then the clock for the ACK/NAK is missing. Would the HAL driver have missed that event?

I am slowly getting used to the idea that I might have to drop the HAL code for the I2C but it is a not a happy thought. I already spend way more time on getting this @♯$♯$% I2C to work properly than I have available.

Want to make sure I explored all other possible avenues before I go down that path.

Posted on January 13, 2017 at 12:15

Yes, the pull ups are on my PCB.

The LIDAR Lite sensor is on a short cable attached to the PCB so it can be unplugged while the pull ups are still in place.

Have not used the SPL before, but it might be worth a try before going fully bare metal.

Thanks for the suggestions.

Regards,

Marco