From 7da7dc8844a265a6920456ae432dbc07ebd07462 Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Wed, 15 Jul 2026 19:39:17 +0200 Subject: [PATCH] fix(esp32-worker): size the IOMUX pull scan by chip GPIO count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _refresh_pin_pulls read a fixed 40 registers from get_internals(3), but the exposed array is per-chip: classic muxgpios[40], ESP32-S3 49 (GPIO0..48). The fixed bound silently missed S3 pulls on GPIO40-48. Read _GPIO_COUNT entries instead (set from the machine at startup). Pairs with qemu-lcgamboa 547e989, which models the S3 IO_MUX pull bits and exposes them via the get_internals override — together they make INPUT_PULLUP buttons work on the emulated S3 exactly like the classic ESP32 (verified on staging with GPIO4 and GPIO40). --- backend/app/services/esp32_worker.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/app/services/esp32_worker.py b/backend/app/services/esp32_worker.py index 0d68b053..96b4e735 100644 --- a/backend/app/services/esp32_worker.py +++ b/backend/app/services/esp32_worker.py @@ -560,8 +560,12 @@ def main() -> None: # noqa: C901 (complexity OK for inline worker) pulls: dict[int, int] = {} iomux_ptr = lib.qemu_picsimlab_get_internals(3) # QEMU_INTERNAL_IOMUX_GPIOS if iomux_ptr: - mux = (ctypes.c_uint32 * 40).from_address(iomux_ptr) - for gpio_pin in range(40): + # The exposed array is indexed by GPIO and sized per chip: + # classic muxgpios[40], S3 iomux regs[49] (GPIO0..48). A + # fixed 40 here missed S3 GPIO40-48 pulls entirely. + n_gpio = _GPIO_COUNT + mux = (ctypes.c_uint32 * n_gpio).from_address(iomux_ptr) + for gpio_pin in range(n_gpio): reg = int(mux[gpio_pin]) pulls[gpio_pin] = 1 if (reg >> 8) & 1 else (2 if (reg >> 7) & 1 else 0) rtcio_ptr = lib.qemu_picsimlab_get_internals(10) # QEMU_INTERNAL_RTCIO