Author Topic: STM32F4 avoid I2C busy flag due to slave clock pulse  (Read 894 times)

0 Members and 1 Guest are viewing this topic.

Offline 3dgeo

  • Frequent Contributor
  • **
  • Posts: 276
  • Country: au
STM32F4 avoid I2C busy flag due to slave clock pulse
« on: August 13, 2022, 02:09:41 pm »
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:
« Last Edit: August 14, 2022, 10:41:33 am by 3dgeo »
 

Online newbrain

  • Super Contributor
  • ***
  • Posts: 1525
  • Country: se
Re: STM32F4 avoid I2C busy flag due to slave clock pulse
« Reply #1 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...
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline 3dgeo

  • Frequent Contributor
  • **
  • Posts: 276
  • Country: au
Re: STM32F4 avoid I2C busy flag due to slave clock pulse
« Reply #2 on: August 13, 2022, 11:36:57 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...

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...
« Last Edit: August 13, 2022, 11:58:55 pm by 3dgeo »
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 680
Re: STM32F4 avoid I2C busy flag due to slave clock pulse
« Reply #3 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).
« Last Edit: August 14, 2022, 05:40:18 am by cv007 »
 

Offline 3dgeo

  • Frequent Contributor
  • **
  • Posts: 276
  • Country: au
Re: STM32F4 avoid I2C busy flag due to slave clock pulse
« Reply #4 on: August 14, 2022, 10:05:24 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).


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.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 6062
  • Country: fi
Re: STM32F4 avoid I2C busy flag due to slave clock pulse
« Reply #5 on: August 14, 2022, 12:30:28 pm »
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

Remotely possible, but quite wild assumption. You should try it.

The fact HAL doesn't make it easy just shows where you are going wrong: you are using the HAL. When it works out of the box, it's great, but when it doesn't, working around it is a misery.
 

Online newbrain

  • Super Contributor
  • ***
  • Posts: 1525
  • Country: se
Re: STM32F4 avoid I2C busy flag due to slave clock pulse
« Reply #6 on: August 14, 2022, 03:14:23 pm »
Can you elaborate?
Using a HW buffer to isolate the MCU pin from the distributed SCL - so that the MCU will not "see" the pulse.
As said only works if clock stretching is not used (probable).
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline 3dgeo

  • Frequent Contributor
  • **
  • Posts: 276
  • Country: au
Re: STM32F4 avoid I2C busy flag due to slave clock pulse
« Reply #7 on: August 15, 2022, 08:50:55 am »
Can you elaborate?
Using a HW buffer to isolate the MCU pin from the distributed SCL - so that the MCU will not "see" the pulse.
As said only works if clock stretching is not used (probable).

You mean like transistor to isolate IC that generates INT? Adding any hardware due to this issue is even worse than bitbnging.
After few days of testing have to say bitbanging works, maybe not very elegant solution to get rid of those pusles, but after hardware IC2 takes over and everything works fine – added a picture to my main post.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 6062
  • Country: fi
Re: STM32F4 avoid I2C busy flag due to slave clock pulse
« Reply #8 on: August 15, 2022, 09:01:47 am »
Bitbanging I2C is fine. MCU I2C peripherals are notoriously buggy (and vary a lot between MCUs, even just product families of same MCU brand), and I2C is low-speed configuration bus, really, so speed doesn't usually matter. Write good bitbang implementation once and you will be able to use it in future projects, and get exactly what you need.
 

Offline wek

  • Regular Contributor
  • *
  • Posts: 235
  • Country: sk
Re: STM32F4 avoid I2C busy flag due to slave clock pulse
« Reply #9 on: August 15, 2022, 05:01:26 pm »
Bitbanging I2C is fine.
+1
MCU I2C peripherals are notoriously buggy
Yes, but I2C slave driving SCL blatantly violates the standard. So, who's the culprit here.

(Btw. I'd like to know what's the slave. According to the waveform in the OP, responding to several different addresses, so the I2C standard was interpreted very loosely by that particular vendor.)

But in this particular case, you can play along, too. Set the pin you use for SCL to throw an interrupt, and when that pulse is finished, reset the I2C module (either using its dedicated reset bit - it's there for a reason - or in RCC - yes, that dedicated reset bit is redundant), set it up as needed, conduct any communication needed, and then shut it down and wait for the next interrupt pin. Timeouts, recovery etc. in place as needed.

JW
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf