Skip to content

ESP-IDF 6.1: new spi_bus_config_t::dma_burst_size left at 0xFFFFFFFF by memset(~0u), so SPI bus init panics in M5.begin() #278

Description

@endaye

Summary

On ESP-IDF v6.1, M5.begin() (or any M5GFX::init()) panics during SPI bus
initialisation and the board boot-loops. The cause is that IDF 6.1 added a new field to
spi_bus_config_t, and lgfx::v1::spi::init() fills that struct with memset(&buscfg, ~0u, ...),
so the new field is left as 0xFFFFFFFF.

IDF 6.0.x and 5.x do not have the field, which is why the existing build matrix does not show this.

Environment

ESP-IDF v6.1 (commit fff9895c82d744c7237be8847347bdd1b07c6643)
M5GFX 0.2.28 (from the component registry)
M5Unified 0.2.21 (from the component registry)
Board M5Stack Cardputer Adv (ESP32-S3FN8, no PSRAM)
Toolchain xtensa-esp-elf-gcc 15.2.0 (crosstool-NG esp-15.2.0_20251204)
Project type plain ESP-IDF component, no Arduino
Host macOS arm64

Symptom

The project builds cleanly (0 errors, 0 warnings). At runtime it boot-loops — 282 resets in 15
seconds — with:

E (160) gdma: gdma_config_transfer(425): invalid max_data_burst_size: 4294967295
E (160) spi_common: alloc_dma_chan(319): config gdma tx transfer failed
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
EXCVADDR: 0x00000004

Decoded backtrace:

m5::M5Unified::begin()                     M5Unified.hpp:363
lgfx::v1::LGFX_Device::init()              LGFXBase.hpp:1423
m5gfx::M5GFX::init_impl(bool, bool)        M5GFX.cpp:1111
m5gfx::M5GFX::autodetect(bool, board_t)    M5GFX.cpp:1826
lgfx::v1::Bus_SPI::init()                  Bus_SPI.cpp:418
lgfx::v1::spi::init(int, int, int, int, int)  lgfx/v1/platforms/esp32/common.cpp:859
spi_bus_initialize()                       esp-idf/components/esp_driver_spi/src/gpspi/spi_common.c:1016
spicommon_dma_chan_free()                  esp-idf/components/esp_driver_spi/src/gpspi/spi_common.c:489   <-- panic

Root cause

src/lgfx/v1/platforms/esp32/common.cpp:841:

spi_bus_config_t buscfg;
memset(&buscfg, ~0u, sizeof(spi_bus_config_t));   // sets every *_io_num to -1
buscfg.mosi_io_num = spi_mosi;
...
buscfg.intr_flags = 0;
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0))
buscfg.data_io_default_level = 0;
#endif

IDF 6.1 added:

uint32_t dma_burst_size; ///< DMA data burst size in bytes. Only used when DMA is enabled.
                         ///  Set to 0 to use driver default.

(components/esp_driver_spi/include/driver/spi_common.h)

After the memset it holds 0xFFFFFFFF, which is neither 0 nor a chip-supported burst size, so
resolve_dma_burst_size() rejects it, alloc_dma_chan() fails, and the unwind path panics.

Field presence, checked against the release tags:

ESP-IDF dma_burst_size in spi_bus_config_t
v6.1 present
v6.0.3 absent
v6.0 absent
v5.5.5 absent

.github/workflows/IDFBuild.yml covers 6.0.2 (where the field does not exist) and is build-only, so
neither half of the matrix can surface this: adding a struct field needs no source change to compile.

Confirmation

Same binary, one line added after buscfg.intr_flags = 0;:

#if defined (ESP_IDF_VERSION_VAL)
  #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 1, 0))
        buscfg.dma_burst_size = 0;
  #endif
#endif
boots in 15 s panics
unpatched 282 282
one line added 1 0

With the line added, everything works: getBoard() returns board_M5CardputerADV, the 240x135
display paints, and both speaker and mic report enabled.

Suggested fix

The minimal change is the version-guarded assignment above, next to the existing
data_io_default_level / isr_cpu_id guards.

More robustly, memset(&buscfg, ~0u, ...) is fragile against upstream struct growth: any new
non-pin field IDF adds silently arrives as 0xFFFFFFFF. Zero-initialising and then setting the
*_io_num fields to -1 explicitly would make future IDF releases default-correct instead of
default-wrong.

Related, on the ESP-IDF side

spi_bus_initialize() panics in its own error path rather than returning the error that
alloc_dma_chan() already produced — spicommon_dma_chan_free() dereferences a DMA context that was
never fully allocated (EXCVADDR: 0x00000004). An invalid dma_burst_size should surface as a
failed return, not a LoadProhibited. That is arguably a separate ESP-IDF issue; happy to file it
there as well if useful.

Activity

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

Metadata

Metadata

Assignees

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