Skip to content

MAX31865 (SPI): deadlock in SPI.beginTransaction() due to LovyanGFX holding SPI bus after DMA flush #82

@knifter

Description

@knifter

Description

Selecting the MAX31865 as an input driver causes the device to hang after the boot screen.

Root Cause

The hang occurs in SPIDevice::beginTransaction() (the Arduino SPI.beginTransaction() call), which blocks forever on xSemaphoreTake().

The display on M5Stack Core uses the VSPI peripheral, driven by LovyanGFX using its own low-level ESP32 SPI driver. The Arduino SPI object also defaults to VSPI. They share the same hardware peripheral.

In the LVGL flush callback (lv_disp_cb), _lgfx.startWrite() is called followed by pushImageDMA(), which starts a DMA transfer and returns immediately — the bus is still held. endWrite() is only called from lv_flush_wait_cb, which LVGL invokes lazily at the start of the next flush cycle.

Between gui.loop() returning and pid->loop() executing in main.cpp, the LovyanGFX DMA transfer is in flight and the SPI bus is still owned. When MAX31865Driver::read() calls into SPIDevice, SPI.beginTransaction() tries to take the VSPI semaphore and blocks forever.

Affected code

  • lib-soogh/src/soogh-lgfx.cpplv_disp_cb / lv_flush_wait_cb
  • src/main.cpploop(), ordering of gui.loop() and pid->loop()
  • src/inputdrv.hMAX31865Driver uses SPI (VSPI)

Proposed Fix

Add lgfx_check_flush() to lib-soogh: if DMA is still busy, wait and call _lgfx.endWrite() to release the bus. Call this from main.cpp::loop() after gui.loop() and before pid->loop().

// soogh-lgfx.cpp
void lgfx_check_flush() {
    if (!_lgfx.dmaBusy()) return;
    while (_lgfx.dmaBusy()) yield();
    _lgfx.endWrite();
}
// main.cpp loop()
gui.loop();
lgfx_check_flush();   // release SPI bus before PID drivers use it
for (PIDLoop* pid : pids) pid->loop();

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions