Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch.embedded > #31391 > unrolled thread

I2C bus recovery

Started bypozz <pozzugno@gmail.com>
First post2022-11-08 16:08 +0100
Last post2022-11-13 10:52 +0000
Articles 8 — 5 participants

Back to article view | Back to comp.arch.embedded


Contents

  I2C bus recovery pozz <pozzugno@gmail.com> - 2022-11-08 16:08 +0100
    Re: I2C bus recovery antispam@math.uni.wroc.pl - 2022-11-08 22:08 +0000
      Re: I2C bus recovery pozz <pozzugno@gmail.com> - 2022-11-09 08:32 +0100
        Re: I2C bus recovery Richard Damon <Richard@Damon-Family.org> - 2022-11-10 07:12 -0500
          Re: I2C bus recovery Rick C <gnuarm.deletethisbit@gmail.com> - 2022-11-10 09:06 -0800
          Re: I2C bus recovery pozz <pozzugno@gmail.com> - 2022-11-10 23:39 +0100
        Re: I2C bus recovery antispam@math.uni.wroc.pl - 2022-11-10 17:26 +0000
        Re: I2C bus recovery Michael Schwingen <news-1513678000@discworld.dascon.de> - 2022-11-13 10:52 +0000

#31391 — I2C bus recovery

Frompozz <pozzugno@gmail.com>
Date2022-11-08 16:08 +0100
SubjectI2C bus recovery
Message-ID<tkdre4$3s0fi$1@dont-email.me>
I wanted to implement an I2C bus recovery during initialization. The 
reason is well known in literature[1].

I read the function i2c_generic_recovery[2] of Linux kernel, but I don't 
understand one thing.

The bus recovery is necessary to bring a slave to the end of a byte 
transmission that could be interrupted for some reason.
However the slave could be transmitting 0xFF, so why the above function 
breaks the loop if SDA is detected high?

     [Line 620] /* Break if SDA is high */

Maybe it's better to send 9 clock cycles whatever the level of SDA line.

And what about STOP condition at the end of the 9 clock cycles? Is it 
necessary? It should be (SCL is already high): set SDA low, pause, set 
SDA high.

Do you use this sort of bus recovery?


[1] 
https://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf

[2] https://elixir.bootlin.com/linux/v4.5/source/drivers/i2c/i2c-core.c#L604

[toc] | [next] | [standalone]


#31392

Fromantispam@math.uni.wroc.pl
Date2022-11-08 22:08 +0000
Message-ID<tkek1k$viu$1@gioia.aioe.org>
In reply to#31391
pozz <pozzugno@gmail.com> wrote:
> I wanted to implement an I2C bus recovery during initialization. The 
> reason is well known in literature[1].
> 
> I read the function i2c_generic_recovery[2] of Linux kernel, but I don't 
> understand one thing.
> 
> The bus recovery is necessary to bring a slave to the end of a byte 
> transmission that could be interrupted for some reason.
> However the slave could be transmitting 0xFF, so why the above function 
> breaks the loop if SDA is detected high?
> 
>     [Line 620] /* Break if SDA is high */

With normal devices start followed by stop should reset state of the bus.
Howere, to send start we need SDA high.  If this is bus with single
master SDA should be high at least at the end of byte (bus should
flat high as device waits for ACK).
> 
> Maybe it's better to send 9 clock cycles whatever the level of SDA line.

I am not sure if this helps: writer is supposed to stop seeing new
start, so it is not clear if extra clock give anything for writers.
OTOH, if bus is clocked reader could get wrong data, so it seem
better to reset bus as soon as possible (that is first time when
SDA is high).
> 
> And what about STOP condition at the end of the 9 clock cycles? Is it 
> necessary? It should be (SCL is already high): set SDA low, pause, set 
> SDA high.
> 
> Do you use this sort of bus recovery?

Well, I plan to do so.  But I do not like to use untested code,
and to preperly test it I would need special driver to inject
various upsets to I2C bus.

> 
> [1] 
> https://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf
> 
> [2] https://elixir.bootlin.com/linux/v4.5/source/drivers/i2c/i2c-core.c#L604

-- 
                              Waldek Hebisch

[toc] | [prev] | [next] | [standalone]


#31395

Frompozz <pozzugno@gmail.com>
Date2022-11-09 08:32 +0100
Message-ID<tkfl2t$5tl0$1@dont-email.me>
In reply to#31392
Il 08/11/2022 23:08, antispam@math.uni.wroc.pl ha scritto:
> pozz <pozzugno@gmail.com> wrote:
>> I wanted to implement an I2C bus recovery during initialization. The
>> reason is well known in literature[1].
>>
>> I read the function i2c_generic_recovery[2] of Linux kernel, but I don't
>> understand one thing.
>>
>> The bus recovery is necessary to bring a slave to the end of a byte
>> transmission that could be interrupted for some reason.
>> However the slave could be transmitting 0xFF, so why the above function
>> breaks the loop if SDA is detected high?
>>
>>      [Line 620] /* Break if SDA is high */
> 
> With normal devices start followed by stop should reset state of the bus.
> Howere, to send start we need SDA high.  If this is bus with single
> master SDA should be high at least at the end of byte (bus should
> flat high as device waits for ACK).

Do you think that a slave transmitting 0xFF interrupts the transmission 
in the middle as soon as it detects a falling transition on SDA (STOP)?

Anyway, in this case the STOP transmission is necessary after reading 
SDA high. I couldn't find the STOP transmission in the Linux kernel 
code, only a few clock cycles until SDA is detected high.


>> Maybe it's better to send 9 clock cycles whatever the level of SDA line.
> 
> I am not sure if this helps: writer is supposed to stop seeing new
> start, so it is not clear if extra clock give anything for writers.

Yes, if the slave transmitting something stops after seeing a STOP (SDA 
going low). I don't know it this is a well-known specification and if 
all the I2C slaves implement this specification correctly.


> OTOH, if bus is clocked reader could get wrong data, so it seem
> better to reset bus as soon as possible (that is first time when
> SDA is high).

What do you mean with reader? When the bus is stuck, the writer is the 
slave and the reader should be the master that is trying to recovery the 
bus, so technically it is not reading anything.

Are you thinking of a bus with multiple slaves? They shouldn't be 
reading anything.


>> And what about STOP condition at the end of the 9 clock cycles? Is it
>> necessary? It should be (SCL is already high): set SDA low, pause, set
>> SDA high.
>>
>> Do you use this sort of bus recovery?
> 
> Well, I plan to do so.  But I do not like to use untested code,
> and to preperly test it I would need special driver to inject
> various upsets to I2C bus.

Yes, this should be ideal, but it's not simple to inject errors in the 
I2C bus, so I asked for some ideas and suggestions.


>> [1]
>> https://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf
>>
>> [2] https://elixir.bootlin.com/linux/v4.5/source/drivers/i2c/i2c-core.c#L604
> 

[toc] | [prev] | [next] | [standalone]


#31403

FromRichard Damon <Richard@Damon-Family.org>
Date2022-11-10 07:12 -0500
Message-ID<7V5bL.79500$2Rs3.1129@fx12.iad>
In reply to#31395
On 11/9/22 2:32 AM, pozz wrote:
> Il 08/11/2022 23:08, antispam@math.uni.wroc.pl ha scritto:
>> pozz <pozzugno@gmail.com> wrote:
>>> I wanted to implement an I2C bus recovery during initialization. The
>>> reason is well known in literature[1].
>>>
>>> I read the function i2c_generic_recovery[2] of Linux kernel, but I don't
>>> understand one thing.
>>>
>>> The bus recovery is necessary to bring a slave to the end of a byte
>>> transmission that could be interrupted for some reason.
>>> However the slave could be transmitting 0xFF, so why the above function
>>> breaks the loop if SDA is detected high?
>>>
>>>      [Line 620] /* Break if SDA is high */
>>
>> With normal devices start followed by stop should reset state of the bus.
>> Howere, to send start we need SDA high.  If this is bus with single
>> master SDA should be high at least at the end of byte (bus should
>> flat high as device waits for ACK).
> 
> Do you think that a slave transmitting 0xFF interrupts the transmission 
> in the middle as soon as it detects a falling transition on SDA (STOP)?

IT is suppossed to if it meets the standard. ANY change of SDA when SCL 
is High resets the logic of every device on the bus in response to the 
Start or Stop bit just sent.

> 
> Anyway, in this case the STOP transmission is necessary after reading 
> SDA high. I couldn't find the STOP transmission in the Linux kernel 
> code, only a few clock cycles until SDA is detected high.

You don't need a STOP, you need either a start or stop. When you enable 
the I2C controller and start a transmission, it will begin with a start, 
and that will provide the needed reset.

> 
> 
>>> Maybe it's better to send 9 clock cycles whatever the level of SDA line.
>>
>> I am not sure if this helps: writer is supposed to stop seeing new
>> start, so it is not clear if extra clock give anything for writers.
> 
> Yes, if the slave transmitting something stops after seeing a STOP (SDA 
> going low). I don't know it this is a well-known specification and if 
> all the I2C slaves implement this specification correctly.
> 

It is a well known requirement of the I2C specification that any start 
or stop bit needs to reset the logic of devices.

Not all devices support it though, but if you have one that doesn't and 
you get stuck like this, your only answer is some other form of reset 
(like a power cycle).

> 
>> OTOH, if bus is clocked reader could get wrong data, so it seem
>> better to reset bus as soon as possible (that is first time when
>> SDA is high).
> 
> What do you mean with reader? When the bus is stuck, the writer is the 
> slave and the reader should be the master that is trying to recovery the 
> bus, so technically it is not reading anything.
> 
> Are you thinking of a bus with multiple slaves? They shouldn't be 
> reading anything.
> 
> 
>>> And what about STOP condition at the end of the 9 clock cycles? Is it
>>> necessary? It should be (SCL is already high): set SDA low, pause, set
>>> SDA high.
>>>
>>> Do you use this sort of bus recovery?
>>
>> Well, I plan to do so.  But I do not like to use untested code,
>> and to preperly test it I would need special driver to inject
>> various upsets to I2C bus.
> 
> Yes, this should be ideal, but it's not simple to inject errors in the 
> I2C bus, so I asked for some ideas and suggestions.
> 
> 
>>> [1]
>>> https://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf
>>>
>>> [2] 
>>> https://elixir.bootlin.com/linux/v4.5/source/drivers/i2c/i2c-core.c#L604
>>
> 

[toc] | [prev] | [next] | [standalone]


#31405

FromRick C <gnuarm.deletethisbit@gmail.com>
Date2022-11-10 09:06 -0800
Message-ID<390366cd-90ba-44c0-80ae-fd3a2cb1e0b1n@googlegroups.com>
In reply to#31403
On Thursday, November 10, 2022 at 8:12:57 AM UTC-4, Richard Damon wrote:
> On 11/9/22 2:32 AM, pozz wrote: 
> > Il 08/11/2022 23:08, anti...@math.uni.wroc.pl ha scritto: 
> >> pozz <pozz...@gmail.com> wrote: 
> >>> I wanted to implement an I2C bus recovery during initialization. The 
> >>> reason is well known in literature[1]. 
> >>> 
> >>> I read the function i2c_generic_recovery[2] of Linux kernel, but I don't 
> >>> understand one thing. 
> >>> 
> >>> The bus recovery is necessary to bring a slave to the end of a byte 
> >>> transmission that could be interrupted for some reason. 
> >>> However the slave could be transmitting 0xFF, so why the above function 
> >>> breaks the loop if SDA is detected high? 
> >>> 
> >>>      [Line 620] /* Break if SDA is high */ 
> >> 
> >> With normal devices start followed by stop should reset state of the bus. 
> >> Howere, to send start we need SDA high.  If this is bus with single 
> >> master SDA should be high at least at the end of byte (bus should 
> >> flat high as device waits for ACK). 
> > 
> > Do you think that a slave transmitting 0xFF interrupts the transmission 
> > in the middle as soon as it detects a falling transition on SDA (STOP)?
> IT is suppossed to if it meets the standard. ANY change of SDA when SCL 
> is High resets the logic of every device on the bus in response to the 
> Start or Stop bit just sent.
> > 
> > Anyway, in this case the STOP transmission is necessary after reading 
> > SDA high. I couldn't find the STOP transmission in the Linux kernel 
> > code, only a few clock cycles until SDA is detected high.
> You don't need a STOP, you need either a start or stop. When you enable 
> the I2C controller and start a transmission, it will begin with a start, 
> and that will provide the needed reset.
> > 
> > 
> >>> Maybe it's better to send 9 clock cycles whatever the level of SDA line. 
> >> 
> >> I am not sure if this helps: writer is supposed to stop seeing new 
> >> start, so it is not clear if extra clock give anything for writers. 
> > 
> > Yes, if the slave transmitting something stops after seeing a STOP (SDA 
> > going low). I don't know it this is a well-known specification and if 
> > all the I2C slaves implement this specification correctly. 
> >
> It is a well known requirement of the I2C specification that any start 
> or stop bit needs to reset the logic of devices. 
> 
> Not all devices support it though, but if you have one that doesn't and 
> you get stuck like this, your only answer is some other form of reset 
> (like a power cycle).
> > 
> >> OTOH, if bus is clocked reader could get wrong data, so it seem 
> >> better to reset bus as soon as possible (that is first time when 
> >> SDA is high). 
> > 
> > What do you mean with reader? When the bus is stuck, the writer is the 
> > slave and the reader should be the master that is trying to recovery the 
> > bus, so technically it is not reading anything. 
> > 
> > Are you thinking of a bus with multiple slaves? They shouldn't be 
> > reading anything. 
> > 
> > 
> >>> And what about STOP condition at the end of the 9 clock cycles? Is it 
> >>> necessary? It should be (SCL is already high): set SDA low, pause, set 
> >>> SDA high. 
> >>> 
> >>> Do you use this sort of bus recovery? 
> >> 
> >> Well, I plan to do so.  But I do not like to use untested code, 
> >> and to preperly test it I would need special driver to inject 
> >> various upsets to I2C bus. 
> > 
> > Yes, this should be ideal, but it's not simple to inject errors in the 
> > I2C bus, so I asked for some ideas and suggestions. 

This is why when Intel wanted to use I2C on their motherboards, they made and improvement to have a time out on the bus, so all devices could reset out of a hang condition.  I forget the name of their version, SMbus or something like that. 

If you use chips rated for their spec, they will work.

-- 

Rick C.

--+++ Get 1,000 miles of free Supercharging
--+++ Tesla referral code - https://ts.la/richard11209 

[toc] | [prev] | [next] | [standalone]


#31408

Frompozz <pozzugno@gmail.com>
Date2022-11-10 23:39 +0100
Message-ID<tkjujg$kp0d$1@dont-email.me>
In reply to#31403
Il 10/11/2022 13:12, Richard Damon ha scritto:
> On 11/9/22 2:32 AM, pozz wrote:
>> Il 08/11/2022 23:08, antispam@math.uni.wroc.pl ha scritto:
>>> pozz <pozzugno@gmail.com> wrote:
>>>> I wanted to implement an I2C bus recovery during initialization. The
>>>> reason is well known in literature[1].
>>>>
>>>> I read the function i2c_generic_recovery[2] of Linux kernel, but I 
>>>> don't
>>>> understand one thing.
>>>>
>>>> The bus recovery is necessary to bring a slave to the end of a byte
>>>> transmission that could be interrupted for some reason.
>>>> However the slave could be transmitting 0xFF, so why the above function
>>>> breaks the loop if SDA is detected high?
>>>>
>>>>      [Line 620] /* Break if SDA is high */
>>>
>>> With normal devices start followed by stop should reset state of the 
>>> bus.
>>> Howere, to send start we need SDA high.  If this is bus with single
>>> master SDA should be high at least at the end of byte (bus should
>>> flat high as device waits for ACK).
>>
>> Do you think that a slave transmitting 0xFF interrupts the 
>> transmission in the middle as soon as it detects a falling transition 
>> on SDA (STOP)?
> 
> IT is suppossed to if it meets the standard. ANY change of SDA when SCL 
> is High resets the logic of every device on the bus in response to the 
> Start or Stop bit just sent.
> 
>>
>> Anyway, in this case the STOP transmission is necessary after reading 
>> SDA high. I couldn't find the STOP transmission in the Linux kernel 
>> code, only a few clock cycles until SDA is detected high.
> 
> You don't need a STOP, you need either a start or stop. When you enable 
> the I2C controller and start a transmission, it will begin with a start, 
> and that will provide the needed reset.

I see, anyway I was looking at an old Linux kernel code. In the actual 
code[1], a STOP condition is really sent before exitigin bus recovery 
function.

[1] 
https://github.com/torvalds/linux/blob/master/drivers/i2c/i2c-core-base.c#L200


>>>> Maybe it's better to send 9 clock cycles whatever the level of SDA 
>>>> line.
>>>
>>> I am not sure if this helps: writer is supposed to stop seeing new
>>> start, so it is not clear if extra clock give anything for writers.
>>
>> Yes, if the slave transmitting something stops after seeing a STOP 
>> (SDA going low). I don't know it this is a well-known specification 
>> and if all the I2C slaves implement this specification correctly.
>>
> 
> It is a well known requirement of the I2C specification that any start 
> or stop bit needs to reset the logic of devices.
> 
> Not all devices support it though, but if you have one that doesn't and 
> you get stuck like this, your only answer is some other form of reset 
> (like a power cycle).

Oh yes, I thought that a slave that had started a byte transmission 
needed to receive 9 clock cycles to go to the end and reset its internal 
state-machine.  From what you say, this is not true. Even when a STOP 
condition is detected in the middle of a byte transmissione, the I2C 
device should reset I2C state machine.

Of course, if this I2C slave device is transmitting 0 (keeping SDA low), 
it's impossible to create a STOP or START condition from the master. The 
master needs to send clock cycle until the slave release SDA (because 
the byte transmission is really finished or because it is transmitting a 1).


>>> OTOH, if bus is clocked reader could get wrong data, so it seem
>>> better to reset bus as soon as possible (that is first time when
>>> SDA is high).
>>
>> What do you mean with reader? When the bus is stuck, the writer is the 
>> slave and the reader should be the master that is trying to recovery 
>> the bus, so technically it is not reading anything.
>>
>> Are you thinking of a bus with multiple slaves? They shouldn't be 
>> reading anything.
>>
>>
>>>> And what about STOP condition at the end of the 9 clock cycles? Is it
>>>> necessary? It should be (SCL is already high): set SDA low, pause, set
>>>> SDA high.
>>>>
>>>> Do you use this sort of bus recovery?
>>>
>>> Well, I plan to do so.  But I do not like to use untested code,
>>> and to preperly test it I would need special driver to inject
>>> various upsets to I2C bus.
>>
>> Yes, this should be ideal, but it's not simple to inject errors in the 
>> I2C bus, so I asked for some ideas and suggestions.
>>
>>
>>>> [1]
>>>> https://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf
>>>>
>>>> [2] 
>>>> https://elixir.bootlin.com/linux/v4.5/source/drivers/i2c/i2c-core.c#L604
>>>
>>
> 

[toc] | [prev] | [next] | [standalone]


#31406

Fromantispam@math.uni.wroc.pl
Date2022-11-10 17:26 +0000
Message-ID<tkjc7o$bna$1@gioia.aioe.org>
In reply to#31395
pozz <pozzugno@gmail.com> wrote:
> Il 08/11/2022 23:08, antispam@math.uni.wroc.pl ha scritto:
> > pozz <pozzugno@gmail.com> wrote:
> >> I wanted to implement an I2C bus recovery during initialization. The
> >> reason is well known in literature[1].
> >>
> >> I read the function i2c_generic_recovery[2] of Linux kernel, but I don't
> >> understand one thing.
> >>
> >> The bus recovery is necessary to bring a slave to the end of a byte
> >> transmission that could be interrupted for some reason.
> >> However the slave could be transmitting 0xFF, so why the above function
> >> breaks the loop if SDA is detected high?
> >>
> >>      [Line 620] /* Break if SDA is high */
> > 
> > With normal devices start followed by stop should reset state of the bus.
> > Howere, to send start we need SDA high.  If this is bus with single
> > master SDA should be high at least at the end of byte (bus should
> > flat high as device waits for ACK).
> 
> Do you think that a slave transmitting 0xFF interrupts the transmission 
> in the middle as soon as it detects a falling transition on SDA (STOP)?
> 
> Anyway, in this case the STOP transmission is necessary after reading 
> SDA high. I couldn't find the STOP transmission in the Linux kernel 
> code, only a few clock cycles until SDA is detected high.
> 
> 
> >> Maybe it's better to send 9 clock cycles whatever the level of SDA line.
> > 
> > I am not sure if this helps: writer is supposed to stop seeing new
> > start, so it is not clear if extra clock give anything for writers.
> 
> Yes, if the slave transmitting something stops after seeing a STOP (SDA 
> going low). I don't know it this is a well-known specification and if 
> all the I2C slaves implement this specification correctly.
> 
> 
> > OTOH, if bus is clocked reader could get wrong data, so it seem
> > better to reset bus as soon as possible (that is first time when
> > SDA is high).
> 
> What do you mean with reader? When the bus is stuck, the writer is the 
> slave and the reader should be the master that is trying to recovery the 
> bus, so technically it is not reading anything.
> 
> Are you thinking of a bus with multiple slaves? They shouldn't be 
> reading anything.

If you see low on SDA this could be writer slave sending 0 or
reader slave sending ACK.

-- 
                              Waldek Hebisch

[toc] | [prev] | [next] | [standalone]


#31411

FromMichael Schwingen <news-1513678000@discworld.dascon.de>
Date2022-11-13 10:52 +0000
Message-ID<slrntn1j30.28h.news-1513678000@a-tuin.ms.intern>
In reply to#31395
On 2022-11-09, pozz <pozzugno@gmail.com> wrote:
>> 
>> Well, I plan to do so.  But I do not like to use untested code,
>> and to preperly test it I would need special driver to inject
>> various upsets to I2C bus.
>
> Yes, this should be ideal, but it's not simple to inject errors in the 
> I2C bus, so I asked for some ideas and suggestions.

I had the same problem (testing error recovery code paths, and getting the
"stop at the right time" working on a STM32F1), so I made a special test
slave based on an AtMega88:

https://www.schwingen.org/i2c-fault-injection/

(You can use an arduino nano if you don't want to build your own PCB).

Together with test code on your host, and maybe a logic analyzer, this
allows rapidly testing lots of error events.

cu
Michael

[toc] | [prev] | [standalone]


Back to top | Article view | comp.arch.embedded


csiph-web