Skip to content

M5Stack CoreS3 display (ILI9342C) blank on ESP-IDF v6.0.1 #192

@wheelbot-tech

Description

@wheelbot-tech

Environment

  • Board: M5Stack CoreS3 (ESP32-S3, ILI9342C display)
  • M5GFX branch: master
  • ESP-IDF version: v6.0.1
  • Symptom: Display shows nothing — slight backlight glow, zero pixels, no crash

Board is detected correctly (board:10), M5.Display.width()/height() return 320×240,
AXP2101 DLDO1 is enabled (backlight on), but fillScreen() and all draw calls produce no output.


1. Wrong LCD RST pin on AW9523

rst_control() uses 1 << 5 (P1_5), but on CoreS3 hardware the LCD RST line is
connected to AW9523 P1_1 (1 << 1). The display never received a valid hardware reset.

// Current code:
uint8_t bits = level ? (1<<5) : 0;

// New :
static constexpr uint8_t lcd_rst_bit = 1 << 1; // AW9523B P1_1
uint8_t bits = level ? lcd_rst_bit : 0;

2. Direct SPI register access broken on ESP32-S3 + IDF 6.0

Writing SPI_USR | SPI_UPDATE directly to SPI_CMD_REG no longer reliably triggers transactions on ESP32-S3 with IDF 6.0. Commands reach the SPI data registers but the hardware does not clock them out.

Fix: use spi_device_polling_transmit() for ESP32-S3 + IDF ≥ 6.0:

#if defined (CONFIG_IDF_TARGET_ESP32S3) && (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0))
 #define LGFX_SPI_USE_IDF_POLLING_TRANSMIT
#endif

All of writeCommand(), writeData(), writeDataRepeat(), writeBytes() need a new code path using spi_device_polling_transmit().

Required changes in spi::init() for this path:

devcfg.flags = 0 (remove SPI_DEVICE_3WIRE | SPI_DEVICE_HALFDUPLEX)
buscfg.max_transfer_sz = 4096

3. GPIO35 DC/MISO function select overridden by spi_bus_initialize()

GPIO35 is shared between LCD D/C (output) and SPI MISO (input). In IDF 6.0, spi_bus_initialize() connects GPIO35 to an SPI peripheral output signal via the GPIO matrix (GPIO_FUNC35_OUT_SEL_CFG_REG), silently overriding the D/C control written to PIO_OUT1_W1TS/TC_REG. Even with OEN=1, the peripheral drives the pin, so D/C is never toggled correctly.

Fix in cs_control() — reset the GPIO function select before toggling OEN:

void cs_control(bool flg) override
{
    lgfx::Panel_ILI9342::cs_control(flg);
    // Force GPIO35 back to simple GPIO output — IDF6 spi_bus_initialize()
    // may have connected it to a peripheral output signal.
    *(volatile uint32_t*)GPIO_FUNC35_OUT_SEL_CFG_REG = SIG_GPIO_OUT_IDX;
    *(volatile uint32_t*)(flg ? GPIO_ENABLE1_W1TC_REG
                               : GPIO_ENABLE1_W1TS_REG) = 1u << (GPIO_NUM_35 & 31);
}

Additional changes for reliable operation
bus_cfg.pin_miso = GPIO_NUM_NC — decouple GPIO35 from spi_bus_initialize()
bus_cfg.spi_3wire = false
bus_cfg.spi_host = SPI3_HOST for CoreS3
Explicit hardware reset pulse via AW9523 before SPI init (LOW 20 ms → HIGH 120 ms)
freq_write = 10 MHz as safe starting frequency

Tested on M5Stack CoreS3, ESP-IDF v6.0.1, [https://github.com/wheelbot-tech/M5GFX/tree/idfv6.0]

Note

Root cause analysis and fix developed with assistance from Codex

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