I also think the calls to read() and write() should be modified to take
a flag, which tells whether or not to generate a STOP.
Linux’s I2C APIs take a linked list of commands to pass to the device
that encompass an I2C “transaction.” The last element of that
generates the STOP.
This seems like a nice programming model, but probably too heavyweight
for a HAL, and if we add a driver interface, we can always layer this on
top of the HAL interface.
On 18 Oct 2016, at 18:08, marko kiiskila wrote:
I would be ok having the extra flag instead of calls to begin/end.
On Oct 18, 2016, at 2:58 PM, Kevin Townsend <ke...@adafruit.com>
I agree designing HALs that play well across vendors is difficult
since the peripherals have all kinds of limitations and edge cases,
sometimes even in device families from the same silicon vendor. :(
STOP is the main thing you need full control over though, yes (based
on my own experience anyway). You can have repeated starts, but some
sensors will expect: START - READ - STOP - START - WRITE - STOP ...
and some will expect: START - READ - START - WRITE - STOP, and they
often won't work as expected using the wrong pattern.
The two gotchas I consistently come across are needing control over
when the STOP bit is inserted (i.e. having that in the right place in
the drivers), and more rarely on sensors that use clock stretching
making sure that the master handles that properly. There are several
'I2C' peripheral blocks out there that don't handle clock stretching
properly, though this isn't an API level issue, rather it's a HW
problem (unless you are bit-banging I2C of course).
On 18/10/16 23:50, will sanfilippo wrote:
Well, I do agree that this new API I am proposing is not as clean as
the old API; just dont know what else to do. I guess this is part of
the problem trying to make generic HALs.
At least you will be able to control when the STOP occurs which is
the most important thing I think.
On Oct 18, 2016, at 1:24 PM, Kevin Townsend <ke...@adafruit.com>
Having control over when the STOP happens is important since
different devices will behave differently, especially if you are
performing a series of events like read/write/read or something
similar. Some devices expect the STOP to happen in different places
in a command sequence.
My vote would be a less attractive AP where the stop is a flag.
Since we apparently aren't using _begin to set the START we may as
well drop the STOP being handled in _end, but I'm obviously curious
what other people think here.
Sending multiple STARTS is perfectly valid BTW:
On 18/10/16 21:58, will sanfilippo wrote:
I am new to i2c so please bear with me. Hopefully this makes sense
to the i2c experts out there.
In adding i2c to the nordic platforms I ran across an issue that I
am not sure how to solve. Well, I know one way to solve it but it
would require changes to the API. Here is the issue:
In order to get the nordic HW to generate a NACK bit (well, the
opposite of an ACK) on the 9th bit after a read, you need to do
something special to the HW prior to reading the last received
character. When you do this, the HW will generate the correct 9th
bit and will also put a STOP condition on the line. While it is
possible to get the HW to generate a STOP independently, I dont
see how I can get it to generate the correct 9th bit unless you
know it is the last character you want to read.
Another issue that is bothersome is the nordic SDK itself: when
you are done with the read it automatically generates the STOP.
That is fine in and of itself; the SDK could be modified, but the
issue is that dang 9th bit.
Our API has the following functions:
hal_i2c_master_begin(): Not exactly sure what this does on all
platforms but currently is a NOOP on the nordic platforms.
hal_i2c_master_write(): generates a start but no stop.
hal_i2c_master_read(): generates a start but no stop.
hal_i2c_master_end(): generates a stop
At first glance, this seems to be a fine API and is easy to see a
“transaction”: a begin, writes and/or reads chained together,
and an end. Unfortunately, I could not see how to do this on the
One way to do this would be to get rid of begin/end and have a
flag in the read/write API. The flag would be “generate stop”.
This way users can chain reads/writes together and end them with a
STOP whenever they want. The only con to this is that it is not so
easy to look at the code to see that transactions have a stop.
Given that I dont have alot of experience wth many i2c devices, I
dont know if having the ability to skip START and/or address when
the read/write APIs are called is useful. So far in my limited
experience the start/address condition between the read/writes is
not an issue.
So to summarize, here is what I suggest:
* Remove the begin/end API.
* Add a flag to write/read that will cause a STOP to be generated
at the end of the read write.
Thanks! Comments greatly appreciated.