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


Groups > comp.arch.embedded > #30101

Re: I2C Single Master: peripheral or bit banging?

From pozz <pozzugno@gmail.com>
Newsgroups comp.arch.embedded
Subject Re: I2C Single Master: peripheral or bit banging?
Date 2020-11-20 12:45 +0100
Organization A noiseless patient Spider
Message-ID <rp8a8d$lh4$1@dont-email.me> (permalink)
References <rp7vjk$edg$1@dont-email.me> <rp86am$nr9$1@newsreader4.netcologne.de>

Show all headers | View raw


Il 20/11/2020 11:38, Bernd Linsel ha scritto:
 > On 20.11.2020 09:43, pozz wrote:
 >> I hate I2C for several reasons. It's only two-wires bus, but for this
 >> reason it is insidious.
 >>
 >> I usually use hw peripherals when they are available, because it's
 >> much more efficient and smart and because it's the only possibility in
 >> many cases.
 >> Actually we have MCUs with abundant UARTs, timers and so on, so
 >> there's no real story: choose a suitable MCU and use that damn
 >> peripheral.
 >> So I usually start using I2C peripherals available in MCUs, but I
 >> found many issues.
 >>
 >> I have experience with AVR8 and SAMC21 by Atmel/Microchip. In both
 >> cases the I2C peripheral is much more complex than UART or similar
 >> serial lines. I2C Single Master, that is the most frequent situation,
 >> is very simple, but I2C Multi Master introduces many critical 
situations.
 >> I2C peripherals usually promise to be compatible with multi-master, so
 >> their internal state machine is somewhat complex... and often there's
 >> some bug or situations that aren't expected that leave the code stucks
 >> at some point.
 >>
 >> I want to write reliable code that not only works most of the time,
 >> but that works ALL the time, in any situations (ok, 99%). So my first
 >> test with I2C is making a temporary short between SCL and SDA. In this
 >> case, I2C in SAMC21 (they named it SERCOM in I2C Master mode) hangs
 >> forever. The manual says to write ADDR register to start putting the
 >> address on the bus and wait for an interrupt flag when it ends. This
 >> interrupt is never fired up. I see the lines goes down (because START
 >> bit is putting low SDA before SCL), but the INTFLAG bits stay cleared
 >> forever. Even error bits in STATUS register (bus error, arbitration
 >> lost, any sort of timeout...) stay cleared and the BUSSTATE is IDLE.
 >> As soon as the short is removed, the state-machine goes on.
 >>
 >> Maybe I'm wrong, so I studied Atmel Software Framework[1] and Arduino
 >> Wire libraries[2]. In both cases, a timeout is implemented at the
 >> driver level.
 >>
 >> Even the datasheet says:
 >>
 >>    "Note:  Violating the protocol may cause the I2C to hang. If this
 >>    happens it is possible to recover from this state by a
 >>    software reset (CTRLA.SWRST='1')."
 >>
 >> I think the driver code should trust the hw, between them there's a
 >> contract, otherwise it's impossibile. For a UART driver, you write
 >> DATA register and wait an interrupt flag when a new data can be
 >> written in the register. If the interrupt nevers fire, the driver
 >> hangs forever.
 >> But I have never seen a UART driver that uses a timeout to recover
 >> from a hardware that could hang. And I used UARTs for many years now.
 >>
 >>
 >> Considering all these big issues when you want to write reliable code,
 >> I'm considering to wipe again the old and good bit banging technique.
 >> For I2C Single Master scenario, it IS very simple: put data low/high
 >> (three-state), put clock low/high. The only problem is to calibrate
 >> the clock frequency, but if you a free timer it will be simple too.
 >>
 >> What is the drawback of bit banging? Maybe you write a few additional
 >> lines of code (you have to spit off 9 clock pulses by code), but I
 >> don't think much more than using a peripheral and protect it with a
 >> timeout.
 >> But you earn a code that is fully under your control and you know when
 >> the I2C transaction starts and you can be sure it will end, even when
 >> there are some hw issues on the board.
 >>
 >>
 >>
 >>
 >>
 >> [1]
 >> 
https://github.com/avrxml/asf/blob/68cddb46ae5ebc24ef8287a8d4c61a6efa5e2848/sam0/drivers/sercom/i2c/i2c_sam0/i2c_master.c#L406 

 >>
 >>
 >> [2]
 >> 
https://github.com/acicuc/ArduinoCore-samd/commit/64385453bb549b6d2f868658119259e605aca74d 

 >>
 >
 > 1. The interrupt will only fire if a connected slave acknowledges the
 > address. If you want to catch the situation of a non-acknowledged start
 > & address byte, you have to set up a timer that times out.
False, at least for SERCOM in I2C Master mode (but I suspect other MCUs 
behaviour is the same).
Quoting from C21 datasheet:

   "If there is no I2C slave device responding to the address packet,
   then the INTFLAG.MB interrupt flag and
   STATUS.RXNACK will be set. The clock hold is active at this point,
   preventing further activity on the bus."


 > 2. I²C is asynchronous, you don't need to keep a fixed bit rate. Just
 > pulse SCL as fast as you can/need (within the spec). Clients can adjust
 > the speed pulling down SCL when they can't keep up with the master's 
speed.
Yes, I know. But you need some pause in bit banging, otherwise you will 
run at a speed too high. And you need a calibration if you use a dumb 
loop on a volatile counter.


 > 3. As you not only have to bit-bang SCL & SDA according to the protocol,
 > but also monitor SCL before you go on, even implementing a s/w I²C
 > master correctly is not trivial; additionally, the CPU load is 
remarkable.
If I'm not wrong, this happens only if you have some slaves that stretch 
the clock to slow down the transfer. Even in this case, I don't think 
monitoring SCL line during the transfer is complex. Yes, you should have 
a timeout, but you need it even when you use hw peripheral.

CPU load? Many times I2C is used in a blocking way waiting for interrupt 
flag. In this case, there's no difference if the CPU waits for an 
interrupt flag or drive SCL and SDA lines.

Even if you need non-blocking driver, you could use a hw timer and bit 
bangs in the interrupt service routine of the timer.


 > If you have difficulties using the I²C peripherals, just have a peek on
 > the according linux driver sources. They are often very reliable (at
 > least for chip families that are a bit mature), and if there exist any
 > issues, they are documented (cf. Raspi's SPI driver bug in the first
 > versions).
I'm talking about MCUs. Linux can't run on these devices.

Back to comp.arch.embedded | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

I2C Single Master: peripheral or bit banging? pozz <pozzugno@gmail.com> - 2020-11-20 09:43 +0100
  Re: I2C Single Master: peripheral or bit banging? Bernd Linsel <bl1@gmx.com> - 2020-11-20 11:38 +0100
    Re: I2C Single Master: peripheral or bit banging? pozz <pozzugno@gmail.com> - 2020-11-20 12:45 +0100
      Re: I2C Single Master: peripheral or bit banging? Bernd Linsel <bl1@gmx.com> - 2020-11-20 15:57 +0100
  Re: I2C Single Master: peripheral or bit banging? Richard Damon <Richard@Damon-Family.org> - 2020-11-20 08:09 -0500
    Re: I2C Single Master: peripheral or bit banging? pozz <pozzugno@gmail.com> - 2020-11-20 15:15 +0100
      Re: I2C Single Master: peripheral or bit banging? Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2020-11-20 17:25 +0200
        Re: I2C Single Master: peripheral or bit banging? pozz <pozzugno@gmail.com> - 2020-11-20 17:33 +0100
          Re: I2C Single Master: peripheral or bit banging? Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2020-11-20 19:39 +0200
            Re: I2C Single Master: peripheral or bit banging? Dimiter_Popoff <dp@tgi-sci.com> - 2020-11-20 23:25 +0200
              Re: I2C Single Master: peripheral or bit banging? Grant Edwards <invalid@invalid.invalid> - 2020-11-20 23:09 +0000
                Re: I2C Single Master: peripheral or bit banging? Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2020-11-21 11:46 +0200
            Re: I2C Single Master: peripheral or bit banging? David Brown <david.brown@hesbynett.no> - 2020-11-21 12:06 +0100
              Re: I2C Single Master: peripheral or bit banging? pozz <pozzugno@gmail.com> - 2020-11-22 17:48 +0100
                Re: I2C Single Master: peripheral or bit banging? David Brown <david.brown@hesbynett.no> - 2020-11-22 19:44 +0100
                Re: I2C Single Master: peripheral or bit banging? pozz <pozzugno@gmail.com> - 2020-11-23 08:44 +0100
                Re: I2C Single Master: peripheral or bit banging? David Brown <david.brown@hesbynett.no> - 2020-11-23 09:42 +0100
                Re: I2C Single Master: peripheral or bit banging? David Brown <david.brown@hesbynett.no> - 2020-11-23 09:44 +0100
                Re: I2C Single Master: peripheral or bit banging? Richard Damon <Richard@Damon-Family.org> - 2020-11-23 07:25 -0500
                Re: I2C Single Master: peripheral or bit banging? Reinhardt Behm <rbehm@hushmail.com> - 2020-11-24 18:15 +0800
  Re: I2C Single Master: peripheral or bit banging? stephen@mpeforth.com (Stephen Pelc) - 2020-11-20 14:53 +0000
  Re: I2C Single Master: peripheral or bit banging? John Speth <johnspeth@yahoo.com> - 2020-11-20 06:56 -0800
  Re: I2C Single Master: peripheral or bit banging? Michael Kellett <mk@mkesc.co.uk> - 2020-11-21 09:10 +0000
    Re: I2C Single Master: peripheral or bit banging? Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2020-11-21 11:48 +0200
    Re: I2C Single Master: peripheral or bit banging? pozz <pozzugno@gmail.com> - 2020-11-22 17:35 +0100
      Re: I2C Single Master: peripheral or bit banging? Michael Kellett <mk@mkesc.co.uk> - 2020-11-22 20:21 +0000
  Re: I2C Single Master: peripheral or bit banging? Mike Perkins <spam@spam.com> - 2020-11-25 17:43 +0000
    Re: I2C Single Master: peripheral or bit banging? pozz <pozzugno@gmail.com> - 2020-11-26 08:54 +0100
      Re: I2C Single Master: peripheral or bit banging? Mike Perkins <spam@spam.com> - 2020-11-26 14:34 +0000

csiph-web