Fix ESP32-C6 GPIO hold capability and add cross-platform smoke builds

This commit is contained in:
mikecarper committed 2026-10-17 21:41:47 -07:00
1 parent ce35e21480
commit 80023f79e0
3 files changed
+47 -1

No files matched your search

+10
View File
@@ -88,6 +88,16 @@ jobs:
--firmware-version v1.17.1.10-halo-keymind-cascade-dev
--radio-preset usa-cascade-fixed --profile cascade --require-ota
cross-platform-smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Build Environment
uses: ./.github/actions/setup-build-environment
- name: Compile RP2040 contact storage and Arduino 3 ESP32-C6 room services
# One process: PlatformIO environments share this checkout's build tree.
run: pio run -e Xiao_rp2040_companion_radio_usb -e LilyGo_Tlora_C6_room_server_
management-reports:
runs-on: ubuntu-latest
steps:
+8 -1
View File
@@ -72,7 +72,8 @@ inline esp_err_t configureHeldOutput(gpio_num_t pin, uint32_t level) {
// Explicitly select a known output before latching it. RTC pads can also be
// retained for packet-wake sleep (e.g. W12 FEM rails). Non-RTC/digital pads
// require the terminal-only commit below; never globally freeze live pads.
// on older chips require the terminal-only commit below; chips with per-pad
// deep-sleep retention hold directly. Never globally freeze live pads.
// The IDF GPIO API selects the correct RTC/digital hold implementation.
inline esp_err_t holdOutputForDeepSleep(gpio_num_t pin, uint32_t level) {
esp_err_t result = configureHeldOutput(pin, level);
@@ -92,15 +93,21 @@ inline esp_err_t releaseOutputAfterDeepSleep(gpio_num_t pin, uint32_t level) {
}
inline void resetTerminalDeepSleepHolds() {
#if !defined(SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP) || !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
gpio_deep_sleep_hold_dis();
#endif
terminalDigitalHoldPending() = false;
}
inline void commitTerminalDeepSleepHolds() {
// Chips such as C6 retain individual gpio_hold_en pads during deep sleep
// and do not expose the global auto-hold API. Older chips need auto-hold.
// IDF4.4's digital auto-hold affects all digital pads DURING deep sleep.
// Arm it only after every virtual shutdown hook and transport quiescence,
// immediately before terminal deep sleep; never in runtime or light sleep.
#if !defined(SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP) || !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
if (terminalDigitalHoldPending()) gpio_deep_sleep_hold_en();
#endif
}
} // namespace esp32
+29
View File
@@ -77,15 +77,21 @@ inline int gpio_hold_dis(int pin) {
if(!api_result) pads[pin].hold=false;
return api_result;
}
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
inline void gpio_deep_sleep_hold_en() { deep_hold=true; ++deep_hold_en_calls; }
inline void gpio_deep_sleep_hold_dis() { deep_hold=false; ++deep_hold_dis_calls; }
#endif
inline void simulate_deep_sleep() {
for(int pin=0;pin<64;++pin) {
bool rtc=false;
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
rtc=rtc_gpio_is_valid_gpio(pin);
#endif
#if SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
if(!rtc && !pads[pin].hold) { pads[pin].output=false; pads[pin].retained=-1; }
#else
if(!rtc && !deep_hold) { pads[pin].output=false; pads[pin].retained=-1; }
#endif
}
}
'''
@@ -249,6 +255,29 @@ int main(){ mesh::esp32::resetTerminalDeepSleepHolds(); femShutdown();
void femShutdown(){ assert(mesh::esp32::holdOutputForDeepSleep(42,1)==ESP_OK); }
''')
def test_single_pad_deep_sleep_hold_omits_unavailable_global_apis(self):
# IDF5.3 C6 headers omit the global APIs entirely. Per-pad holds are
# retained directly, including across reset until the pin is released.
self.compile_run(r'''
#include <helpers/ESP32GpioHold.h>
int main() {
using namespace mesh::esp32;
resetTerminalDeepSleepHolds();
assert(!terminalDigitalHoldPending() && deep_hold_dis_calls==0);
assert(holdOutputForDeepSleep(18,1)==ESP_OK);
commitTerminalDeepSleepHolds();
assert(!deep_hold && deep_hold_en_calls==0);
simulate_deep_sleep();
assert(physical(18)==1);
pads[18].latch=0; pads[18].output=false;
resetTerminalDeepSleepHolds();
assert(deep_hold_dis_calls==0);
assert(releaseOutputAfterDeepSleep(18,1)==ESP_OK);
assert(!pads[18].hold && physical(18)==1);
}
''', caps=1, defines=('SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP=1',
'CONFIG_IDF_TARGET_ESP32C6=1'))
def test_only_terminal_sleep_commits_after_virtual_shutdown_and_wake_setup(self):
production=(ROOT/'src/helpers/ESP32Board.cpp').read_text()
sleep=body(production,'void ESP32Board::enterDeepSleep(uint32_t secs)')