diff --git a/.build-test-rules.yml b/.build-test-rules.yml
index a879f1e14..f241485a5 100644
--- a/.build-test-rules.yml
+++ b/.build-test-rules.yml
@@ -3,7 +3,7 @@ examples:
disable:
- if: CONFIG_NAME in ["esp-box", "esp-box-lite"]
reason: Do not build examples for deprecated BSPs
- - if: (IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR < 2) and CONFIG_NAME in ["esp_bsp_generic", "esp_bsp_devkit"]
+ - if: (IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR < 2) and CONFIG_NAME in ["esp_bsp_generic", "esp_bsp_devkit", "m5stack_core"]
reason: Example depends on BSP, which is supported only for IDF >= 5.2
- if: (IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR < 3) and CONFIG_NAME in ["esp32_p4_function_ev_board", "esp-box-3", "esp32_s3_lcd_ev_board"]
reason: Example depends on BSP, which is supported only for IDF >= 5.3
diff --git a/bsp/m5stack_core/CMakeLists.txt b/bsp/m5stack_core/CMakeLists.txt
new file mode 100644
index 000000000..8053566f2
--- /dev/null
+++ b/bsp/m5stack_core/CMakeLists.txt
@@ -0,0 +1,7 @@
+idf_component_register(
+ SRCS "m5stack_core.c"
+ INCLUDE_DIRS "include"
+ PRIV_INCLUDE_DIRS "priv_include"
+ REQUIRES driver spiffs
+ PRIV_REQUIRES fatfs esp_lcd
+)
diff --git a/bsp/m5stack_core/Kconfig b/bsp/m5stack_core/Kconfig
new file mode 100644
index 000000000..047ad0252
--- /dev/null
+++ b/bsp/m5stack_core/Kconfig
@@ -0,0 +1,93 @@
+menu "Board Support Package"
+
+ config BSP_ERROR_CHECK
+ bool "Enable error check in BSP"
+ default y
+ help
+ Error check assert the application before returning the error code.
+
+ menu "I2C"
+ config BSP_I2C_NUM
+ int "I2C peripheral index"
+ default 1
+ range 0 1
+ help
+ ESP32 has two I2C peripherals, pick the one you want to use.
+
+ config BSP_I2C_FAST_MODE
+ bool "Enable I2C fast mode"
+ default y
+ help
+ I2C has two speed modes: normal (100kHz) and fast (400kHz).
+
+ config BSP_I2C_CLK_SPEED_HZ
+ int
+ default 400000 if BSP_I2C_FAST_MODE
+ default 100000
+ endmenu
+
+ menu "SPIFFS - Virtual File System"
+ config BSP_SPIFFS_FORMAT_ON_MOUNT_FAIL
+ bool "Format SPIFFS if mounting fails"
+ default n
+ help
+ Format SPIFFS if it fails to mount the filesystem.
+
+ config BSP_SPIFFS_MOUNT_POINT
+ string "SPIFFS mount point"
+ default "/spiffs"
+ help
+ Mount point of SPIFFS in the Virtual File System.
+
+ config BSP_SPIFFS_PARTITION_LABEL
+ string "Partition label of SPIFFS"
+ default "storage"
+ help
+ Partition label which stores SPIFFS.
+
+ config BSP_SPIFFS_MAX_FILES
+ int "Max files supported for SPIFFS VFS"
+ default 5
+ help
+ Supported max files for SPIFFS in the Virtual File System.
+ endmenu
+
+ menu "SD card - Virtual File System"
+ config BSP_SD_FORMAT_ON_MOUNT_FAIL
+ bool "Format SD card if mounting fails"
+ default n
+ help
+ The SDMMC host will format (FAT) the SD card if it fails to mount the filesystem.
+
+ config BSP_SD_MOUNT_POINT
+ string "SD card mount point"
+ default "/sdcard"
+ help
+ Mount point of the SD card in the Virtual File System
+
+ endmenu
+
+ menu "Display"
+ config BSP_M5STACK_CORE_LCD_INVERT_COLOR
+ bool "Invert LCD colors (for Core v2.2 and above)"
+ default y
+ help
+ Enable this option if you have M5Stack Core v2.2 or above with IPS display.
+ Disable for older versions with TN display.
+ config BSP_DISPLAY_BRIGHTNESS_LEDC_CH
+ int "LEDC channel index"
+ default 1
+ range 0 7
+ help
+ LEDC channel is used to generate PWM signal that controls display brightness.
+ Set LEDC index that should be used.
+ endmenu
+
+ config BSP_I2S_NUM
+ int "I2S peripheral index"
+ default 0
+ range 0 1
+ help
+ ESP32 has two I2S peripherals, pick the one you want to use.
+
+endmenu
diff --git a/bsp/m5stack_core/LICENSE b/bsp/m5stack_core/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/bsp/m5stack_core/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/bsp/m5stack_core/README.md b/bsp/m5stack_core/README.md
new file mode 100644
index 000000000..7383ae40e
--- /dev/null
+++ b/bsp/m5stack_core/README.md
@@ -0,0 +1,44 @@
+# BSP: M5Stack Core
+
+> [!WARNING]
+> The SD card is not working simultaneously with the LCD screen. We are working on a fix.
+
+[![Component Registry](https://components.espressif.com/components/espressif/m5stack_core/badge.svg)](https://components.espressif.com/components/espressif/m5stack_core)
+
+* [Hardware Reference](https://docs.m5stack.com/en/core/basic_v2.7)
+
+
+
+
+This BSP supports the following M5Stack Core v2.7 series devices:
+- M5Stack Basic v2.7
+- M5Stack Fire v2.7
+- Other M5Stack Core based devices
+
+M5Stack Core is a development board based on ESP32 microcontroller. It features:
+
+- **MCU**: ESP32 dual-core Xtensa® 32-bit LX6 microprocessor, up to 240MHz
+- **Memory**: 4MB Flash + 520KB SRAM
+- **Interface**: USB Type-C for programming and debugging
+- **Display**: 2.0" TFT LCD screen (320x240 resolution) with ILI9341 controller
+ - If you have a v2.2 or above, you can enable the IPS display by setting `CONFIG_BSP_M5STACK_CORE_LCD_INVERT_COLOR=y` in the SDK configuration. Vice versa.
+- **Power Management**: IP5306 power management chip for battery charging and power control
+- **Audio**: Single GPIO controlled speaker
+- **Storage**: microSD card slot (SPI interface)
+- **Input**: Three physical buttons (ButtonA, ButtonB, ButtonC)
+- **Expansion**: Bottom expansion headers for additional modules
+
+
+### Capabilities and dependencies
+| Capability | Available | Component |Version|
+|-------------|------------------|--------------------------------------------------------------------------------------------------|-------|
+| DISPLAY |:heavy_check_mark:|[espressif/esp_lcd_ili9341](https://components.espressif.com/components/espressif/esp_lcd_ili9341)| ^1 |
+| LVGL_PORT |:heavy_check_mark:| [espressif/esp_lvgl_port](https://components.espressif.com/components/espressif/esp_lvgl_port) | ^2 |
+| TOUCH | :x: | | |
+| BUTTONS |:heavy_check_mark:| [espressif/button](https://components.espressif.com/components/espressif/button) | ^2.4 |
+| AUDIO | :x: | | |
+|AUDIO_SPEAKER|:heavy_check_mark:| | |
+| AUDIO_MIC | :x: | | |
+| SDCARD |:heavy_check_mark:| idf | >=5.2 |
+| IMU | :x: | | |
+
diff --git a/bsp/m5stack_core/idf_component.yml b/bsp/m5stack_core/idf_component.yml
new file mode 100644
index 000000000..d76f68411
--- /dev/null
+++ b/bsp/m5stack_core/idf_component.yml
@@ -0,0 +1,21 @@
+version: "1.0.0"
+description: Board Support Package (BSP) for M5Stack Core
+url: https://github.com/espressif/esp-bsp/tree/master/bsp/m5stack_core
+
+targets:
+ - esp32
+
+tags:
+ - bsp
+
+dependencies:
+ idf: ">=5.2"
+ esp_lcd_ili9341: "^1"
+
+ button:
+ version: "^2.4"
+ public: true
+
+ espressif/esp_lvgl_port:
+ version: "^2"
+ public: true
diff --git a/bsp/m5stack_core/include/bsp/config.h b/bsp/m5stack_core/include/bsp/config.h
new file mode 100644
index 000000000..f3cb5ebe7
--- /dev/null
+++ b/bsp/m5stack_core/include/bsp/config.h
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+/**************************************************************************************************
+ * BSP configuration
+ **************************************************************************************************/
+// By default, this BSP is shipped with LVGL graphical library. Enabling this option will exclude it.
+// If you want to use BSP without LVGL, select BSP version with 'noglib' suffix.
+#if !defined(BSP_CONFIG_NO_GRAPHIC_LIB) // Check if the symbol is not coming from compiler definitions (-D...)
+#define BSP_CONFIG_NO_GRAPHIC_LIB (0)
+#endif
diff --git a/bsp/m5stack_core/include/bsp/display.h b/bsp/m5stack_core/include/bsp/display.h
new file mode 100644
index 000000000..1963bbd68
--- /dev/null
+++ b/bsp/m5stack_core/include/bsp/display.h
@@ -0,0 +1,121 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief BSP LCD
+ *
+ * This file offers API for basic LCD control.
+ * It is useful for users who want to use the LCD without the default Graphical Library LVGL.
+ *
+ * For standard LCD initialization with LVGL graphical library, you can call all-in-one function bsp_display_start().
+ */
+
+#pragma once
+#include "esp_lcd_types.h"
+
+/* LCD color formats */
+#define ESP_LCD_COLOR_FORMAT_RGB565 (1)
+#define ESP_LCD_COLOR_FORMAT_RGB888 (2)
+
+/* LCD display color format */
+#define BSP_LCD_COLOR_FORMAT (ESP_LCD_COLOR_FORMAT_RGB565)
+/* LCD display color bytes endianess */
+#define BSP_LCD_BIGENDIAN (1)
+/* LCD display color bits */
+#define BSP_LCD_BITS_PER_PIXEL (16)
+/* LCD display color space */
+#define BSP_LCD_COLOR_SPACE (ESP_LCD_COLOR_SPACE_BGR)
+/* LCD definition */
+#define BSP_LCD_H_RES (320)
+#define BSP_LCD_V_RES (240)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief BSP display configuration structure
+ *
+ */
+typedef struct {
+ int max_transfer_sz; /*!< Maximum transfer size, in bytes. */
+} bsp_display_config_t;
+
+/**
+ * @brief Create new display panel
+ *
+ * For maximum flexibility, this function performs only reset and initialization of the display.
+ * You must turn on the display explicitly by calling esp_lcd_panel_disp_on_off().
+ * The display's backlight is not turned on either. You can use bsp_display_backlight_on/off(),
+ * bsp_display_brightness_set() (on supported boards) or implement your own backlight control.
+ *
+ * If you want to free resources allocated by this function, you can use esp_lcd API, ie.:
+ *
+ * \code{.c}
+ * esp_lcd_panel_del(panel);
+ * esp_lcd_panel_io_del(io);
+ * spi_bus_free(spi_num_from_configuration);
+ * \endcode
+ *
+ * @param[in] config display configuration
+ * @param[out] ret_panel esp_lcd panel handle
+ * @param[out] ret_io esp_lcd IO handle
+ * @return
+ * - ESP_OK On success
+ * - Else esp_lcd failure
+ */
+esp_err_t bsp_display_new(const bsp_display_config_t *config, esp_lcd_panel_handle_t *ret_panel, esp_lcd_panel_io_handle_t *ret_io);
+
+/**
+ * @brief Initialize display's brightness
+ *
+ * Brightness is controlled with AXP2101 via I2C.
+ *
+ * @return
+ * - ESP_OK On success
+ * - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t bsp_display_brightness_init(void);
+
+/**
+ * @brief Set display's brightness
+ *
+ * Brightness is controlled with AXP2101 via I2C.
+ * Backlight must be already initialized by calling bsp_display_brightness_init() or bsp_display_start()
+ *
+ * @param[in] brightness_percent Brightness in [%]
+ * @return
+ * - ESP_OK On success
+ * - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t bsp_display_brightness_set(int brightness_percent);
+
+/**
+ * @brief Turn on display backlight
+ *
+ * Backlight must be already initialized by calling bsp_display_brightness_init() or bsp_display_start()
+ *
+ * @return
+ * - ESP_OK On success
+ * - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t bsp_display_backlight_on(void);
+
+/**
+ * @brief Turn off display backlight
+ *
+ * Backlight must be already initialized by calling bsp_display_brightness_init() or bsp_display_start()
+ *
+ * @return
+ * - ESP_OK On success
+ * - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t bsp_display_backlight_off(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/bsp/m5stack_core/include/bsp/esp-bsp.h b/bsp/m5stack_core/include/bsp/esp-bsp.h
new file mode 100644
index 000000000..78b794cf2
--- /dev/null
+++ b/bsp/m5stack_core/include/bsp/esp-bsp.h
@@ -0,0 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+#include "bsp/m5stack_core.h"
diff --git a/bsp/m5stack_core/include/bsp/m5stack_core.h b/bsp/m5stack_core/include/bsp/m5stack_core.h
new file mode 100644
index 000000000..d77242a43
--- /dev/null
+++ b/bsp/m5stack_core/include/bsp/m5stack_core.h
@@ -0,0 +1,341 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief ESP BSP: M5Stack Core
+ */
+
+#pragma once
+
+#include "sdkconfig.h"
+#include "driver/gpio.h"
+#include "driver/sdmmc_host.h"
+#include "bsp/config.h"
+#include "bsp/display.h"
+
+#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
+#include "lvgl.h"
+#include "esp_lvgl_port.h"
+#endif // BSP_CONFIG_NO_GRAPHIC_LIB == 0
+
+#include "iot_button.h"
+
+/**************************************************************************************************
+ * BSP Capabilities
+ **************************************************************************************************/
+
+#define BSP_CAPS_DISPLAY 1
+#define BSP_CAPS_TOUCH 0
+#define BSP_CAPS_BUTTONS 1
+#define BSP_CAPS_AUDIO 0
+#define BSP_CAPS_AUDIO_SPEAKER 1
+#define BSP_CAPS_AUDIO_MIC 0
+#define BSP_CAPS_SDCARD 1
+#define BSP_CAPS_IMU 0
+
+/**************************************************************************************************
+ * M5Stack-Core pinout
+ **************************************************************************************************/
+/* I2C */
+#define BSP_I2C_SCL (GPIO_NUM_22)
+#define BSP_I2C_SDA (GPIO_NUM_21)
+
+/* Audio */
+#define BSP_SPEAKER_IO (GPIO_NUM_25)
+
+/* Display */
+#define BSP_LCD_MOSI (GPIO_NUM_23)
+#define BSP_LCD_MISO (GPIO_NUM_NC)
+#define BSP_LCD_PCLK (GPIO_NUM_18)
+#define BSP_LCD_CS (GPIO_NUM_14)
+#define BSP_LCD_DC (GPIO_NUM_27)
+#define BSP_LCD_RST (GPIO_NUM_33)
+#define BSP_LCD_BACKLIGHT (GPIO_NUM_32)
+
+/* SD card */
+#define BSP_SD_MOSI (GPIO_NUM_23)
+#define BSP_SD_MISO (GPIO_NUM_19)
+#define BSP_SD_SCK (GPIO_NUM_18)
+#define BSP_SD_CS (GPIO_NUM_4)
+
+/* BUTTON */
+#define BSP_BUTTON_LEFT (GPIO_NUM_39)
+#define BSP_BUTTON_MIDDLE (GPIO_NUM_38)
+#define BSP_BUTTON_RIGHT (GPIO_NUM_37)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************************************
+ *
+ * Speaker interface
+ *
+ * M5Stack-Core has a simple speaker that can be controlled via GPIO.
+ * The speaker must be initialized before use by calling bsp_speaker_init()
+ **************************************************************************************************/
+/**
+ * @brief Initialize speaker GPIO
+ *
+ * @return
+ * - ESP_OK On success
+ * - ESP_ERR_INVALID_ARG GPIO parameter error
+ */
+esp_err_t bsp_speaker_init(void);
+
+/**************************************************************************************************
+ *
+ * I2C interface
+ *
+ * There are multiple devices connected to I2C peripheral:
+ * - IP5306
+ **************************************************************************************************/
+#define BSP_I2C_NUM CONFIG_BSP_I2C_NUM
+
+/**
+ * @brief Init I2C driver
+ *
+ * @return
+ * - ESP_OK On success
+ * - ESP_ERR_INVALID_ARG I2C parameter error
+ * - ESP_FAIL I2C driver installation error
+ *
+ */
+esp_err_t bsp_i2c_init(void);
+
+/**
+ * @brief Deinit I2C driver and free its resources
+ *
+ * @return
+ * - ESP_OK On success
+ * - ESP_ERR_INVALID_ARG I2C parameter error
+ *
+ */
+esp_err_t bsp_i2c_deinit(void);
+
+/**************************************************************************************************
+ *
+ * SPIFFS
+ *
+ * After mounting the SPIFFS, it can be accessed with stdio functions ie.:
+ * \code{.c}
+ * FILE* f = fopen(BSP_SPIFFS_MOUNT_POINT"/hello.txt", "w");
+ * fprintf(f, "Hello World!\n");
+ * fclose(f);
+ * \endcode
+ **************************************************************************************************/
+#define BSP_SPIFFS_MOUNT_POINT CONFIG_BSP_SPIFFS_MOUNT_POINT
+
+/**
+ * @brief Mount SPIFFS to virtual file system
+ *
+ * @return
+ * - ESP_OK on success
+ * - ESP_ERR_INVALID_STATE if esp_vfs_spiffs_register was already called
+ * - ESP_ERR_NO_MEM if memory can not be allocated
+ * - ESP_FAIL if partition can not be mounted
+ * - other error codes
+ */
+esp_err_t bsp_spiffs_mount(void);
+
+/**
+ * @brief Unmount SPIFFS from virtual file system
+ *
+ * @return
+ * - ESP_OK on success
+ * - ESP_ERR_NOT_FOUND if the partition table does not contain SPIFFS partition with given label
+ * - ESP_ERR_INVALID_STATE if esp_vfs_spiffs_unregister was already called
+ * - ESP_ERR_NO_MEM if memory can not be allocated
+ * - ESP_FAIL if partition can not be mounted
+ * - other error codes
+ */
+esp_err_t bsp_spiffs_unmount(void);
+
+/**************************************************************************************************
+ *
+ * SD card
+ *
+ * After mounting the SD card, it can be accessed with stdio functions ie.:
+ * \code{.c}
+ * FILE* f = fopen(BSP_SD_MOUNT_POINT"/hello.txt", "w");
+ * fprintf(f, "Hello %s!\n", bsp_sdcard->cid.name);
+ * fclose(f);
+ * \endcode
+ *
+ * @attention IO2 is also routed to RGB LED and push button
+ **************************************************************************************************/
+#define BSP_SD_MOUNT_POINT CONFIG_BSP_SD_MOUNT_POINT
+extern sdmmc_card_t *bsp_sdcard;
+
+/**
+ * @brief Mount microSD card to virtual file system
+ *
+ * @return
+ * - ESP_OK on success
+ * - ESP_ERR_INVALID_STATE if esp_vfs_fat_sdmmc_mount was already called
+ * - ESP_ERR_NO_MEM if memory can not be allocated
+ * - ESP_FAIL if partition can not be mounted
+ * - other error codes from SDMMC or SPI drivers, SDMMC protocol, or FATFS drivers
+ */
+esp_err_t bsp_sdcard_mount(void);
+
+/**
+ * @brief Unmount micorSD card from virtual file system
+ *
+ * @return
+ * - ESP_OK on success
+ * - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label
+ * - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount was already called
+ * - ESP_ERR_NO_MEM if memory can not be allocated
+ * - ESP_FAIL if partition can not be mounted
+ * - other error codes from wear levelling library, SPI flash driver, or FATFS drivers
+ */
+esp_err_t bsp_sdcard_unmount(void);
+
+/**************************************************************************************************
+ *
+ * LCD interface
+ *
+ * M5Stack-Core is shipped with 2.0inch ILI9341C display controller.
+ * It features 16-bit colors, 320x240 resolution.
+ *
+ * LVGL is used as graphics library. LVGL is NOT thread safe, therefore the user must take LVGL mutex
+ * by calling bsp_display_lock() before calling and LVGL API (lv_...) and then give the mutex with
+ * bsp_display_unlock().
+ *
+ * Display's backlight must be enabled explicitly by calling bsp_display_backlight_on()
+ **************************************************************************************************/
+#define BSP_LCD_PIXEL_CLOCK_HZ (40 * 1000 * 1000)
+#define BSP_LCD_SPI_NUM (SPI2_HOST)
+
+#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
+#define BSP_LCD_DRAW_BUFF_SIZE (BSP_LCD_H_RES * 50)
+#define BSP_LCD_DRAW_BUFF_DOUBLE (1)
+
+/**
+ * @brief BSP display configuration structure
+ */
+typedef struct {
+ lvgl_port_cfg_t lvgl_port_cfg; /*!< LVGL port configuration */
+ uint32_t buffer_size; /*!< Size of the buffer for the screen in pixels */
+ bool double_buffer; /*!< True, if should be allocated two buffers */
+ struct {
+ unsigned int buff_dma: 1; /*!< Allocated LVGL buffer will be DMA capable */
+ unsigned int buff_spiram: 1; /*!< Allocated LVGL buffer will be in PSRAM */
+ } flags;
+} bsp_display_cfg_t;
+/**
+ * @brief Initialize display
+ *
+ * This function initializes SPI, display controller and starts LVGL handling task.
+ * LCD backlight must be enabled separately by calling bsp_display_brightness_set()
+ *
+ * @return Pointer to LVGL display or NULL when error occured
+ */
+lv_display_t *bsp_display_start(void);
+
+/**
+ * @brief Initialize display
+ *
+ * This function initializes SPI, display controller and starts LVGL handling task.
+ * LCD backlight must be enabled separately by calling bsp_display_brightness_set()
+ *
+ * @param cfg display configuration
+ *
+ * @return Pointer to LVGL display or NULL when error occured
+ */
+lv_display_t *bsp_display_start_with_config(const bsp_display_cfg_t *cfg);
+
+/**
+ * @brief Get pointer to input device (touch, buttons, ...)
+ *
+ * @note The LVGL input device is initialized in bsp_display_start() function.
+ *
+ * @return Pointer to LVGL input device or NULL when not initialized
+ */
+lv_indev_t *bsp_display_get_input_dev(void);
+
+/**
+ * @brief Take LVGL mutex
+ *
+ * @param timeout_ms Timeout in [ms]. 0 will block indefinitely.
+ * @return true Mutex was taken
+ * @return false Mutex was NOT taken
+ */
+bool bsp_display_lock(uint32_t timeout_ms);
+
+/**
+ * @brief Give LVGL mutex
+ *
+ */
+void bsp_display_unlock(void);
+
+/**
+ * @brief Rotate screen
+ *
+ * Display must be already initialized by calling bsp_display_start()
+ *
+ * @param[in] disp Pointer to LVGL display
+ * @param[in] rotation Angle of the display rotation
+ */
+void bsp_display_rotate(lv_display_t *disp, lv_display_rotation_t rotation);
+#endif // BSP_CONFIG_NO_GRAPHIC_LIB == 0
+
+/**************************************************************************************************
+ *
+ * BSP Features
+ *
+ * This module provides an interface to enable and disable various features on the M5Stack-Core-2 board.
+ * Supported features include the LCD display, touch screen, SD card, and speaker.
+ *
+ * The bsp_feature_enable function is used to enable or disable a specified feature.
+ * It communicates with the Power Management Unit (PMU) via the I2C interface to control the power of each feature.
+ *
+ * Supported PMU models include AXP2101 and AXP192.
+ * Depending on the configuration, the function selects the appropriate PMU registers and values to enable or disable the feature.
+ *
+ * Parameters:
+ * - feature: The feature to enable or disable, of type bsp_feature_t enum.
+ * - enable: A boolean value, true to enable the feature, false to disable it.
+ *
+ * Return value:
+ * - esp_err_t: Error code indicating the result of the operation.
+ *
+ **************************************************************************************************/
+typedef enum {
+ BSP_FEATURE_LCD,
+} bsp_feature_t;
+
+esp_err_t bsp_feature_enable(bsp_feature_t feature, bool enable);
+
+/**************************************************************************************************
+ *
+ * Button interface
+ *
+ * M5Stack-Core has three buttons:
+ * - Left button (GPIO39): Used for navigation (previous)
+ * - Middle button (GPIO38): Used for selection (enter)
+ * - Right button (GPIO37): Used for navigation (next)
+ *
+ * The buttons can be used with LVGL for UI navigation
+ **************************************************************************************************/
+/**
+ * @brief Create button objects
+ *
+ * @param btn_array Output array of button handles
+ * @param btn_cnt Output number of created buttons
+ * @param btn_array_size Size of output array
+ * @return
+ * - ESP_OK Success
+ * - ESP_ERR_INVALID_ARG Parameter error
+ * - ESP_FAIL Create button failed
+ */
+esp_err_t bsp_iot_button_create(button_handle_t btn_array[], int *btn_cnt, int btn_array_size);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/bsp/m5stack_core/m5stack_core.c b/bsp/m5stack_core/m5stack_core.c
new file mode 100644
index 000000000..3811e8f1a
--- /dev/null
+++ b/bsp/m5stack_core/m5stack_core.c
@@ -0,0 +1,470 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "bsp/m5stack_core.h"
+#include "bsp/display.h"
+#include "esp_lcd_ili9341.h"
+#include "bsp_err_check.h"
+
+static const char *TAG = "M5Stack";
+
+#define BSP_IP5306_ADDR 0x75
+
+#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
+static lv_display_t *disp;
+static lv_indev_t *disp_indev = NULL;
+/* Button definitions */
+typedef enum {
+ BSP_BUTTON_PREV, // Button left
+ BSP_BUTTON_ENTER, // Button middle
+ BSP_BUTTON_NEXT, // Button right
+ BSP_BUTTON_NUM
+} bsp_button_t;
+#endif // (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
+static i2c_master_bus_handle_t i2c_handle = NULL;
+static bool i2c_initialized = false;
+static i2c_master_dev_handle_t ip5306_h = NULL;
+static bool spi_initialized = false;
+
+esp_err_t bsp_i2c_init(void)
+{
+ /* I2C was initialized before */
+ if (i2c_initialized) {
+ return ESP_OK;
+ }
+
+ const i2c_master_bus_config_t i2c_config = {
+ .i2c_port = BSP_I2C_NUM,
+ .scl_io_num = BSP_I2C_SCL,
+ .sda_io_num = BSP_I2C_SDA,
+ .clk_source = I2C_CLK_SRC_DEFAULT,
+ };
+ BSP_ERROR_CHECK_RETURN_ERR(i2c_new_master_bus(&i2c_config, &i2c_handle));
+
+ const i2c_device_config_t ip5306_config = {
+ .dev_addr_length = I2C_ADDR_BIT_LEN_7,
+ .device_address = BSP_IP5306_ADDR,
+ .scl_speed_hz = CONFIG_BSP_I2C_CLK_SPEED_HZ,
+ };
+ BSP_ERROR_CHECK_RETURN_ERR(i2c_master_bus_add_device(i2c_handle, &ip5306_config, &ip5306_h));
+
+ i2c_initialized = true;
+
+ return ESP_OK;
+}
+
+esp_err_t bsp_i2c_deinit(void)
+{
+ if (i2c_initialized) {
+ // Delete I2C device for IP5306 first
+ if (i2c_handle != NULL) {
+ i2c_master_bus_rm_device(ip5306_h);
+ ip5306_h = NULL;
+ }
+ // Then delete the I2C master bus
+ BSP_ERROR_CHECK_RETURN_ERR(i2c_del_master_bus(i2c_handle));
+ i2c_handle = NULL;
+ i2c_initialized = false;
+ }
+ return ESP_OK;
+}
+
+esp_err_t bsp_feature_enable(bsp_feature_t feature, bool enable)
+{
+ esp_err_t err = ESP_OK;
+
+ /* Initialize I2C */
+ BSP_ERROR_CHECK_RETURN_ERR(bsp_i2c_init());
+
+ switch (feature) {
+ case BSP_FEATURE_LCD:
+ // backlight is controlled by GPIO
+ if (enable) {
+ err = bsp_display_backlight_on();
+ } else {
+ err = bsp_display_backlight_off();
+ }
+ break;
+ }
+ return err;
+}
+
+static esp_err_t bsp_spi_init(uint32_t max_transfer_sz)
+{
+ /* SPI was initialized before */
+ if (spi_initialized) {
+ return ESP_OK;
+ }
+
+ ESP_LOGD(TAG, "Initialize SPI bus");
+ const spi_bus_config_t buscfg = {
+ .sclk_io_num = BSP_LCD_PCLK,
+ .mosi_io_num = BSP_LCD_MOSI,
+ .miso_io_num = BSP_LCD_MISO,
+ .quadwp_io_num = GPIO_NUM_NC,
+ .quadhd_io_num = GPIO_NUM_NC,
+ .max_transfer_sz = max_transfer_sz,
+ };
+ ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed");
+
+ spi_initialized = true;
+
+ return ESP_OK;
+}
+
+esp_err_t bsp_spiffs_mount(void)
+{
+ esp_vfs_spiffs_conf_t conf = {
+ .base_path = CONFIG_BSP_SPIFFS_MOUNT_POINT,
+ .partition_label = CONFIG_BSP_SPIFFS_PARTITION_LABEL,
+ .max_files = CONFIG_BSP_SPIFFS_MAX_FILES,
+#ifdef CONFIG_BSP_SPIFFS_FORMAT_ON_MOUNT_FAIL
+ .format_if_mount_failed = true,
+#else
+ .format_if_mount_failed = false,
+#endif
+ };
+
+ esp_err_t ret_val = esp_vfs_spiffs_register(&conf);
+
+ BSP_ERROR_CHECK_RETURN_ERR(ret_val);
+
+ size_t total = 0, used = 0;
+ ret_val = esp_spiffs_info(conf.partition_label, &total, &used);
+ if (ret_val != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret_val));
+ } else {
+ ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
+ }
+
+ return ret_val;
+}
+
+esp_err_t bsp_spiffs_unmount(void)
+{
+ return esp_vfs_spiffs_unregister(CONFIG_BSP_SPIFFS_PARTITION_LABEL);
+}
+
+esp_err_t bsp_sdcard_mount(void)
+{
+ const esp_vfs_fat_sdmmc_mount_config_t mount_config = {
+#ifdef CONFIG_BSP_SD_FORMAT_ON_MOUNT_FAIL
+ .format_if_mount_failed = true,
+#else
+ .format_if_mount_failed = false,
+#endif
+ .max_files = 5,
+ .allocation_unit_size = 16 * 1024
+ };
+
+ sdmmc_host_t host = SDSPI_HOST_DEFAULT();
+ host.slot = BSP_LCD_SPI_NUM;
+ sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
+ slot_config.gpio_cs = BSP_SD_CS;
+ slot_config.host_id = host.slot;
+
+ ESP_RETURN_ON_ERROR(bsp_spi_init((BSP_LCD_H_RES * BSP_LCD_V_RES) * sizeof(uint16_t)), TAG, "");
+
+ return esp_vfs_fat_sdspi_mount(BSP_SD_MOUNT_POINT, &host, &slot_config, &mount_config, &bsp_sdcard);
+}
+
+esp_err_t bsp_sdcard_unmount(void)
+{
+ return esp_vfs_fat_sdcard_unmount(BSP_SD_MOUNT_POINT, bsp_sdcard);
+}
+
+esp_err_t bsp_speaker_init(void)
+{
+ // Configure speaker GPIO as output mode
+ gpio_config_t io_conf = {
+ .pin_bit_mask = (1ULL << BSP_SPEAKER_IO),
+ .mode = GPIO_MODE_OUTPUT,
+ .pull_up_en = GPIO_PULLUP_DISABLE,
+ .pull_down_en = GPIO_PULLDOWN_DISABLE,
+ .intr_type = GPIO_INTR_DISABLE,
+ };
+ ESP_ERROR_CHECK(gpio_config(&io_conf));
+
+ gpio_set_level(BSP_SPEAKER_IO, 0); // Turn off speaker
+
+ return ESP_OK;
+}
+
+#define LCD_CMD_BITS 8
+#define LCD_PARAM_BITS 8
+#define LCD_LEDC_CH CONFIG_BSP_DISPLAY_BRIGHTNESS_LEDC_CH
+
+esp_err_t bsp_display_brightness_init(void)
+{
+ // Setup LEDC peripheral for PWM backlight control
+ const ledc_channel_config_t LCD_backlight_channel = {
+ .gpio_num = BSP_LCD_BACKLIGHT,
+ .speed_mode = LEDC_LOW_SPEED_MODE,
+ .channel = LCD_LEDC_CH,
+ .intr_type = LEDC_INTR_DISABLE,
+ .timer_sel = 1,
+ .duty = 0,
+ .hpoint = 0
+ };
+ const ledc_timer_config_t LCD_backlight_timer = {
+ .speed_mode = LEDC_LOW_SPEED_MODE,
+ .duty_resolution = LEDC_TIMER_10_BIT,
+ .timer_num = 1,
+ .freq_hz = 5000,
+ .clk_cfg = LEDC_AUTO_CLK
+ };
+
+ BSP_ERROR_CHECK_RETURN_ERR(ledc_timer_config(&LCD_backlight_timer));
+ BSP_ERROR_CHECK_RETURN_ERR(ledc_channel_config(&LCD_backlight_channel));
+
+ return ESP_OK;
+}
+
+esp_err_t bsp_display_brightness_set(int brightness_percent)
+{
+ if (brightness_percent > 100) {
+ brightness_percent = 100;
+ }
+ if (brightness_percent < 0) {
+ brightness_percent = 0;
+ }
+
+ ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness_percent);
+ uint32_t duty_cycle = (1023 * brightness_percent) / 100; // LEDC resolution set to 10bits, thus: 100% = 1023
+ BSP_ERROR_CHECK_RETURN_ERR(ledc_set_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH, duty_cycle));
+ BSP_ERROR_CHECK_RETURN_ERR(ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH));
+
+ return ESP_OK;
+}
+
+esp_err_t bsp_display_backlight_off(void)
+{
+ return bsp_display_brightness_set(0);
+}
+
+esp_err_t bsp_display_backlight_on(void)
+{
+ return bsp_display_brightness_set(100);
+}
+
+esp_err_t bsp_display_new(const bsp_display_config_t *config, esp_lcd_panel_handle_t *ret_panel,
+ esp_lcd_panel_io_handle_t *ret_io)
+{
+ esp_err_t ret = ESP_OK;
+ assert(config != NULL && config->max_transfer_sz > 0);
+
+ BSP_ERROR_CHECK_RETURN_ERR(bsp_feature_enable(BSP_FEATURE_LCD, true));
+
+ /* Initialize SPI */
+ ESP_RETURN_ON_ERROR(bsp_spi_init(config->max_transfer_sz), TAG, "");
+
+ ESP_LOGI(TAG, "Install panel IO");
+ const esp_lcd_panel_io_spi_config_t io_config = {
+ .dc_gpio_num = BSP_LCD_DC,
+ .cs_gpio_num = BSP_LCD_CS,
+ .pclk_hz = BSP_LCD_PIXEL_CLOCK_HZ,
+ .lcd_cmd_bits = LCD_CMD_BITS,
+ .lcd_param_bits = LCD_PARAM_BITS,
+ .spi_mode = 0,
+ .trans_queue_depth = 10,
+ };
+ 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");
+
+ ESP_LOGI(TAG, "Install LCD driver");
+ const esp_lcd_panel_dev_config_t panel_config = {
+ .reset_gpio_num = BSP_LCD_RST, // Shared with Touch reset
+ .color_space = BSP_LCD_COLOR_SPACE,
+ .bits_per_pixel = BSP_LCD_BITS_PER_PIXEL,
+ };
+
+ ESP_GOTO_ON_ERROR(esp_lcd_new_panel_ili9341(*ret_io, &panel_config, ret_panel), err, TAG, "New panel failed");
+
+ esp_lcd_panel_reset(*ret_panel);
+ esp_lcd_panel_init(*ret_panel);
+#if CONFIG_BSP_M5STACK_CORE_LCD_INVERT_COLOR
+ esp_lcd_panel_invert_color(*ret_panel, true);
+#else
+ esp_lcd_panel_invert_color(*ret_panel, false);
+#endif
+ return ret;
+
+err:
+ if (*ret_panel) {
+ esp_lcd_panel_del(*ret_panel);
+ }
+ if (*ret_io) {
+ esp_lcd_panel_io_del(*ret_io);
+ }
+ spi_bus_free(BSP_LCD_SPI_NUM);
+ return ret;
+}
+
+#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
+static lv_display_t *bsp_display_lcd_init(const bsp_display_cfg_t *cfg)
+{
+ assert(cfg != NULL);
+ esp_lcd_panel_io_handle_t io_handle = NULL;
+ esp_lcd_panel_handle_t panel_handle = NULL;
+ const bsp_display_config_t bsp_disp_cfg = {
+ .max_transfer_sz = BSP_LCD_DRAW_BUFF_SIZE * sizeof(uint16_t),
+ };
+
+ BSP_ERROR_CHECK_RETURN_NULL(bsp_display_new(&bsp_disp_cfg, &panel_handle, &io_handle));
+
+ esp_lcd_panel_disp_on_off(panel_handle, true);
+
+ /* Add LCD screen */
+ ESP_LOGD(TAG, "Add LCD screen");
+ const lvgl_port_display_cfg_t disp_cfg = {
+ .io_handle = io_handle,
+ .panel_handle = panel_handle,
+ .buffer_size = cfg->buffer_size,
+ .double_buffer = cfg->double_buffer,
+ .hres = BSP_LCD_H_RES,
+ .vres = BSP_LCD_V_RES,
+ .monochrome = false,
+ /* Rotation values must be same as used in esp_lcd for initial settings of the screen */
+ .rotation =
+ {
+ .swap_xy = false,
+ .mirror_x = false,
+ .mirror_y = false,
+ },
+ .flags = {
+ .buff_dma = cfg->flags.buff_dma,
+ .buff_spiram = cfg->flags.buff_spiram,
+#if LVGL_VERSION_MAJOR >= 9
+ .swap_bytes = (BSP_LCD_BIGENDIAN ? true : false),
+#endif
+ }
+ };
+
+ return lvgl_port_add_disp(&disp_cfg);
+}
+
+static const button_config_t bsp_button_config[BSP_BUTTON_NUM] = {
+ {
+ .type = BUTTON_TYPE_GPIO,
+ .gpio_button_config.active_level = false,
+ .gpio_button_config.gpio_num = BSP_BUTTON_LEFT,
+ },
+ {
+ .type = BUTTON_TYPE_GPIO,
+ .gpio_button_config.active_level = false,
+ .gpio_button_config.gpio_num = BSP_BUTTON_MIDDLE,
+ },
+ {
+ .type = BUTTON_TYPE_GPIO,
+ .gpio_button_config.active_level = false,
+ .gpio_button_config.gpio_num = BSP_BUTTON_RIGHT,
+ },
+};
+
+static lv_indev_t *bsp_display_indev_init(lv_display_t *disp)
+{
+ const lvgl_port_nav_btns_cfg_t btns = {
+ .disp = disp,
+ .button_prev = &bsp_button_config[BSP_BUTTON_PREV],
+ .button_next = &bsp_button_config[BSP_BUTTON_NEXT],
+ .button_enter = &bsp_button_config[BSP_BUTTON_ENTER]
+ };
+
+ return lvgl_port_add_navigation_buttons(&btns);
+}
+
+lv_display_t *bsp_display_start(void)
+{
+ bsp_display_cfg_t cfg = {.lvgl_port_cfg = ESP_LVGL_PORT_INIT_CONFIG(),
+ .buffer_size = BSP_LCD_DRAW_BUFF_SIZE,
+ .double_buffer = BSP_LCD_DRAW_BUFF_DOUBLE,
+ .flags = {
+ .buff_dma = true,
+ .buff_spiram = false,
+ }
+ };
+ cfg.lvgl_port_cfg.task_affinity = 1; /* For camera */
+ return bsp_display_start_with_config(&cfg);
+}
+
+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));
+
+ BSP_ERROR_CHECK_RETURN_NULL(bsp_display_brightness_init());
+
+ BSP_NULL_CHECK(disp = bsp_display_lcd_init(cfg), NULL);
+
+ // Initialize keypad input device
+ BSP_NULL_CHECK(disp_indev = bsp_display_indev_init(disp), NULL);
+
+ // Turn on backlight
+ bsp_display_backlight_on();
+
+ return disp;
+}
+
+lv_indev_t *bsp_display_get_input_dev(void)
+{
+ return disp_indev;
+}
+
+void bsp_display_rotate(lv_display_t *disp, lv_display_rotation_t rotation)
+{
+ lv_disp_set_rotation(disp, rotation);
+}
+
+bool bsp_display_lock(uint32_t timeout_ms)
+{
+ return lvgl_port_lock(timeout_ms);
+}
+
+void bsp_display_unlock(void)
+{
+ lvgl_port_unlock();
+}
+
+esp_err_t bsp_iot_button_create(button_handle_t btn_array[], int *btn_cnt, int btn_array_size)
+{
+ esp_err_t ret = ESP_OK;
+ if ((btn_array_size < BSP_BUTTON_NUM) || (btn_array == NULL)) {
+ return ESP_ERR_INVALID_ARG;
+ }
+
+ if (btn_cnt) {
+ *btn_cnt = 0;
+ }
+ for (int i = 0; i < BSP_BUTTON_NUM; i++) {
+ btn_array[i] = iot_button_create(&bsp_button_config[i]);
+ if (btn_array[i] == NULL) {
+ ret = ESP_FAIL;
+ break;
+ }
+ if (btn_cnt) {
+ (*btn_cnt)++;
+ }
+ }
+ return ret;
+}
+#endif // (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
diff --git a/bsp/m5stack_core/priv_include/bsp_err_check.h b/bsp/m5stack_core/priv_include/bsp_err_check.h
new file mode 100644
index 000000000..cf2f36eb4
--- /dev/null
+++ b/bsp/m5stack_core/priv_include/bsp_err_check.h
@@ -0,0 +1,58 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include "esp_check.h"
+#include "sdkconfig.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Assert on error, if selected in menuconfig. Otherwise return error code. */
+#if CONFIG_BSP_ERROR_CHECK
+#define BSP_ERROR_CHECK_RETURN_ERR(x) ESP_ERROR_CHECK(x)
+#define BSP_ERROR_CHECK_RETURN_NULL(x) ESP_ERROR_CHECK(x)
+#define BSP_ERROR_CHECK(x, ret) ESP_ERROR_CHECK(x)
+#define BSP_NULL_CHECK(x, ret) assert(x)
+#define BSP_NULL_CHECK_GOTO(x, goto_tag) assert(x)
+#else
+#define BSP_ERROR_CHECK_RETURN_ERR(x) do { \
+ esp_err_t err_rc_ = (x); \
+ if (unlikely(err_rc_ != ESP_OK)) { \
+ return err_rc_; \
+ } \
+ } while(0)
+
+#define BSP_ERROR_CHECK_RETURN_NULL(x) do { \
+ if (unlikely((x) != ESP_OK)) { \
+ return NULL; \
+ } \
+ } while(0)
+
+#define BSP_NULL_CHECK(x, ret) do { \
+ if ((x) == NULL) { \
+ return ret; \
+ } \
+ } while(0)
+
+#define BSP_ERROR_CHECK(x, ret) do { \
+ if (unlikely((x) != ESP_OK)) { \
+ return ret; \
+ } \
+ } while(0)
+
+#define BSP_NULL_CHECK_GOTO(x, goto_tag) do { \
+ if ((x) == NULL) { \
+ goto goto_tag; \
+ } \
+ } while(0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/bsp/m5stack_core_2/README.md b/bsp/m5stack_core_2/README.md
index 89967d1f2..10bb4ebfd 100644
--- a/bsp/m5stack_core_2/README.md
+++ b/bsp/m5stack_core_2/README.md
@@ -16,6 +16,8 @@ M5Core2 is the second generation core device in the M5Stack development kit seri
- **Interface**: USB TYPE-C interface for charging, program downloading, and serial communication.
- **Display**: 2.0-inch integrated capacitive touch screen with three programmable capacitive buttons on the front.
- **Power Management:** Managed by an AXP192 power management chip (upgraded to AXP2101 in Core2 V1.1), which effectively controls power consumption. It includes a built-in green LED power indicator for battery level notification. The battery capacity is 390mAh, providing longer power duration than the previous model.
+ - For Core2 V1.0: Configure `CONFIG_BSP_PMU_AXP192`
+ - For Core2 V1.1: Configure `CONFIG_BSP_PMU_AXP2101`
- **Audio**: I2S digital audio interface power amplifier chip to prevent signal distortion, along with a built-in speaker.
- **Expansion**: Retains a TF-card (microSD) slot, and an expansion board on the back with a 6-axis IMU sensor and a microphone.
- **RTC Module**: Built-in RTC module for accurate timing, with a dedicated battery for RTC power supply in Core2 V1.1.
diff --git a/examples/bsp_ext.py b/examples/bsp_ext.py
index 78d2b52fc..6549a9f8c 100644
--- a/examples/bsp_ext.py
+++ b/examples/bsp_ext.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import os
from re import match, compile
@@ -61,7 +61,8 @@ def set_bsp_callback(action: str, ctx: Context, args: PropertyDict, **kwargs: st
'esp32_p4_function_ev_board',
'm5stack_core_s3',
'm5dial',
- 'm5stack_core_2'
+ 'm5stack_core_2',
+ 'm5stack_core',
}
if bsp == '':
diff --git a/examples/display/sdkconfig.bsp.m5stack_core b/examples/display/sdkconfig.bsp.m5stack_core
new file mode 100644
index 000000000..636599d69
--- /dev/null
+++ b/examples/display/sdkconfig.bsp.m5stack_core
@@ -0,0 +1,25 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+CONFIG_IDF_TARGET="esp32"
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP_DEFAULT_CPU_FREQ_240=y
+
+## LVGL8 ##
+CONFIG_LV_USE_PERF_MONITOR=y
+CONFIG_LV_COLOR_16_SWAP=y
+CONFIG_LV_MEM_CUSTOM=y
+CONFIG_LV_MEMCPY_MEMSET_STD=y
+
+## LVGL9 ##
+CONFIG_LV_CONF_SKIP=y
+
+#CLIB default
+CONFIG_LV_USE_CLIB_MALLOC=y
+CONFIG_LV_USE_CLIB_SPRINTF=y
+CONFIG_LV_USE_CLIB_STRING=y
+
+# Performance monitor
+CONFIG_LV_USE_OBSERVER=y
+CONFIG_LV_USE_SYSMON=y
+CONFIG_LV_USE_PERF_MONITOR=y