critical_section: use 0x88 mask on v4 to avoid INESTEN=1 wedge - #25
Merged
Conversation
V4 silicon (CH32V20x) wedges with MIE stuck at 0 in user code when critical_section::with is invoked inside an ISR body with INTSYSCR.INESTEN=1. The standard 0x8 mask creates an MIE=0/MPIE=1 mismatch that V4's nested-interrupt machinery handles incorrectly, eventually propagating MIE=0 outward via nested mrets. The 0x88 mask (MIE+MPIE together) matches the openwch SDK __disable_irq/__enable_irq pattern for V20x [1] and preserves the implicit "MIE and MPIE move together" invariant V4 assumes. Uses gintenr (CSR 0x800, bit-level alias of mstatus per V4 manual §8.3) to match the openwch site exactly. Repro: dxl-pirate (embassy on CH32V203C8T6) at INTSYSCR=0b0111 wedges within ~3000 USART3 pings on the 0x8 mask; 0x88 cleared 40K+. [1] https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/SRC/Core/core_riscv.h
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.
Summary
V4 cores (CH32V20x) can wedge with
MIEstuck at 0 in user code whencritical_section::withruns inside an ISR body whileINTSYSCR.INESTEN=1. The standard 0x8-mask path touchesMIEonly, leaving anMIE=0/MPIE=1mismatch that V4's nested-interrupt machinery doesn't recover from —MIE=0eventually propagates outward through nestedmrets, all async IRQs end up masked indefinitely, and the system silently stalls (no sync exception, ISR enter/exit counts balanced).This PR routes V4 through its own cfg arm using the 0x88 mask (
MIE+MPIEtogether viagintenr), matching openwch's__disable_irq/__enable_irqpattern for V20x [1] and preserving the implicit "MIE and MPIE move together" invariant V4 expects inside an ISR body.Why openwch's C SDK doesn't hit this
C code without an embassy-style task runtime essentially never invokes a
critical_section-style acquire from inside an ISR body, so the bad path doesn't fire. openwch's__disable_irq/__enable_irqhappen to use the 0x88 mask anyway — likely accidental robustness inherited from older WCH conventions, no comment explains it.Verification
Reproduced on CH32V203C8T6 with embassy + nested PFIC (
INTSYSCR=0b0111, HWSTKEN + INESTEN + PMTCFG=01): wedge fires within a few thousand IRQ-driven round-trips on the standard 0x8 mask; the 0x88 mask cleared tens of thousands without recurrence.PMTCFG=0(no preempt classes possible) still wedges, so the trigger is theINESTENbit enabling the nesting machinery, not actual L2-preempt firings.References
core_riscv.h