Here's a quote from NXP's I2C specification:
All transactions begin with a START and are terminated by a STOP.
While a STOP is required to end a transaction, there is also the possibility to send another START before sending the final STOP. This is called a repeated start.
So a transaction won't always be as simple as START-STOP. There can also be START-START-STOP.
The repeated start signal is identical to the original start signal. It is just a special name given to the second one.
Why Do This?
Consider a typical I2C transaction for reading a register value from a target device. The read actually starts with a write - to send the address of the desired register. This is followed by the actual read to get the returned value. So there are actually two I2C transactions involved:
- I2C write - send the register address
- I2C read - receive the returned value
Each of these requires an initial START. But should there be a STOP between the two? Yes, no, maybe. It all depends. The answer is target device specific and would be found in the target device datasheet.
What's the Issue?
Some devices require a repeated start.
For these devices, a STOP is seen as sort of a "reset". They may throw away the register value from the initial write, so the subsequent read won't work. Or they may do something like go back to sleep, which would also potentially corrupt the attempt to read.
In these cases, the STOP is suppressed until the very very end - when all the I2C communication is done. In between, STARTs are reused - these are called repeated starts.
Here's an example - the MMA8451 accelerometer. Inside the datasheet, there's a section (5.11) that describes how to talk to the device over I2C. A single byte read is the most basic read interaction, where a request is made to return the single byte value (Data[7:0]) stored in a particular device register. Here is what the datasheet shows:
Note that there is no STOP after the requested register address is sent via a write (W) operation. Instead, another START is sent. The only difference is the read/write bit is now set to read (R). And then the value (Data[7:0]) is sent by the device and read back.
Then finally a STOP.
Why is That an Issue?
This is another detail that seems simple, but can cause some grief when actually implementing an I2C library. You probably are not doing this directly in your code, but are using an existing one, like the Wire library provided by Arduino cores.
The basic START-STOP pattern is pretty easy to implement. But dealing with providing the option for suppressing a STOP can be tricky.
Arduino Example
The Arduino Wire library provides for an optional parameter in endTransmission() to control the behavior of sending a stop when writing. For example, the MMA8451 example from above would be done with:
Wire.beginTransmission(device_address); Wire.write(register_address); Wire.endTransmission(false); // !! NO STOP !! Wire.requestFrom(device_address, 1); register_data = Wire.read();
However, the degree to which that is supported can be core dependent. Remember, "Arduino" encompasses many boards with numerous architectures, like AVR, ESP8266, ESP32, ARM, etc. Each of these has their own completely separate Arduino "core" which implements the Arduino API. So there can be variability between cores.
A slightly different example might occur when attempting to transfer large amounts of data. If the amount of data exceeds the buffer being used, it can not be done with a single transfer. Instead, multiple transfers must be done. In that case, it can be useful to suppress the stop between each. For the case of a read, this would be done with option parameter in requestFrom(). But actually supporting this can be tricky:
When this happens, it essentially means that platform and its I2C implementation can not support repeated start. So if you're trying to talk to an I2C target device that requires repeated start, you're sort of stuck.
Linux Example
The Linux kernel implementation also lacks the ability to suppress a stop for some situations.
It provides the ability to do the following:
- A basic write with a stop
- A basic read with a stop
- A combined write followed by a read with a repeated start
Therefore, one can write with a stop, or, using the combined method, a write with no stop followed by a repeated start and a read. But there is no way to do just a write with no stop.
CircuitPython Example
This is related to the Linux example above and is a good example of how sometimes these "issues" come down to specific design decisions made by developers. While the code *could* be changed to potentially better support odd-ball scenarios, it is decided not to for other reasons (i.e., it will just introduce other issues).
It's a closed issue thread, but contains some good discussion on the rational:
Page last edited March 08, 2024
Text editor powered by tinymce.