Electronics > Microcontrollers

STM32F4 avoid I2C busy flag due to slave clock pulse

(1/2) > >>

3dgeo:
Howdy,

by design slave IC pusles SCL (when I2C is not used) every time data is ready. While testing with Arduino environment and UNO board those pulses did not give any trouble. But when used with STM32 (HAL) I2C due to those pulses gets stuck. Salt to the wound is that my first I2C command is to dissable those INT signals (have no idea why they set it on by dafault).

Tested with logic analyser and debug tools (register states).

Now lets get technical...
Reference manual states:
I2C interface can operate in one of the four following modes:
• Slave transmitter
• Slave receiver
• Master transmitter
• Master receiver
By default, it operates in slave mode. The interface automatically switches from slave to
master, after it generates a START condition and from master to slave, if an arbitration loss
or a Stop generation occurs, allowing multimaster capability.

From what I found there is no way to force I2C to be in master mode all the time.
So in slave mode MCU assumes data is being sent and trigers busy flag:
I2C Status register 2 (I2C_SR2)
Bit 1 BUSY: Bus busy
0: No communication on the bus
1: Communication ongoing on the bus
– Set by hardware on detection of SDA or SCL low
– cleared by hardware on detection of a Stop condition.

It indicates a communication in progress on the bus. This information is still updated when
the interface is disabled (PE=0).

Alrighty then, lets triger START condition on I2C init so MCU would stay in Master mode, as that register R/W that might help, right?
Master mode is selected as soon as the Start condition is generated on the bus with a START bit.
Set the START bit in the I2C_CR1 register to generate a Start condition

I've tried writing START bit on I2C peri setup, did not help – bit still stays 0.

At this point my only valid idea is to disable INTs by bitbanging and then init I2C peri, but that is not a solution I would be happy in a long run...

Any ideas?
 

EDIT:
Made a picture with bitbanging in effect:

newbrain:
Apart from bitabanging, maybe the easiest solution would be to just buffer SCL, if the I2C target does not use clock stretching and avoids generating an INT pulse if it recognise a START condition.
There might be critical races though, if the target drive SCL and the controller drives SDA at exactly the same time...

3dgeo:

--- Quote from: newbrain on August 13, 2022, 07:36:14 pm ---Apart from bitabanging, maybe the easiest solution would be to just buffer SCL, if the I2C target does not use clock stretching and avoids generating an INT pulse if it recognise a START condition.
There might be critical races though, if the target drive SCL and the controller drives SDA at exactly the same time...

--- End quote ---

Can you elaborate? What do you mean by buffer SCL? I've tried many things to make it work, it seems as soon as IO gets binded I2C gets stuck and setting any I2C register prior seems to have no effect.
That IC do not disturb I2C if communication is in progress or any of the I2C pin is low.

I even find F/S bits in I2C_CCR register:
F/S: I2C master mode selection  0: Sm mode I2C    1: Fm mode I2C
Even tho I mannaged to set it I2C still breaks.

Well, good news that bitbanging works, tho as I've wrote – that is not a solution I'm happy with...

cv007:
Maybe you can leave the scl pin as default alternate function (input mode), then switch to scl alternate function when a start is done and back to af0 when the transaction is completed. The i2c will not see scl in af0, but I do not know what state it would see since there is no pin routing to the i2c.

If it works, at least you are basically doing something that is already being done (setting up scl pin).

3dgeo:

--- Quote from: cv007 on August 14, 2022, 02:19:16 am ---Maybe you can leave the scl pin as default alternate function (input mode), then switch to scl alternate function when a start is done and back to af0 when the transaction is completed. The i2c will not see scl in af0, but I do not know what state it would see since there is no pin routing to the i2c.

If it works, at least you are basically doing something that is already being done (setting up scl pin).

--- End quote ---


HAL resets I2C after IO setup (toggle CR1 SWRST), I'm pretty sure reason of it is that I2C gets BUSY flag from assigning IO to it (IO state change detected), so any play with IO will give BUSY state (tried commenting out line where IO gets assigned to I2C alternative function – BUSY state). And if I reset I2C it will get BUSY state from INT pulse.
It seems playing with IO will not give desired result, my only hope is I2C_CCR F/S bits (or maybe START bit) – need to find out if F/S bit locks I2C in to master mode or is it only a suggestion and I2C still acts as a slave until START condition.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version