fix(multicore): reset core1 on PSM PROC1 release so MicroPython _thread stops hanging#60
Merged
Merged
Conversation
…ging MicroPython (>= v1.28.0) runs pico-sdk's multicore_reset_core1() before every _thread.start_new_thread: it forces PROC1 in PSM.FRCE_OFF, then blocks in multicore_fifo_pop_blocking() waiting for core1's bootrom to push its "ready" word (0). Writing FRCE_OFF was an inert register store, so core1 never left reset, never signalled, and core0 slept in WFE forever. Give PsmPeripheral an OnProc1Released callback that fires on the FRCE_OFF PROC1 set -> clear transition. RP2040Machine wires it to reset core1, clear the SIO launch handshake, and inject the ready word (SioPeripheral.SignalCore1BootromReady: drain core1's mailbox, enqueue 0 into core0's RX FIFO, SetInterrupt + SEV). That unblocks the pop; the subsequent §2.8.3 launch sequence is already handled by HandleLaunchHandshake. MulticoreResetTests drives the full hw_set_bits/hw_clear_bits -> PSM -> SIO path through the bus and asserts the ready word and the SEV wake. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Older builds (<= v1.21.0) don't call multicore_reset_core1 in the _thread path, so they can't exercise the core1-reset hang. Embed MicroPython v1.28.0 — the version that reproduces it (as does the Wokwi pedestrian-crossing sketch, project 469350452950129665) — and add MicroPythonThreadTests: a worker thread must run on core1 and the main thread must continue past start_new_thread instead of blocking in WFE. Add v1.28.0 to the version-compatibility matrix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problema
_thread.start_new_threaden MicroPython (≥ v1.28.0) colgaba a core0 indefinidamente en WFE.Antes de cada
start_new_thread, MicroPython invocamulticore_reset_core1()de la pico-sdk, que:PSM.FRCE_OFF, espera el read-back, y lo limpia.0) por el FIFO a core0.multicore_fifo_pop_blocking()esperando esa palabra.En el emulador, escribir
PSM.FRCE_OFFera un store de registro inerte: core1 nunca salía de reset, nunca mandaba el0, y core0 dormía en WFE para siempre. El handshake §2.8.3 (HandleLaunchHandshake) ya estaba bien implementado, pero core0 moría antes de llegar a él (launchSeqPos=0), en el paso de reset.Solución (~64 líneas, 3 archivos)
PsmPeripheral: nuevo callbackOnProc1Released, disparado al detectar la transición set → clear del bit PROC1 (bit 16) enFRCE_OFF. El puente APB ya traduce los alias atómicos dehw_set_bits/hw_clear_bitsa un read-modify-write sobre el offset base, así que la detección es directa y fiable.SioPeripheral.SignalCore1BootromReady(): vacía el mailbox de entrada de core1, encola el0de "listo" en el FIFO Core1→Core0, y haceSetInterrupt(15)+EventRegistered(SEV) para despertar el WFE de core0.RP2040Machine.ResetCore1FromPsm(): cablea el callback → resetea core1, limpia el estado de launch del SIO, y emite la señal de listo. La secuencia de launch posterior la maneja el handshake existente.Validación con firmware real
Detalle clave descubierto durante la investigación: v1.21.0 NO reproduce el bug (su
_threadno llama amulticore_reset_core1), por eso la validación usa MicroPython v1.28.0.Verificación definitiva: con el fix desactivado el test cuelga; con el fix, pasa.
MulticoreResetTests(unit): ejercen el camino completohw_set_bits/hw_clear_bits→ PSM → SIO a través del bus, y verifican la palabra de listo y el wake por SEV.MicroPythonThreadTests(integración): sobre v1.28.0 real, un thread worker corre en core1 (CORE1-ALIVE) y el thread principal continúa más allá destart_new_thread(MAIN-DONE) en vez de bloquearse.micropython-v1.28.0.uf2embebido en el assembly de tests (offline-capable) y añadido a la matriz de versiones soportadas.Resultados
hello_multicore,multicore_fifo_irqs), que no ejercitabanmulticore_reset_core1.🤖 Generated with Claude Code