From c071c619b6151befa469d777605dfc50b1485d91 Mon Sep 17 00:00:00 2001 From: ainyan03 <205502311+ainyan03@users.noreply.github.com> Date: Thu, 5 Nov 2026 07:00:00 +0000 Subject: [PATCH 1/2] M5PM1: keep the wake source and retry the first read in begin() On a ToughC5 started by the PM1 timer, the first I2C read of the PM1 in Power.begin() is NACKed. begin() then fails, the board setup goes on and clears WAKE_SRC, and only the second begin() succeeds, so the reason for the power-on is gone and an application reading it gets 0. Retry the first read and keep WAKE_SRC before it is cleared. It is available from M5.Power.M5pm1.getWakeSource(). PaperMono clears WAKE_SRC before its first begin(), so it now calls begin() first. --- src/utility/Power_Class.inl | 2 ++ src/utility/power/M5PM1_Class.hpp | 10 ++++++++++ src/utility/power/M5PM1_Class.inl | 15 ++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/utility/Power_Class.inl b/src/utility/Power_Class.inl index 67386bd7..840047eb 100644 --- a/src/utility/Power_Class.inl +++ b/src/utility/Power_Class.inl @@ -938,6 +938,8 @@ namespace m5 _pmic = pmic_t::pmic_m5pm1; _wakeupPin = GPIO_NUM_1; // PY IQR + /// bring up the PM1 early so getWakeSource() sees WAKE_SRC before it is cleared below. + M5pm1.begin(); M5pm1.clearWakeSource(); M5pm1.clearIRQStatus(); M5pm1.setGPIOIRQMaskBits(0x1E); // enable GPIO0 interrupt, disable other GPIO IRQ diff --git a/src/utility/power/M5PM1_Class.hpp b/src/utility/power/M5PM1_Class.hpp index 411f299f..538de35d 100644 --- a/src/utility/power/M5PM1_Class.hpp +++ b/src/utility/power/M5PM1_Class.hpp @@ -158,6 +158,15 @@ namespace m5 bool setPwmDuty12bit(pwm_channel_t channel, std::uint32_t duty12, pwm_polarity_t polarity = pwm_polarity_t::normal, bool enable = true); + /// get the reason for this power-on, read once by the first begin(). + /// The bits match m5pm1_wake_src_t of the M5PM1 library: 0x01 timer, 0x02 VIN, 0x04 power + /// button, 0x08 reset button, 0x10 reset command, 0x20 external GPIO, 0x40 5VINOUT. + /// @return the bits, or 0 when no reason was recorded or the read failed. + /// @note On ToughC5 and PaperMono, M5.begin() clears the PM1 register, so a read through another + /// driver afterwards returns 0. Other boards leave the register as it is, and it can still + /// hold the previous reason after a reset of the ESP32 alone. + std::uint8_t getWakeSource(void) const { return _wake_source; } + /// clear PM1 wake source bits selected by mask. /// Single-write selective clear assuming the write-zero-to-clear behavior /// adopted by the official driver; the datasheet does not specify the write polarity. @@ -252,6 +261,7 @@ namespace m5 bool powerOff(void); private: + std::uint8_t _wake_source = 0; bool _pek_double_pending = false; }; } diff --git a/src/utility/power/M5PM1_Class.inl b/src/utility/power/M5PM1_Class.inl index f41c406c..cbbf462d 100644 --- a/src/utility/power/M5PM1_Class.inl +++ b/src/utility/power/M5PM1_Class.inl @@ -70,9 +70,22 @@ namespace m5 { if (!_init) { std::uint32_t val = 0; - auto res = readRegister(M5PM1_REG_DEVICE_ID, (uint8_t*)&val, 4); + // The first transfer after an idle period can be NACKed; the next one answers. + bool res = false; + for (int retry = 3; !(res = readRegister(M5PM1_REG_DEVICE_ID, (uint8_t*)&val, 4)) && --retry; ) + { + m5gfx::delay(1); + } if (res) { + // Power.begin() clears WAKE_SRC on some boards, so keep it for getWakeSource(). + std::uint8_t wake_source = 0; + for (int retry = 3; !readRegister(M5PM1_REG_WAKE_SRC, &wake_source, 1) && --retry; ) + { + wake_source = 0; + m5gfx::delay(1); + } + _wake_source = wake_source & 0x7F; writeRegister8(M5PM1_REG_I2C_CFG, 0x00); // disable I2C idle sleep writeRegister8(M5PM1_REG_WDT_CNT, 0x00); // disable watchdog } From 3a5b340858a9d1b89a6f5cbf3d20d3567af8b072 Mon Sep 17 00:00:00 2001 From: ainyan03 <205502311+ainyan03@users.noreply.github.com> Date: Thu, 5 Nov 2026 07:00:00 +0000 Subject: [PATCH 2/2] Add the ToughC5 M-Bus pins to getPin The table now has a row for board_M5ToughC5, matching the V0.6 schematic and PCB and the board catalog. --- src/M5Unified.inl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/M5Unified.inl b/src/M5Unified.inl index 09fb97c3..93d17b9b 100644 --- a/src/M5Unified.inl +++ b/src/M5Unified.inl @@ -421,6 +421,23 @@ static constexpr const uint8_t _pin_table_mbus[][31] = { }, #elif defined (CONFIG_IDF_TARGET_ESP32H2) #elif defined (CONFIG_IDF_TARGET_ESP32C5) +{ board_t::board_M5ToughC5, + 255 , GPIO_NUM_0 , + 255 , GPIO_NUM_1 , + 255 , 255 , + GPIO_NUM_7 , GPIO_NUM_4 , + GPIO_NUM_8 , GPIO_NUM_6 , + GPIO_NUM_9 , 255 , + GPIO_NUM_12, GPIO_NUM_11, + GPIO_NUM_12, GPIO_NUM_11, + GPIO_NUM_2 , GPIO_NUM_3 , + GPIO_NUM_2 , GPIO_NUM_3 , + GPIO_NUM_23, GPIO_NUM_24, + GPIO_NUM_27, GPIO_NUM_28, + 255 , GPIO_NUM_5 , + 255 , 255 , + 255 , 255 , +}, #elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32) { board_t::board_M5Stack , 255 , GPIO_NUM_35,