Skip to content

ESP32-C5 SDIO slave not receiving data from STM32 SPI master (MOSI/CMD issue) #992

@KimChungJae

Description

@KimChungJae

ESP32-C5 SDIO slave not receiving data from STM32 SPI master (MOSI/CMD issue)

Environment

ESP32 Side:

  • Chip: ESP32-C5 (eco2)
  • Firmware: ESP-AT v5.1.0.0-dev (factory_ESP32C5-SDIO.bin)
  • Compile: Feb 5 2026 13:16:02
  • ESP-IDF: v5.5.1-833-gcc569cbd80-dirty
  • Mode: SDIO Slave (1-bit mode)

Host Side:

  • MCU: STM32H750VBT6
  • Interface: SPI6 as SDSPI master (software SDIO emulation)
  • Clock: 468 kHz (Prescaler 256)
  • Library: esp-at/examples/at_sdspi_host (ported to STM32H7)

Hardware Connection

STM32H750 Pin Function ESP32-C5 GPIO SDIO Signal Pull-up
PG13 SPI6_SCK GPIO9 CLK No
PG14 SPI6_MOSI GPIO10 CMD 10kΩ ✅
PG12 SPI6_MISO GPIO8 DAT0 10kΩ ✅
PA8 GPIO_EXTI8 GPIO7 DAT1 (HS) 10kΩ ✅
PA15 GPIO_Output GPIO13 DAT3 (CS) 10kΩ ✅

Verified: All connections confirmed with multimeter, pull-up resistors present.

Problem Description

Symptom 1: MISO works, but MOSI doesn't

MISO (ESP32 → STM32):Working

STM32 receives data from ESP32:
- Pattern 1: 0xA5 0xA5 0xA5 0xA5 0xA5 0xA5 0xA5 0xA5
- Pattern 2: 0x3C 0xD1 0x05 0x90 0x61 0x74 0x05 0x90

This proves the hardware connection is good!

MOSI (STM32 → ESP32):Not working

STM32 sends:
- Idle clocks: 0xFF 0xFF 0xFF 0xFF ... (20 bytes)
- CMD0: 0x40 0x00 0x00 0x00 0x00 0x95 0xFF 0xFF ... (15 bytes)

ESP32 response: Nothing (timeout)

Error from STM32 sdspi library:
E sdspi_transaction: Not found response
E sdspi_transaction: CMD0 response error, expect 0x1, response 0

Symptom 2: ESP32 always logs error during initialization

ESP32 UART log:

I (933) main_task: Calling app_main()
I (933) at-workaround: no external 32k oscillator, disable it now.
Waiting 3 seconds for STM32 host to boot...
Starting AT interface...
I (4001) at-init: at param mode: 1
...
I (6941) at-init: module_name: ESP32C5-SDIO
I (6944) at-init: max tx power=78, ret=0
...
I (6960) at-init: v5.1.0.0-dev (unknown)
E (6964) at-sdio: invalid data:0 or len:-1      ← Always occurs!
I (6968) wifi:mode : sta (3c:dc:75:84:51:58) + softAP (3c:dc:75:84:51:59)

Error location: main/interface/sdio/at_sdio_task.c

  • Line 50 in at_sdio_write_data(): if (len < 0 || data == NULL)
  • Line 86 in at_sdio_read_data(): if (data == NULL || len < 0)

Timing: This error occurs 23ms after SDIO initialization, regardless of when STM32 sends CMD0.

Symptom 3: ESP32 stops reading MOSI after error

After the "invalid data" error appears:

  • ✅ ESP32 continues to send data on MISO (STM32 receives it)
  • ❌ ESP32 stops receiving data on MOSI (ignores STM32's CMD0)

Theory: After the error, ESP32 enters an error state and disables MOSI/CMD reception.

What We Tried

1. Timing adjustments ⏱️

Attempt 1: Added 3-second delay in app_main() before esp_at_init()

// C:\ESP\esp-at\main\app_main.c
void app_main(void)
{
    esp_at_main_preprocess();
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_at_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    
    printf("Waiting 3 seconds for STM32 host to boot...\n");
    vTaskDelay(pdMS_TO_TICKS(3000));  // ← Added delay
    printf("Starting AT interface...\n");
    
    esp_at_init();
}

Result: "invalid data" error still occurs at the same timing (E (6964))

Attempt 2: STM32 waits 4.8s ~ 8s after ESP32 reset
Result: No difference, CMD0 still fails

2. SPI clock speed 🔄

  • Tested: 15 MHz, 468 kHz
  • Result: No difference

3. Hardware verification ✅

  • Multimeter: All connections verified, continuity OK
  • Oscilloscope: MISO shows data, MOSI shows clock but ESP32 doesn't respond
  • Pull-ups: Confirmed 10kΩ on CMD, DAT0, DAT1, DAT3

4. DAT1 (HS) interrupt implementation

  • Configured PA8 as GPIO_EXTI with falling edge trigger
  • Implemented semaphore handler in sdspi_port.c
  • Result: No change

5. DMA settings

  • Tried: DMA_CIRCULAR, DMA_NORMAL modes
  • Tried: Polling mode instead of DMA
  • Result: No difference (hardware signals confirmed with oscilloscope)

Code References

STM32 SDSPI Port (working part)

Based on esp-at/examples/at_sdspi_host/STM32 example, ported to STM32H7:

  • User/Src/sdspi_port.c: Hardware abstraction layer
  • User/Src/sdspi_host.c: SDSPI protocol implementation (unchanged from example)
  • User/Src/esp_sdspi.c: High-level API

Key function: at_spi_transmit()

esp_err_t at_spi_transmit(void* tx_buff, void* rx_buff, uint32_t len)
{
    // Cache operations for STM32H7
    SCB_CleanDCache_by_Addr((uint32_t*)tx_buff, len);
    
    // SPI transfer (tried both DMA and Polling modes)
    HAL_SPI_TransmitReceive(&hspi6, tx_buff, rx_buff, len, 1000);
    
    SCB_InvalidateDCache_by_Addr((uint32_t*)rx_buff, len);
    
    return ESP_OK;
}

Debug Logs

STM32 Debug Output:

[SDSPI] Resetting ESP32-C5...
[SDSPI] Wait 4.8s (ESP32 boot 2s + app delay 3s)...
TX[20]: FF FF FF FF FF FF FF FF (CS=1)    ← Idle clocks
RX[20]: A5 A5 A5 A5 A5 A5 A5 A5            ← ESP32 responds!
TX[15]: 40 00 00 00 00 95 FF FF (CS=0)    ← CMD0
RX[15]: 40 00 00 00 00 95 FF FF            ← Echo back (no ESP32 response)
E sdspi_transaction: Not found response
E sdspi_transaction: CMD0 response error, expect 0x1, response 0

ESP32 Debug Output:

I (933) main_task: Calling app_main()
Waiting 3 seconds for STM32 host to boot...
Starting AT interface...
I (4001) at-init: at param mode: 1
I (6941) at-init: module_name: ESP32C5-SDIO
E (6964) at-sdio: invalid data:0 or len:-1    ← Always occurs
I (6968) wifi:mode : sta (3c:dc:75:84:51:58) + softAP (3c:dc:75:84:51:59)

Questions

1. What causes "invalid data:0 or len:-1" error?

Looking at at_sdio_task.c:

static int32_t at_sdio_write_data(uint8_t *data, int32_t len)
{
    if (len < 0 || data == NULL) {
        ESP_LOGE(TAG, "invalid data:%p or len:%d", data, len);  // ← Line 50
        return -1;
    }
    // ...
}

Who calls this function with NULL/invalid args during initialization?

  • Is this expected during AT core initialization?
  • Should we ignore this error?

2. Why does ESP32 stop receiving MOSI after the error?

static void at_sdio_task(void *params)
{
    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
    
    for (;;) {
        esp_err_t ret = sdio_slave_recv(&handle, &addr, &size, portMAX_DELAY);  // ← Should wait forever
        // ...
    }
}

The task uses portMAX_DELAY, so it should wait forever for data from STM32. But after the "invalid data" error, ESP32 doesn't receive CMD0 from STM32.

Does the error state disable MOSI/CMD pin reception?

3. Is ESP32-C5 SDIO slave tested with SPI-based hosts?

The example at_sdspi_host is based on STM32F1 with hardware SDIO controller. We're using STM32H7 with SPI6 emulating SDIO.

Is software SDIO emulation (SPI) tested/supported with ESP32-C5?

Workaround Attempts

We tried modifying at_sdio_task.c to ignore the error:

// Commented out error log
if (len < 0 || data == NULL) {
    // ESP_LOGE(TAG, "invalid data:%p or len:%d", data, len);  // Commented
    return -1;
}

Result: Error log disappears, but ESP32 still doesn't receive CMD0.

Request

  1. Root cause analysis: Why does "invalid data" error occur during initialization?
  2. Workaround: How to make ESP32 receive MOSI/CMD data after initialization?
  3. Confirmation: Is ESP32-C5 SDIO slave + STM32 SPI master a supported configuration?

We've spent over a month on this issue. Any help would be greatly appreciated!

Additional Information

  • STM32 MISO reception works (proves hardware is OK)
  • STM32 can read data from ESP32 (0xA5, 0x3C patterns)
  • Only MOSI direction fails (ESP32 can't read from STM32)
  • Problem is not timing-related (tried many variations)
  • Problem is not clock speed-related (tested 468kHz ~ 15MHz)

Thank you!

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