12 ms·
I really don't like I2C. Yes, in principle it's pretty simple, but if you consider NACKS, slaves holding SCK low, what happens if your master resets while the s
by Ives 7y ago
I really don't like I2C. Yes, in principle it's pretty simple, but if you consider NACKS, slaves holding SCK low, what happens if your master resets while the slave is trying to send a 0 bit (hint: power cycle!), etc, it's so easy for the peripheral to get stuck.
SPI is much easier to write correctly, and pretty much only has the extra wire (usually not a problem) and the phase polarity issues as a negative point.
- shortsightedsid 7y agoOn the other hand you need a lot more pins for SPI. One more advantage of SPI that I see is higher data rates, full-duplex communication etc..
- uep 7y agoFor exactly that reason, I've encountered peripherals getting stuck during i2c transactions far too many times. At least a handful of times I've had to add boot (and sometimes runtime) logic to clear stuck transactions, due to the lack of a dedicated way to reset said peripheral. It's quite annoying because one stuck device can block all other communication on the bus. Let's hope your reset pin (if you have it), isn't on an i2c expander on the same i2c bus.
- fra 7y agoFor what it's worth, here is a good doc on I2C resets: https://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf https://www.analog.com/media/en/technical-documentation/appl...
- pslam 7y agoSame. I really dislike I2C, but it's universal and it's been around for decades, and it's hard to avoid designs without it. I2C keeps causing these additional issues which the article doesn't touch on: * No way to safely bring the bus back to idle from mid-transaction. By "safely" I mean not accidentally transmit an extra byte which could e.g overwrite EEPROM memory. There is no combination of transitioning the 2-wire bus from an arbitrary state back to idle which works in the general case. If it's important, you end up adding a dedicated reset wire. * No safe, universal way to bring the bus from tristate, or low, to pulled-up. There are designs where this ends up being necessary. You end up with a spurious transaction, which may wedge the bus, or having to add a reset wire or buffer. * The protocol is extremely hostile to devices with non-zero latency response. It's designed as a simple "Address this register and then immediately read out a byte in the next clock cycle". Works great for trivial devices, but for anything more complex it ends up needing a bank of register acting as a "proxy" to access the higher latency side of the chip. At this point I2C is an awesomely bad choice, but people keep doing this, because it's so universal.
- fra 7y ago> No way to safely bring the bus back to idle from mid-transaction. [...] No safe, universal way to bring the bus from tristate, or low, to pulled-up. These are great points, and I'll add a note about them in the article. Thanks! > The protocol is extremely hostile to devices with non-zero latency response. [...] Technically, this is what clock-stretching is for. In practice, you're right that complex devices implemented proxy registers. I've seen it on DP->MIPI bridges for example.
- russdill 7y agoThere is a safe, out of band way to do this that system designers can utilize. Reset all the other peripherals on the bus.
- ngcc_hk 7y agoWow
- amelius 7y ago> No way to safely bring the bus back to idle from mid-transaction. Why would you want to do that? Not having the ability to do this is part of the contract. If you design your device such that it always completes the transaction, then there should be no problem, unless one of the devices on the bus doesn't play fair but then you have a different problem.
- esmi 7y agoSay you’ve asked an I2C ROM for a block read. After the first byte something, also on the bus, asserts an interrupt via a side band GPIO. I can’t read the something until the block read finishes.
- pslam 7y agoThe specific case I was thinking of was the host suffering an incident where it is not possible or practical for its software to know where it left off. For example, you get a kernel panic, or soft-reset for some reason. When you recover, you now have a bus in an unknown state, possibly mid-transaction, and if you pick the wrong order in which to bring the bus back to idle, you might wedge it or accidentally cause a side-effect (e.g overwrite a byte in an EEPROM).
- fra 7y agoI think I2C and SPI have very different use cases. Over I2C, you can interact with 127 devices with just 2 pins. To do the same with SPI, you'd need 130 (4 + an additional CS for every device on the bus). You may think of the extra pins as not a problem, but on every product I've worked on we've been pin-limited on the MCU.
- TickleSteve 7y agoDon't forget the reset lines to each device that you need to release the bus when they get locked up!
- fra 7y agoNo reason why you need to reset them individually ;-).
- Ives 7y agoAgreed, but most I2C busses only have 2 or 3 devices on them. There are some boards with 16 or so devices on the same bus, but much more than that and you'd better hope you can either program their addresses or order them with a specific address, or you might end up with 2 chips with the same address.
- fra 7y agoI've worked on server hardware with dozens of devices on a bus :-). Making sure addresses were programmable was a must indeed.
- oliverx0 7y agoThis happened to me once. Used proximity infrared sensors that used I2C with a fixed address. Needed to use multiple of them. I was able to fix it with a tri-state buffer, but quite the pain to figure out why things were not working and coming up with a solution.
- vvanders 7y agoNot always the case that you need the pin count, a good number of SPI devices support daisy chaining[1]. [1] https://www.maximintegrated.com/en/design/technical-documents/app-notes/3/3947.html https://www.maximintegrated.com/en/design/technical-document...
- fpgaminer 7y agoI built a battery powered project designed to run continuously for ten years. Of all the things in that design, the I2C bus makes me the most nervous (1). Every time the MCU wakes up it has to use I2C to read from the RTC. If at any point in that ten year span the I2C bus gets jammed ... I mitigated the issues by doing I2C resets on every read (see the Analog Devices I2C reset documentation linked in another comment) and reading multiple times to filter out any spurious bit errors. Other than that I just have my fingers crossed that a bit doesn't accidentally flip and overwrite something in the RTC. Or that the bus somehow gets stuck driven between sleeps and drains the battery early. sigh SPI would have been so much nicer. (1) I mean, okay, the massive lithium battery exploding is perhaps the most nerve racking component, but I2C is a close second.
- ajross 7y ago> SPI is much easier to write correctly I'm not sure that I buy that. A daisy chained SPI bus is a rats nest of configuration hassle and basically impossible to debug. You're trading hardware robustness for software complexity, and that's not always a win. And as far as hardware messes: SPI doesn't synchronize anything beyond the bit level (modulo an out of band chip enable or reset, of course, which would work to "fix" an I2C device too), making shift/offset bugs a real danger. Board-level digital interfacing is just hard. That's why we do it as little as possible and put everything on the SoC these days.
- Gracana 7y agoThere are so many buggy I2C devices out there, I wouldn't say you're gaining hardware robustness, either.
- deleted 7y ago[deleted]
- tuckerpo 7y agoSMBus (which is close enough to call I2C) is also a major pain in the ass for Linux integration. If a master goes out of sync with a slave, or a poorly programmer slave tries to multi-master the bus or something, your kernel will hang and crash.
- threatripper 7y agoThis sounds much like a brown-out where only half the system resets or worse, parts of it go into an undefined state. The proper way to deal with this is a complete reset/power cycle. Granted, that's not easy to do if your peripherals have no reset pin or their power source cannot be switched by the bus master. Would your problems go away if you had I2C plus a dedicated reset pin on all peripherals?
- rcxdude 7y agoI2C has caused me probably the most grief out of all the buses, as it's been the most painful to work with when designing the schematic (because even with only 3 devices you have to deal with address conflicts), initially writing the software (because the specification is quite lax on what can happen when, inevitably the interface between hardware and software is quite complex and a lot of it is very latency sensitive. A lot of hardware for it is quite buggy or just poorly designed as well), and in terms of ongoing bugs and issues (because of said latency sensitivity and propensity for locking up). I try to avoid it as much as possible. If I need a peripheral, I prefer SPI, if I need a bus for connecting devices I control, I use CAN. If I'm connecting two systems together, a UART.