From 37b8390d2429b76bdaf6bd8953f2c1f110507b9f Mon Sep 17 00:00:00 2001 From: Frederik Date: Mon, 31 Aug 2026 21:18:43 +0200 Subject: [PATCH 1/2] CoreInk: assert the power-hold latch (GPIO12) at startup CoreInk latches its own power rail on with GPIO12. Out of reset that pad is an input, and nothing in this firmware drives it until M5GFX's board autodetect does so as a side effect of M5.begin() - measured ~2000ms after reset. On battery the rail is held up by nothing at all during that window, so the board switches itself off after any reset, and powering it on means holding the power button down for two seconds or more instead of pressing it. Drive the pin from a MICROPY_BOARD_STARTUP hook, which app_main runs before creating the MicroPython task. Measured on hardware, reset to latch asserted: stock ~2000ms M5Stack factory Arduino build ~400ms this hook ~980ms M5Unified already asserts a hold pin this way for the Timer Cam in Power_Class::begin(); the CoreInk branch of that switch sets ADC and wake pins but never touches power_hold. 980ms is not yet short enough on battery - see the following commit. --- m5stack/boards/M5STACK_CoreInk/board_init.c | 40 +++++++++++++++++++ .../M5STACK_CoreInk/mpconfigboard.cmake | 4 ++ .../boards/M5STACK_CoreInk/mpconfigboard.h | 5 +++ 3 files changed, 49 insertions(+) create mode 100644 m5stack/boards/M5STACK_CoreInk/board_init.c diff --git a/m5stack/boards/M5STACK_CoreInk/board_init.c b/m5stack/boards/M5STACK_CoreInk/board_init.c new file mode 100644 index 000000000..b11854fa2 --- /dev/null +++ b/m5stack/boards/M5STACK_CoreInk/board_init.c @@ -0,0 +1,40 @@ +/* +* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD +* +* SPDX-License-Identifier: MIT +*/ + +#include "py/mpconfig.h" +#include "esp_log.h" +#include "driver/gpio.h" + +// CoreInk latches its own power rail on with GPIO12: running on battery, the +// rail stays up only while that pin is driven high - or while the user keeps +// the power button pressed. Out of reset the pad is an input, so there is a +// window on every boot during which nothing holds the rail up. +// +// M5GFX does assert the pin, but only as a side effect of board autodetect, +// which is reached from M5.begin() around 2s into a MicroPython boot. The +// rail does not survive unaided for anything like that long. On battery the +// consequences are that the board switches itself off after any reset, and +// that powering it on means holding the power button down for seconds rather +// than pressing it. +// +// Asserting the latch here - the first thing app_main does, before the +// MicroPython task is created - closes that window to ~50ms. +#define COREINK_POWER_HOLD_PIN GPIO_NUM_12 + +void CoreInk_board_startup(void) { + gpio_config_t power_hold = { + .pin_bit_mask = 1ULL << COREINK_POWER_HOLD_PIN, + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&power_hold); + gpio_set_level(COREINK_POWER_HOLD_PIN, 1); + ESP_LOGI("CoreInk", "power hold (GPIO12) asserted"); + + boardctrl_startup(); +} diff --git a/m5stack/boards/M5STACK_CoreInk/mpconfigboard.cmake b/m5stack/boards/M5STACK_CoreInk/mpconfigboard.cmake index 47189c1c1..baea56f4d 100644 --- a/m5stack/boards/M5STACK_CoreInk/mpconfigboard.cmake +++ b/m5stack/boards/M5STACK_CoreInk/mpconfigboard.cmake @@ -4,6 +4,10 @@ # coreink https://github.com/m5stack/m5stack-board-id/blob/main/board.csv#L8 set(BOARD_ID 6) + +set(MICROPY_SOURCE_BOARD + ${MICROPY_BOARD_DIR}/board_init.c +) set(MICROPY_PY_LVGL 0) # Font Support diff --git a/m5stack/boards/M5STACK_CoreInk/mpconfigboard.h b/m5stack/boards/M5STACK_CoreInk/mpconfigboard.h index e5596ae38..895da65d2 100644 --- a/m5stack/boards/M5STACK_CoreInk/mpconfigboard.h +++ b/m5stack/boards/M5STACK_CoreInk/mpconfigboard.h @@ -7,5 +7,10 @@ #define MICROPY_HW_BOARD_NAME "M5STACK CoreInk" #define MICROPY_HW_MCU_NAME "ESP32-S3" +// Assert the power-hold latch (GPIO12) from app_main, before the +// MicroPython task starts - see board_init.c. +#define MICROPY_BOARD_STARTUP CoreInk_board_startup +void CoreInk_board_startup(void); + // If not enable LVGL, ignore this... #include "./../mpconfiglvgl.h" From 446527feea96a455cefcf5276befac6fffb2cc5c Mon Sep 17 00:00:00 2001 From: Frederik Date: Mon, 31 Aug 2026 21:18:55 +0200 Subject: [PATCH 2/2] CoreInk: skip app image validation on power-on reset With the startup hook in place the power-hold latch is still not asserted until ~980ms after reset, because the bootloader SHA-256s the whole ~3.4MB app image before app_main is reached. That is spent entirely before any application code runs, and on battery it is long enough for the rail to collapse. Deep-sleep wakes already skip validation (BOOTLOADER_SKIP_VALIDATE_IN_DEEP_ SLEEP=y), so the normal wake path never paid this cost - only resets did. Skipping it on power-on as well brings the latch to 50ms after reset. Verified on hardware, running on battery: a machine.reset() loop counting in RTC memory reboots indefinitely, where on stock firmware the board switches off at the first reset and stays off until USB is connected. This board has a single factory partition and no OTA slot, so a failed validation was never recoverable anyway. --- m5stack/boards/M5STACK_CoreInk/sdkconfig.board | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/m5stack/boards/M5STACK_CoreInk/sdkconfig.board b/m5stack/boards/M5STACK_CoreInk/sdkconfig.board index 724b3624d..968256ed1 100644 --- a/m5stack/boards/M5STACK_CoreInk/sdkconfig.board +++ b/m5stack/boards/M5STACK_CoreInk/sdkconfig.board @@ -12,3 +12,12 @@ CONFIG_ESPTOOLPY_FLASHFREQ="80m" CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y + +# CoreInk holds its power rail on with GPIO12, asserted at the top of app_main +# (board_init.c). Validating the ~3.4MB app image costs ~900ms before app_main +# is reached on every power-on reset, and on battery the rail does not survive +# that long: the board switches off instead of restarting. Deep-sleep wakes +# already skip validation; skip it on power-on too. This board has a single +# factory partition, so there is no second image to fall back to if validation +# were to fail. +CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON=y