2

Consider this image from sparkfun:

enter image description here

Let's say I have this setup, a master and n slaves, plus a programmer connected to the SPI lines.

When I program the master (Arduino), the Arduino is reset. This means that all the data pins go low.

Since SS is active low, all the SS pins on the slaves go active.

I believe this means that all the slaves start driving the same MISO line (blue arrow from slaves to master), either high or low.

Doesn't this result in bus contention on that line? If not, what's the mechanism that prevents bus contention from happening?

  • 2
    This means that all the data pins go low. They don't go LOW, but high impedance input. – Gerben Mar 3 '16 at 9:59
  • 1
    And since the ports go high impedance, put a pull-up resistor on the SS line to drive it high when the MASTER is reset – frarugi87 Mar 3 '16 at 10:04
3

Yes, you can get SPI bus contention when using multiple SPI slave devices. It is up to you, the designer, to ensure that each SPI slave device has its chip select (CS or SS) asserted only when no other devices are driving MISO. Normally that is achieved by:

  • initialize all of the CS pins high (inactive) during setup
  • in the code that accesses SPI device #1,
    • assert SPI device #1 CS1 low (active)
    • perform SPI transfers on SPI device #1
    • release SPI device #1 CS1 high (inactive)
  • in the code that accesses SPI device #2,
    • assert SPI device #2 CS2 low (active)
    • perform SPI transfers on SPI device #1
    • release SPI device #2 CS2 high (inactive)

SPI bus contention can also occur during device programming (loading the bootloader or firmware image), if there is an attached SPI slave device, and its chip select (SS) is not pulled inactive by a pullup resistor.

I had a problem with this on one of my designs a few weeks ago. I was trying to burn the bootloader into some blank ATmega328-AU chips post-assembly, and my device programmer wasn't able to successfully program the chips because my one slave device had its chip select connected only to an ATmega328 pin.

I had previously breadboarded this design using an Arduino Pro Mini board, and it was working fine; but when I moved to first prototype PCB there was bus contention on MISO -- the blank ATmega328 wasn't driving the slave device's chip select high or low, but it floated low (active), causing MISO contention.

My solution (workaround) was temporarily contacting the chip-select to VDD 3.3V through a 10kohm resistor. This made my SPI slave device inactive, allowing the device programmer to successfully load the bootloader.

I think there would be no harm in leaving the pullup resistor on chip select (since it's an active-low signal), but it was only really necessary when using the device programmer. After I had the prototype boards initialized with the bootloader image, I was subsequently able to load firmware images as usual.

(One minor unrelated issue was that my assembler purchased ATmega328-AU when I had specified ATmega328P-AU -- they are almost the same, and it doesn't make a difference for my application, but it was annoying that I had to use a slightly different command line argument than then one I used with the Arduino Pro Mini board.)

  • Really my question applies both ways. If there is bus contention that the programming should fail. But I think what you're saying is that my assumption that pins are driven low on reset (or blank) is false. Rather, they float. – Ana Mar 3 '16 at 8:55
  • I think the ATmega328 PORTB pins are initially configured as inputs at power-up reset, will check datasheet... – MarkU Mar 3 '16 at 8:56
  • Confirmed. Section 13.2.1 Configuring the Pin: "The port pins are tri-stated when reset condition becomes active, even if no clocks are running." – MarkU Mar 3 '16 at 8:58

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.