STM32F4 avoid I2C busy flag due to slave clock pulse - Page 1
Forum section: electronics / general

author: 3dgeo
author_rank: Frequent Contributor
timestamp: August 13, 2022, 02:09:41 pm
content: Howdy,by designslave 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 manualstates:I2C interface can operate in one of the four following modes:• Slave transmitter• Slave receiver• Master transmitter• Master receiverBy default, it operates in slave mode. The interface automatically switches from slave tomaster, after it generates a START condition and from master to slave, if an arbitration lossor 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 busy0: No communication on the bus1: 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 whenthe 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 conditionI'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:

author: newbrain
author_rank: Super Contributor
timestamp: August 13, 2022, 07:36:14 pm
content: 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...

author: 3dgeo
author_rank: Frequent Contributor
timestamp: August 13, 2022, 11:36:57 pm
content: Quote from: newbrain on August 13, 2022, 07:36:14 pmCan 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 I2CEven 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...

author: cv007
author_rank: Frequent Contributor
timestamp: August 14, 2022, 02:19:16 am
content: 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).

author: 3dgeo
author_rank: Frequent Contributor
timestamp: August 14, 2022, 10:05:24 am
content: Quote from: cv007 on August 14, 2022, 02:19:16 amHAL 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 asuggestionand I2C still acts as a slave until START condition.

author: Siwastaja
author_rank: Super Contributor
timestamp: August 14, 2022, 12:30:28 pm
content: Quote from: 3dgeo on August 14, 2022, 10:05:24 amRemotely 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.

author: newbrain
author_rank: Super Contributor
timestamp: August 14, 2022, 03:14:23 pm
content: Quote from: 3dgeo on August 13, 2022, 11:36:57 pmUsing 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).

author: 3dgeo
author_rank: Frequent Contributor
timestamp: August 15, 2022, 08:50:55 am
content: Quote from: newbrain on August 14, 2022, 03:14:23 pmYou 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.

author: Siwastaja
author_rank: Super Contributor
timestamp: August 15, 2022, 09:01:47 am
content: 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.

author: wek
author_rank: Frequent Contributor
timestamp: August 15, 2022, 05:01:26 pm
content: Quote from: Siwastaja on August 15, 2022, 09:01:47 am+1Quote from: Siwastaja on August 15, 2022, 09:01:47 amYes, 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