tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

I2C iic_exec() and clock stretch



Sorry to intrude...


So...  I have a I2C device I am writing a driver for that has a read
cycle that needs one of the following:

1) Start a read with a STOP, except that before the data is sent down
the bus, clock stretch for a bit while the device is working on what is
is suppose to be working on.  When it is done, the data will be sent.

2) Start the read with no STOP cycle, but return NACK part way though
until the device is done doing what it is suppose to be doing.  When it
stops sending a NACK, or after you wait a bit, it seems that you can do
a read with a STOP and get the data.


Neither of these two situations appear to be supported with iic_exec()
as it exists today.  What I was wondering is if anyone has worked on
anything to enhance iic_exec() to deal with this sort of thing.


The device in question is the SI7021 humidity and temperature sensor.
It is a fairly inexpensive device that works pretty well and has tons of
example code out there for all kinds of OSs and devices.  The data sheet
is available at, among other places:

https://cdn-learn.adafruit.com/assets/assets/000/035/931/original/Support_Documents_TechnicalDocs_Si7021-A20.pdf


I am using a Raspberry PI 3 as the computer.  To do read type #1, I
hacked up bcm2835_bsc.c to provide a simple device property to specify
the amount of clock stretch to the BCM2835 iic that is desired and a new
flag in i2cvar.h that can be used by iic_exec() that will tell the
controller driver to use the stretch, but getting that property set from
attached children provided to be ugly.  I am thinking that something
like a iic_execv() should maybe exist that works, mechanically, a little
like sysctl_createv() so that a si70xx driver can do a I2C transaction,
but tell the controller driver, do this transaction with these
additional arguments that are more complicated then a simple flag.

To do read type #2 with the SI7021 iic_exec() needs to be able to do a 0
length read, I think and this is disallowed by bcm2835_bsc.c by a
KASSERT(dlen >= 1).  I didn't really look at any other drivers to see if
this sort of thing is allowed.  This is basically a cycle that looks
like:

START+ADDRESS+COMMAND+START+ADDRESS
NACK will be returned until the measurement is done
START+ADDRESS
You get up to three bytes back.

It was simpler to hack in support for clock stretching then to figure
out if it was possible to do 0 length reads.



In any case, I was curious if anyone had any thoughts or was working on
something like this??




-- 
Brad Spencer - brad%anduin.eldar.org@localhost - KC8VKS
http://anduin.eldar.org  - & -  http://anduin.ipv6.eldar.org [IPv6 only]


Home | Main Index | Thread Index | Old Index