Skip to content

docs(sdcardio): clarify SD-first init rule for boards with floating C…#10947

Merged
dhalbert merged 3 commits intoadafruit:mainfrom
mikeysklar:patch-1
Apr 15, 2026
Merged

docs(sdcardio): clarify SD-first init rule for boards with floating C…#10947
dhalbert merged 3 commits intoadafruit:mainfrom
mikeysklar:patch-1

Conversation

@mikeysklar
Copy link
Copy Markdown

@mikeysklar mikeysklar commented Apr 15, 2026

Documentation change only.

The .. important:: note in SDCard.__init__ says to always initialize the SD card before other SPI peripherals. This is correct in most cases, but on boards with a floating CS pin (e.g. Feather RP2040 RFM, where RFM_CS has no pull-up), the other peripheral's CS must be driven HIGH first to avoid corrupting the bus during SD init.

Adds an exception note to the existing important block for this case.

forum thread credit ThoMue for pointing this out...

…S pins

The existing "Important" note says the SD card must always be initialized before any other SPI peripheral. This is correct in most cases, but is misleading for boards like the Feather RP2040 RFM where the co-located peripheral (RFM95) has a floating CS pin with no hardware pull-up. On those boards the floating CS corrupts the SPI bus during SD init, so that peripheral's CS must be driven HIGH first. Added an exception paragraph to the important block to document this case.
Comment thread shared-bindings/sdcardio/SDCard.c Outdated
@mikeysklar
Copy link
Copy Markdown
Author

thx dan - indentation aligned with blank line after

Copy link
Copy Markdown
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at the docs-html artifact, and it looks good. Thanks!

@dhalbert dhalbert merged commit b8d92f9 into adafruit:main Apr 15, 2026
577 checks passed
@bablokb
Copy link
Copy Markdown

bablokb commented Apr 16, 2026

@mikeysklar

The .. important:: note in SDCard.__init__ says to always initialize the SD card before other SPI peripherals. This is correct in most cases

I never understood this note, can you give some reasoning why "this is correct"? Driving the CS of the SD card high, initialize a different device first and then the SD-card should also work. The floating CS is a general problem of shared busses, irrespective of an SD-card present or not.

@mikeysklar
Copy link
Copy Markdown
Author

mikeysklar commented Apr 16, 2026

@bablokbGood point. The "SD first" rule was never really about SD cards being special — it was implicitly relying on hardware pull-ups on all other CS pins doing the work of keeping the bus clean at boot.

The floating CS on the Feather RP2040 RFM just exposed what the real invariant actually is: before any SPI transaction, every CS line on the bus must be in a known HIGH state, whether that's guaranteed by a pull-up resistor or driven HIGH in software. The init order is secondary to that.

@dhalbert
Copy link
Copy Markdown
Collaborator

It's fine to rewrite this again to clarify.

@bablokb
Copy link
Copy Markdown

bablokb commented Apr 16, 2026

I actually fell over this a few years ago when my e-ink was wildly flashing while initializing the SD-card. One thing that would really simplify things if fourwire would accept a DigitalInOut in addition to a microcontroller.Pin. Because currently, you have to create a DIO, pull it high, then later deinit it to pass the pin to the fourwire-constructor. The same hold true for the sdcard-constructor (and maybe other places).

@dhalbert
Copy link
Copy Markdown
Collaborator

@bablokb
Both constructors do this:

    common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL);

So the CS pins are pulled high in the constructor. For FourWire, this happens at the end of the constructor.

But for FourWire, no SPI transaction happens during the constructor, whereas for SDCard, the constructor does some initialization. Maybe the solution is for SDCard (and anything else that takes an SPI bus) to avoid doing any SPI operations during the constructor. The int could be deferred until another operation was requested, though that defers reporting any problems (like no SD card present). Or a separate init() operation could be added, but that's an API change.

@mikeysklar
Copy link
Copy Markdown
Author

Before adjusting the comments the original forum issue isn't entirely resolved. I'll work with the user and what I believe is the same hardware setup today before changing the comments to something like:

Before initializing the SD card, make sure every CS pin on the shared SPI bus is HIGH — either via a hardware pull-up or driven HIGH in software. The old "SD first" rule only held because pull-ups were assumed. Init order is secondary; clean CS lines are what actually matter.

@bablokb
Copy link
Copy Markdown

bablokb commented Apr 16, 2026

@bablokb Both constructors do this:

    common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL);

So the CS pins are pulled high in the constructor. For FourWire, this happens at the end of the constructor.

I think my comment above is only true for 9.x. If I read the code correctly, it is possible now to pass a pin or dio to the Fourwire constructor.

Splitting Fourwire-construction and display construction is a valid workaround (I wasn't aware of that). But it makes the encapsulation of display creation within an utility class/method impossible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants