[i2c] AT91 bus driver loses data
Mark M. Hoffman
mhoffman at lightlink.com
Thu Feb 8 13:47:38 CET 2007
Hi Ronny:
* Ronny Nilsson <rln-i2c at arbetsmyra.dyndns.org> [2007-02-07 17:25:42 +0100]:
> I've found problems with the AT91 I2C driver I'd like to discuss. I'm a
> user of the the Atmel AT91RM9200 cpu and just recently begun using I2C.
> For small transfers it works quite OK, however, for somewhat large
> transfers I've found the current driver to be unreliable...
>
> Explanation:
> * The driver ain't using the full capacity of the hardware to detect
> errors. Things like overruns and NACKs are silently ignored.
>
> * The driver uses polling for receive and transmit. While this works
> fine on an idle system it seems to create data loss on busy ones. A
> board experiencing modest network load will spend a fair amount of time
> servicing interrupts etc., which in turn make the I2C driver to miss
> characters. (There is only a one byte buffer in the HW). The cpu in
> those cases issue an error flag for overrun/underrun, but since the
> driver ignore them the transferred data is simply lost or become
> garbage.
>
> * The cpu errata recommends using interrupts in favour of polling for
> detecting the error flags mentioned above. Simply adding a oneliner
> check unfortunately isn't enough.
>
>
> Because of the small buffer (one byte) events should be serviced
> quickly. I made a test shot of disabling cpu interrupts at some
> critical sections in the driver which confirmed the explanations above.
> Large I2C transfers work perfect with interrupts disabled.
> Unfortunately the critical section is quite lengthy... I need about 1.5
> ms just for reading the time out of my RTC. Running that long with
> interrupts disabled ain't a good solution.
>
> I propose a redesign of the AT91 I2C driver. Using interrupts instead
> of polling should enhance the reliability and lessen risk of data loss.
> - Or, at least something should be done to detect errors if/when they
> occur. I've searched the list archive for any reason to why that
> approach wasn't adopted right from the start, but failed to find one.
> Perhaps have I missed something? Are there any
> technical/political/other reason for *not* using an interrupt based
> driver?
AFAIK, early I2C bus drivers used polling for reasons that are no longer
relevant (buggy PC hardware and/or BIOS). There's no technical reason not to
use interrupts for something like AT91.
Nonetheless, I'm surprised to see a performance problem. The I2C protocol
allows the bus master to hold the clock as long as necessary in order to
get a byte in or out. There is literally no timeout specified in the
protocol for this: the slave can do nothing but wait. If all the I2C slaves
on your bus worked this way, then your transfers might take some time, but
they shouldn't be corrupted.
In reality, slaves do timeout. But even these timeouts are usually on the
order of 100s of msec. So you can understand why in almost all cases the
polling method is good enough - it's pretty hard to starve the I2C bus driver
long enough for it to matter.
In your case, I would take a closer look at your slaves just in case one of
them is behaving badly and there is something you can do about it. But
otherwise, nothing prevents rewriting the driver to use interrupts if need
be.
> If you'd like I gladly help with the work.
Regards,
--
Mark M. Hoffman
mhoffman at lightlink.com
More information about the i2c
mailing list