4
\$\begingroup\$

I'm writing I²C code for an application where I have only one master, but several slaves. In all the datasheets I've read (not only for this project), the repeated start condition is only used to switch between write and read and write to/from the same slave or vice versa. Of course, those datasheets wouldn't show other slaves (why should they, anyway).

Is it legal to omit the stop condition between transfers to/from different slaves?

Do some slaves misbehave when addressed after a repeated start condition, after different slave had been addressed before?

I know that the second question cannot be safely answered with "no", but if any of you had problems in such a situation before, that's enough for me.

\$\endgroup\$
4
\$\begingroup\$

The repeated start condition was added to the specification to allow a master in a multiple master setup to keep control over the bus while initiating a new operation. It does work in a one master setup as well, as can be seen on page 9 of the specification: the repeated start condition is described in a general description, so it works for both modes. Also, after a repeated start condition the address is sent again, so it should work when changing the address as well.

However, it is not very common, so some slaves (I've never seen one though, but Michael Karas has as stated in his answer) might expect a stop condition, which might cause problems when omitting the stop condition. I therefore would recommend you to include the stop condition just to be sure, although your implementation wouldn't be 'wrong' following the specification. A stop condition doesn't cost that much time.

\$\endgroup\$
  • \$\begingroup\$ I know that the stop condition doesn't cost much time; the background is more implementation-oriented. I'm writing interrupt driven I2C code for an AVR, and having to insert stops has an impact on the implementation. \$\endgroup\$ – Christoph Feb 23 '13 at 14:12
  • \$\begingroup\$ I see, good point. Answer stays the same: it should work, following the specification. \$\endgroup\$ – Keelan Feb 23 '13 at 14:14
  • 2
    \$\begingroup\$ @Christoph: Then the root problem seems to be a badly thought out architecture as to what goes in interrupt code, what the foreground does, and how the application interacts with it all. There is no legitimate reason you couldn't send a stop at the end of every message. \$\endgroup\$ – Olin Lathrop Feb 23 '13 at 14:49
  • 1
    \$\begingroup\$ @Olin: It's not thought out yet, so it can't be badly thought out yet. How can inserting stop conditions at the end of every operation not have an impact on the implementation compared to not inserting a stop and sending a repeated start? The implementation will be different. \$\endgroup\$ – Christoph Feb 23 '13 at 15:04
  • \$\begingroup\$ The question is how much impact it will have. @OlinLathrop says that when the impact is large, you're implementation is badly thought out - so the implementation should be that way that adding a stop condition wouldn't be that hard to add to the implementation. \$\endgroup\$ – Keelan Feb 23 '13 at 15:05
4
\$\begingroup\$

My recommendation is to always end every transaction with each device with a stop sequence. You will have a much greater chance of success in talking to various types of alternate devices that you try attach in the future.

I have specifically seen devices that behave badly when there is a missing stop at the end of the transaction.

As a matter of fact there was work I did, some years back, designing some slave devices into FPGA type parts. I found it essential to decode the stop condition and use that to reset the slave's transaction state machine. The main reason for this is that strange things can happen on the bus, things that the master side of the bus didn't even expect to happen. When an operation in progress gets corrupted by these "unexpected things" havoc can arise that takes some work to recover from. The best design strategy for devices is that they design to and utilize the stop sequence to produce the interface reset. When this strategy is followed the manufacturer of devices gets a lot less call for support and a happier batch of customers. Likewise the customer that is interfacing to devices will know about this and can simply provide for a "bus reset" of her/his I2C network that consists of a START -> STOP sequence pair. This can be utilized in the master side higher level driver software as part of a retry loop for when device communications has failed for one reason or another.

If you probe around on the web you can find certain app notes that describe various sorts of involved I2C "bus reset" schemes that try to recover devices that have hung due to unexpected events in the bus. Some of these include doing start - stop sequences with 9 or 27 clock cycles in between. Others have shown how to gate the power to the target device using a FET in the Vcc line to effect an "internal reset" in the slave device.

If everybody designed so as to simply reset off the stop sequence all the the bizarre I2C problems that can happen can be solved in a simple way without having to resort to schemes as discussed in these app notes. I have experienced a vast improvement in the robustness of newer I2C devices that I use in my own embedded design projects. This is such a relief as compared to LM75 temp sensors from 10-15 years ago that needed power gating of their Vcc pins to provide reliable operation OR some unnamed I2C 8-bit DAC/ADC that required extra clocks type recovery resets.

So based upon years of experience I want to recommend again that you not try to do this repeated start sequence / changed address scheme. Always follow the simplest sequence that get the job done for a specific I2C device. And make sure each transaction ends with a stop sequence and provide for a bus reset function that is a start-stop sequence pair.

I know that there are probably many readers here that are implementing I2C communications software that is designed on the assumption that devices will always just work. I would like to point out that there are a whole slew of mission critical embedded applications where this technique is unacceptable. It becomes necessary to detect every possible error in a transaction and then add another layer above this that includes retries and attempted bus reset recovery. And finally if critical behavior of the product depends upon the I2C channel that has failed take careful steps to shut down the device in an orderly and safe manner.

\$\endgroup\$
  • \$\begingroup\$ I like the design of the I2C protocol, but a lot of the existing hardware... not so much. It would seem like there are a number of things the protocol should be able to provide for, but hardware implementations can't. For example, I see no reason it shouldn't be possible to have multiple I2C slave devices on the bus that would respond sensibly to a "Get 48-bit serial numbers in numerical order starting with XXXXXX" command if I2C arbitration hardware could be enabled in slave mode, and re-enabled every six bytes. I can't think of any implementations, though... \$\endgroup\$ – supercat Mar 26 '13 at 19:25
  • \$\begingroup\$ ...except perhaps for the 8749 (whose I2C hardware only processed a bit at a time) which might be able to do such a thing. \$\endgroup\$ – supercat Mar 26 '13 at 19:26
  • 1
    \$\begingroup\$ I forgot to mention: a start/stop pair won't work to reset the bus if data is being read from a slave. If e.g. a serial EEPROM is reading a sequence of zeroes, then for eight bit times out of each group of nine it will be holding SDA low; if the master doesn't pulse SCL enough times that the slave releases it, it won't be able to issue a stop/start. Also, many EEPROM and similar devices will ignore any transaction which doesn't end with a proper stop sequence. Thus, it's often desirable to ensure that the sequence used to reset the bus can't possibly be mistaken for a legitimate stop. \$\endgroup\$ – supercat Mar 20 '15 at 6:14
0
\$\begingroup\$

I have been writing some software for a microcontroller as master with several slave devices and I wanted to be sure that the master recognised the case when the slave made no response.

I had some software running and talking to one slave, so I thought I would change to use a different address that no slave would respond to. I accidentally used this invalid address at the stage just after a repeated start where the device is re-addressed in read mode to make it read out its register contents.

I turns out, that for this particular device at least, it ignored the invalid address and carried on as normal and I received all the usual data.

My interim conclusion here is that I2C devices, once the first address has gone on to the bus, will continue to ignore transactions, or respond to transactions until the next stop condition.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.