machine: avoid sync.Once during ESP32 startup

UART initialization runs before the scheduler has a current task.
Once.Do uses defer, which requires a current task when panic recovery
is enabled.

Use an interrupt-protected flag for this unicore initialization path
instead.
This commit is contained in:
Jake Bailey
2026-09-04 09:46:55 -07:00
committed by Ron Evans
parent 3725265fb0
commit a96cc30257
+7 -5
View File
@@ -478,7 +478,7 @@ var (
rtsctsSignal: 199, rtsctsSignal: 199,
} }
onceUart = sync.Once{} uartInterruptConfigured bool
) )
// CPU interrupt line used for all UART peripherals. // CPU interrupt line used for all UART peripherals.
@@ -588,11 +588,13 @@ func (uart *UART) configureInterrupt() {
} }
// Register the ISR only once (shared across all UARTs on the same CPU int). // Register the ISR only once (shared across all UARTs on the same CPU int).
// interrupt.New is a compiler intrinsic and requires a plain (non-capturing) // Avoid sync.Once here because serial is initialized before a task exists.
// handler function, so we use a named package-level function. state := interrupt.Disable()
onceUart.Do(func() { if !uartInterruptConfigured {
_ = interrupt.New(cpuInterruptFromUART, handleUARTInterrupt).Enable() _ = interrupt.New(cpuInterruptFromUART, handleUARTInterrupt).Enable()
}) uartInterruptConfigured = true
}
interrupt.Restore(state)
} }
// handleUARTInterrupt is the shared UART interrupt handler. It must be a plain // handleUARTInterrupt is the shared UART interrupt handler. It must be a plain