Skip to content

P4: machine.SDCard() cannot bring up the TF card on the Waveshare P4 panel #4

Description

@bdbarnett

Summary

On the Waveshare ESP32-P4-WIFI6-Touch-LCD-4B, machine.SDCard() — the form board_peripherals.sdcard() uses — never brings up the card. The peripheral initialises, the card never answers: info() raises ESP_ERR_TIMEOUT, ioctl(4/5/6) return -1, and readblocks() returns False.

The card itself is fine. When it did come up, it read as a 32 GB card (62,685,184 x 512 blocks) with a valid MBR (55aa).

Three things the board config does not do

From the Waveshare GPIO allocation table: D0-D3 = GPIO39-42, CLK = GPIO43, CMD = GPIO44, power control = GPIO45.

  1. GPIO45 is a power-control pin and nothing drives it. Observed working with it driven low. board_peripherals.sdcard() drives nothing — the same shape as the S3's CH422G/EXIO5 trap, where an unset enable pin made a whole peripheral look absent.
  2. 4-bit width is required. width=1 never answered at any frequency.
  3. 25 MHz and above fail. 4-20 MHz worked; the default is 20 MHz.

The explicit-pin arguments are not available here — SDCard(clk=..., cmd=..., data=...) raises TypeError: extra keyword arguments given, so SOC_SDMMC_USE_GPIO_MATRIX is off for this target and 39-44 are the fixed pins.

What is still unexplained, and why this is not just a config fix

Getting the parameters right is not sufficient. With Pin(45, OUT, value=0), slot=0, width=4, freq=20000000, a fresh boot still times out.

The two runs where the card came up were both preceded by many failed attempts in the same session, and — critically — the following run also worked. An ESP32 reset does not reset the card, so those successes are a card left initialised by an earlier accident, not a sequence that can be reproduced on demand. Everything since is ESP_ERR_TIMEOUT.

Sequences tried, all failing from a clean boot: retry loops (5x with settles), a deliberate power cycle (GPIO45 high 400 ms, then low), a slow identification pass at 400 kHz then a fast open, and an ascending frequency walk with deinit() between attempts.

Also note the first SDCard() after boot constructs; subsequent ones raise ESP_ERR_TIMEOUT at construction, so the peripheral is left held and a naive retry loop cannot work without a deinit() on every path.

Impact

  • board_peripherals.sdcard() on this board cannot work as written, whatever else is fixed.
  • Blocks the host-side SD format test across the USB MSC link — the last open item on the "SD card as a device drive" row in the roadmap, which needs a working card behind sd_drive.py.

Method note

An earlier report in this session claimed the card was unformatted with "sector 0 signature 0000". That was wrong: readblocks() had returned False and never written the buffer, and the zeros were the buffer's own. Anything checking this should pre-fill the buffer with a poison value (0xA5) and assert it was overwritten — reading zeros from an untouched buffer is indistinguishable from reading an empty sector.

Separately: sd_drive.py takes ioctl at face value

examples/sd_drive.py reads card.ioctl(4, 0) straight into its block count. A card returning -1 produces no output and no error — the example simply does nothing, which is how this was first mistaken for the example being broken. It should refuse a non-positive block count with a real message.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions