From 224c12477edd516f488327fe2fb26473f8d14260 Mon Sep 17 00:00:00 2001 From: mbwilliamson1581 Date: Thu, 2 Apr 2026 11:02:08 -0400 Subject: [PATCH 1/5] Revised m5stack_core_s3.c to provide LCD and SD concurrent functionality with the shared SPI bus Initiation and mounting follows: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/sdspi_share.html 1) Initialize SPI Bus 2.1) Attach other SPI Devices which will tie those CS lines high 3) Attach SD to SPI Bus and Mount SD Card --- bsp/m5stack_core_s3/m5stack_core_s3.c | 78 ++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/bsp/m5stack_core_s3/m5stack_core_s3.c b/bsp/m5stack_core_s3/m5stack_core_s3.c index 45affaf2f..39f2ec27d 100644 --- a/bsp/m5stack_core_s3/m5stack_core_s3.c +++ b/bsp/m5stack_core_s3/m5stack_core_s3.c @@ -59,6 +59,12 @@ static i2c_master_dev_handle_t axp2101_h = NULL; static i2c_master_dev_handle_t aw9523_h = NULL; static bool spi_initialized = false; +#define AW9523_REG_INPUT0 0x00 ///< Register for reading input values +#define AW9523_REG_OUTPUT0 0x02 ///< Register for writing output values +#define AW9523_REG_CONFIG0 0x04 ///< Register for configuring direction +#define AW9523_REG_INTENABLE0 0x06 ///< Register for enabling interrupt +#define AW9523_REG_GCR 0x11 ///< Register for general configuration + esp_err_t bsp_i2c_init(void) { /* I2C was initialized before */ @@ -66,11 +72,14 @@ esp_err_t bsp_i2c_init(void) return ESP_OK; } + // Schematic p3 shows I2C_SYS_SDA & I2C_SYS_SCL connectec via R20 2.2k & R22 2.2k to VDD_3V3 + // Add .flags.enable_internal_pullup to negate Warning 1617: i2c.master: Please check pull-up resistances whether be connected properly.... const i2c_master_bus_config_t i2c_config = { .i2c_port = BSP_I2C_NUM, .sda_io_num = BSP_I2C_SDA, .scl_io_num = BSP_I2C_SCL, .clk_source = I2C_CLK_SRC_DEFAULT, + .flags.enable_internal_pullup = true, }; BSP_ERROR_CHECK_RETURN_ERR(i2c_new_master_bus(&i2c_config, &i2c_handle)); @@ -89,7 +98,37 @@ esp_err_t bsp_i2c_init(void) BSP_ERROR_CHECK_RETURN_ERR(i2c_master_bus_add_device(i2c_handle, &aw9523_config, &aw9523_h)); i2c_initialized = true; - return ESP_OK; + + uint8_t data[2]; + esp_err_t err = ESP_OK; + // MBMW Feature + data[0] = AW9523_REG_CONFIG0; // 1 for input, 0 for output + data[1] = 0b00000000; // P0_3 = ES_INT, P0_4 = TF_SW + data[1] |= (BSP_CAPS_AUDIO) ? 0b00001000 : 0; // P0_3 = ES_INT + data[1] |= (BSP_CAPS_SDCARD)? 0b00010000 : 0; // P0_4 = TF_SW + err |= i2c_master_transmit(aw9523_h, data, sizeof(data), 1000); + + data[0] = AW9523_REG_CONFIG0 + 1; // 1 for input, 0 for output + data[1] = 0b00000000; // P1_2 = TOUCH_INT, P1_3 = AW_INT + data[1] |= (BSP_CAPS_TOUCH)? 0b00000100 : 0; // P1_2 = TOUCH_INT + data[1] |= (BSP_CAPS_AUDIO)? 0b00001000 : 0; // P1_3 = AW_INT + err |= i2c_master_transmit(aw9523_h, data, sizeof(data), 1000); + + data[0] = AW9523_REG_INTENABLE0; // 0 = Interrupt enabled, 1 = Interrupt disabled + data[1] = 0b11111111; // P0_3 = ES_INT + data[1] &= (BSP_CAPS_AUDIO) ? 0b11110111 : 255; // P0_3 = ES_INT + err |= i2c_master_transmit(aw9523_h, data, sizeof(data), 1000); + + data[0] = AW9523_REG_INTENABLE0 + 1 ; // 0 = Interrupt enabled, 1 = Interrupt disabled + data[1] = 0b11111111; // P1_2 = TOUCH_INT, P1_3 = AW_INT + // Do Not enable interrupts for TOUCH. esp_lcg_touch_ft5x06.c requires hard gpio for interrupt. + // If esp-idf featured io_expansion with enum gpio_num_t > GPIO_NUM_MAX + // then custom 'overloads' could be implemented to support interrupt from io_expander + // ** data[1] &= (BSP_CAPS_TOUCH)? 0b11111011 : 255; // P1_2 = TOUCH_INT + data[1] &= (BSP_CAPS_AUDIO)? 0b11110111 : 255; // P1_3 = AW_INT + err |= i2c_master_transmit(aw9523_h, data, sizeof(data), 1000); + + return err; } esp_err_t bsp_i2c_deinit(void) @@ -149,15 +188,15 @@ static esp_err_t bsp_enable_feature(bsp_feature_t feature) } /* AW9523 P0 is in push-pull mode */ - data[0] = 0x11; - data[1] = 0x10; + data[0] = AW9523_REG_GCR; + data[1] = 0x10; // Bit 4 1 = Push-pull, 0 = Open-drain err |= i2c_master_transmit(aw9523_h, data, sizeof(data), 1000); - data[0] = 0x02; + data[0] = AW9523_REG_OUTPUT0; data[1] = aw9523_P0; err |= i2c_master_transmit(aw9523_h, data, sizeof(data), 1000); - data[0] = 0x03; + data[0] = AW9523_REG_OUTPUT0 + 1; data[1] = aw9523_P1; err |= i2c_master_transmit(aw9523_h, data, sizeof(data), 1000); @@ -303,11 +342,19 @@ esp_err_t bsp_sdcard_sdspi_mount(bsp_sdcard_cfg_t *cfg) cfg->slot.sdspi = &sdslot; } -#if !CONFIG_FATFS_LONG_FILENAMES +#if !(defined(CONFIG_FATFS_LONG_FILENAMES) || !defined(CONFIG_FATFS_LFN_NONE)) ESP_LOGW(TAG, "Warning: Long filenames on SD card are disabled in menuconfig!"); #endif - return esp_vfs_fat_sdspi_mount(BSP_SD_MOUNT_POINT, cfg->host, cfg->slot.sdspi, cfg->mount, &bsp_sdcard); + // MBMW SD & LCD Sharing SPI Bus + // Ensure sdspi_mount is only called once + if(bsp_sdcard == NULL) { + return esp_vfs_fat_sdspi_mount(BSP_SD_MOUNT_POINT, cfg->host, cfg->slot.sdspi, cfg->mount, &bsp_sdcard); + } else { + ESP_LOGW(TAG, "SD card already mounted!"); + return ESP_OK; + } + } esp_err_t bsp_sdcard_mount(void) @@ -476,6 +523,17 @@ esp_err_t bsp_display_new(const bsp_display_config_t *config, esp_lcd_panel_hand ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, ret_io), err, TAG, "New panel IO failed"); + // MBMW SD & LCD Sharing SPI Bus + if(BSP_CAPS_SDCARD) { + esp_err_t sd_ret = bsp_sdcard_mount(); + if(sd_ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to mount SD during LCD initialization, error: %s", esp_err_to_name(sd_ret)); + } else { + ESP_LOGI(TAG, "SD Card mounted successfully during LCD initialization"); + } + + } + ESP_LOGD(TAG, "Install LCD driver"); const esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = BSP_LCD_RST, // Shared with Touch reset @@ -601,12 +659,18 @@ lv_display_t *bsp_display_start_with_config(const bsp_display_cfg_t *cfg) assert(cfg != NULL); BSP_ERROR_CHECK_RETURN_NULL(lvgl_port_init(&cfg->lvgl_port_cfg)); + // MBMW SD & LCD Sharing SPI Bus. Ensure nothing is sent to the LCD by LVGL + lvgl_port_stop(); + BSP_ERROR_CHECK_RETURN_NULL(bsp_display_brightness_init()); BSP_NULL_CHECK(disp = bsp_display_lcd_init(cfg), NULL); BSP_NULL_CHECK(disp_indev = bsp_display_indev_init(disp), NULL); + // MBMW SD & LCD Sharing SPI Bus. Everything is set up, we can allow updates to the LCD + lvgl_port_resume(); + return disp; } From 8ff32cd5476d3b91cd3d4d438ea0cf41a848326d Mon Sep 17 00:00:00 2001 From: mbwilliamson1581 Date: Thu, 2 Apr 2026 11:28:31 -0400 Subject: [PATCH 2/5] Revise README.md and API.md for M5Stack Core S3 to reflect the latest updates and improvements in the API and documentation. Ensure that all new features and changes Revise Version reflecting SD and LCD support. --- bsp/m5stack_core_s3/API.md | 8 ++++++-- bsp/m5stack_core_s3/README.md | 1 + bsp/m5stack_core_s3/idf_component.yml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bsp/m5stack_core_s3/API.md b/bsp/m5stack_core_s3/API.md index d036f1237..4a02cf7c0 100644 --- a/bsp/m5stack_core_s3/API.md +++ b/bsp/m5stack_core_s3/API.md @@ -243,13 +243,17 @@ bsp_spiffs_unmount(); ### SD Card Initialization / Deinitialization -The BSP offers a flexible API for working with SD cards. In addition to the default mount and unmount functions, you can also use a configuration structure or access preconfigured `host` and `slot` structures. +The SD Card and LCD share an SPI bus. +https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/sdspi_share.html +The SD Card is mounted during the bsp_display_start() process and occurs during the bsp_display_mount() function if the SDCARD capability is set using BSP_CAPS_SDCARD macro. Do not use the the default mount API "bsp_sdcard_mount()" +The BSP offers a flexible API for working with SD cards. File operations and unmount functions remain unchanged. +You can also use a configuration structure or access preconfigured `host` and `slot` structures. Mount with Default Configuration ``` /* Mount microSD card to the virtual file system */ -bsp_sdcard_mount(); +** Mounting occurs automatically during bsp_display_start() process ** /* ... perform file operations ... */ diff --git a/bsp/m5stack_core_s3/README.md b/bsp/m5stack_core_s3/README.md index 3f0a92300..20c0fb94e 100644 --- a/bsp/m5stack_core_s3/README.md +++ b/bsp/m5stack_core_s3/README.md @@ -4,6 +4,7 @@ | --- | --- | --- | --- | -- | > [!WARNING] > The SD card is not working simultaneously with the LCD screen. We are working on a fix. +> **** SD Card IS working in this fork *** ## Overview diff --git a/bsp/m5stack_core_s3/idf_component.yml b/bsp/m5stack_core_s3/idf_component.yml index d30219f54..5f14aea22 100644 --- a/bsp/m5stack_core_s3/idf_component.yml +++ b/bsp/m5stack_core_s3/idf_component.yml @@ -1,4 +1,4 @@ -version: "3.0.2" +version: "3.1.0" description: Board Support Package (BSP) for M5Stack CoreS3 url: https://github.com/espressif/esp-bsp/tree/master/bsp/m5stack_core_s3 From f51d01a06db151f4da9c3bfa6bc7affc645a556b Mon Sep 17 00:00:00 2001 From: mbwilliamson1581 Date: Thu, 2 Apr 2026 12:47:23 -0400 Subject: [PATCH 3/5] Rev Line 345: ** #if !(defined(CONFIG_FATFS_LONG_FILENAMES) || defined(CONFIG_FATFS_LFN_STACK) || defined(CONFIG_FATFS_LFN_HEAP)) --- bsp/m5stack_core_s3/m5stack_core_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsp/m5stack_core_s3/m5stack_core_s3.c b/bsp/m5stack_core_s3/m5stack_core_s3.c index 39f2ec27d..c79128bb0 100644 --- a/bsp/m5stack_core_s3/m5stack_core_s3.c +++ b/bsp/m5stack_core_s3/m5stack_core_s3.c @@ -342,7 +342,7 @@ esp_err_t bsp_sdcard_sdspi_mount(bsp_sdcard_cfg_t *cfg) cfg->slot.sdspi = &sdslot; } -#if !(defined(CONFIG_FATFS_LONG_FILENAMES) || !defined(CONFIG_FATFS_LFN_NONE)) +#if !(defined(CONFIG_FATFS_LONG_FILENAMES) || defined(CONFIG_FATFS_LFN_STACK) || defined(CONFIG_FATFS_LFN_HEAP)) ESP_LOGW(TAG, "Warning: Long filenames on SD card are disabled in menuconfig!"); #endif From df282b713e14c19f45754d318ea24ef30b41a065 Mon Sep 17 00:00:00 2001 From: mbwilliamson1581 Date: Thu, 2 Apr 2026 13:51:01 -0400 Subject: [PATCH 4/5] Only free SPI when *disp and *bsp_sdcard are NULL --- bsp/m5stack_core_s3/m5stack_core_s3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bsp/m5stack_core_s3/m5stack_core_s3.c b/bsp/m5stack_core_s3/m5stack_core_s3.c index c79128bb0..f21becc21 100644 --- a/bsp/m5stack_core_s3/m5stack_core_s3.c +++ b/bsp/m5stack_core_s3/m5stack_core_s3.c @@ -371,7 +371,8 @@ esp_err_t bsp_sdcard_unmount(void) bsp_sdcard = NULL; //TODO: Check if LCD initialized (when LCD deinit will be covered by BSP) - if (spi_initialized) { + // Only free SPI when *disp and *bsp_sdcard are NULL + if ((spi_initialized) && (disp == NULL) && (bsp_sdcard == NULL)) { ret |= spi_bus_free(BSP_SDSPI_HOST); spi_initialized = false; } From b6824a9277c89a4255737b5a8df25327a9142b75 Mon Sep 17 00:00:00 2001 From: mbwilliamson1581 Date: Fri, 3 Apr 2026 08:00:15 -0400 Subject: [PATCH 5/5] static esp_err_t bsp_sdcard_mount_worker(void) created to handle SD Card mounting during LCD initialization. esp_err_t bsp_sdcard_mount() is now a dummy function to retain API compatibility, with a log message indicating that SD Card is initialized and mounted during LCD initialization due to shared SPI bus. --- bsp/m5stack_core_s3/API.md | 7 +++++-- bsp/m5stack_core_s3/m5stack_core_s3.c | 9 +++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/bsp/m5stack_core_s3/API.md b/bsp/m5stack_core_s3/API.md index 4a02cf7c0..8a50fc49d 100644 --- a/bsp/m5stack_core_s3/API.md +++ b/bsp/m5stack_core_s3/API.md @@ -245,7 +245,7 @@ bsp_spiffs_unmount(); The SD Card and LCD share an SPI bus. https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/sdspi_share.html -The SD Card is mounted during the bsp_display_start() process and occurs during the bsp_display_mount() function if the SDCARD capability is set using BSP_CAPS_SDCARD macro. Do not use the the default mount API "bsp_sdcard_mount()" +The SD Card is mounted during the bsp_display_start() process and occurs during the bsp_display_mount() function if the SDCARD capability is set using BSP_CAPS_SDCARD macro. Default API "bsp_sdcard_mount()" is retained but is a dummy function. The BSP offers a flexible API for working with SD cards. File operations and unmount functions remain unchanged. You can also use a configuration structure or access preconfigured `host` and `slot` structures. @@ -253,9 +253,12 @@ Mount with Default Configuration ``` /* Mount microSD card to the virtual file system */ -** Mounting occurs automatically during bsp_display_start() process ** +// Mounting occurs automatically during bsp_display_start() process ** +// bsp_sdcard_mount() is retained for API compatibility but is only a dummy function +bsp_sdcard_mount(); /* ... perform file operations ... */ +// File operations can occur after bsp_display_start(); /* Unmount microSD card */ bsp_sdcard_unmount(); diff --git a/bsp/m5stack_core_s3/m5stack_core_s3.c b/bsp/m5stack_core_s3/m5stack_core_s3.c index f21becc21..ca30e6499 100644 --- a/bsp/m5stack_core_s3/m5stack_core_s3.c +++ b/bsp/m5stack_core_s3/m5stack_core_s3.c @@ -358,6 +358,12 @@ esp_err_t bsp_sdcard_sdspi_mount(bsp_sdcard_cfg_t *cfg) } esp_err_t bsp_sdcard_mount(void) +{ + ESP_LOGI(TAG, "bsp_sdcard_mount() Dummy function for m5stack_core_s3 API. SD Card and LCD share SPI bus. SD Card is initialized and mounted during LCD initialization."); + return ESP_OK; +} + +static esp_err_t bsp_sdcard_mount_worker(void) { bsp_sdcard_cfg_t cfg = {0}; return bsp_sdcard_sdspi_mount(&cfg); @@ -526,13 +532,12 @@ esp_err_t bsp_display_new(const bsp_display_config_t *config, esp_lcd_panel_hand // MBMW SD & LCD Sharing SPI Bus if(BSP_CAPS_SDCARD) { - esp_err_t sd_ret = bsp_sdcard_mount(); + esp_err_t sd_ret = bsp_sdcard_mount_worker(); if(sd_ret != ESP_OK) { ESP_LOGW(TAG, "Failed to mount SD during LCD initialization, error: %s", esp_err_to_name(sd_ret)); } else { ESP_LOGI(TAG, "SD Card mounted successfully during LCD initialization"); } - } ESP_LOGD(TAG, "Install LCD driver");