diff --git a/src/runtime/runtime_rp2.go b/src/runtime/runtime_rp2.go index 1cd23d6dc..f6d31f980 100644 --- a/src/runtime/runtime_rp2.go +++ b/src/runtime/runtime_rp2.go @@ -8,7 +8,6 @@ import ( "internal/task" "machine" _ "machine/usb/cdc" - "runtime/interrupt" "runtime/volatile" "unsafe" ) @@ -140,14 +139,7 @@ func startSecondaryCores() { // Enable the FIFO interrupt for the GC stop the world phase. // We can only do this after we don't need the FIFO anymore for starting the // second core. - intr := interrupt.New(sioIrqFifoProc0, func(intr interrupt.Interrupt) { - switch rp.SIO.FIFO_RD.Get() { - case 1: - gcInterruptHandler(0) - } - }) - intr.Enable() - intr.SetPriority(0xff) + enableSIOFifoInterruptCore0() } var core1StartSequence = [...]uint32{ @@ -174,14 +166,7 @@ func runCore1() { // the GC. // Use the lowest possible priority (highest priority value), so that other // interrupts can still happen while the GC is running. - intr := interrupt.New(sioIrqFifoProc1, func(intr interrupt.Interrupt) { - switch rp.SIO.FIFO_RD.Get() { - case 1: - gcInterruptHandler(1) - } - }) - intr.Enable() - intr.SetPriority(0xff) + enableSIOFifoInterruptCore1() // Now start running the scheduler on this core. schedulerLock.Lock() diff --git a/src/runtime/runtime_rp2040.go b/src/runtime/runtime_rp2040.go index 2ca3605e0..56c7da102 100644 --- a/src/runtime/runtime_rp2040.go +++ b/src/runtime/runtime_rp2040.go @@ -4,9 +4,39 @@ package runtime import ( "device/rp" + "runtime/interrupt" ) const ( sioIrqFifoProc0 = rp.IRQ_SIO_IRQ_PROC0 sioIrqFifoProc1 = rp.IRQ_SIO_IRQ_PROC1 ) + +// On RP2040, each core has its own SIO FIFO IRQ. Core0 enables +// IRQ_SIO_IRQ_PROC0 and Core1 enables IRQ_SIO_IRQ_PROC1, so each handler can +// use a fixed core ID. +func enableSIOFifoInterruptCore0() { + intr := interrupt.New(sioIrqFifoProc0, handleSIOFifoInterruptCore0) + intr.Enable() + intr.SetPriority(0xff) +} + +func enableSIOFifoInterruptCore1() { + intr := interrupt.New(sioIrqFifoProc1, handleSIOFifoInterruptCore1) + intr.Enable() + intr.SetPriority(0xff) +} + +func handleSIOFifoInterruptCore0(intr interrupt.Interrupt) { + switch rp.SIO.FIFO_RD.Get() { + case 1: + gcInterruptHandler(0) + } +} + +func handleSIOFifoInterruptCore1(intr interrupt.Interrupt) { + switch rp.SIO.FIFO_RD.Get() { + case 1: + gcInterruptHandler(1) + } +} diff --git a/src/runtime/runtime_rp2350.go b/src/runtime/runtime_rp2350.go index 91af23212..02c00b61e 100644 --- a/src/runtime/runtime_rp2350.go +++ b/src/runtime/runtime_rp2350.go @@ -4,6 +4,7 @@ package runtime import ( "device/rp" + "runtime/interrupt" ) const ( @@ -14,3 +15,25 @@ const ( sioIrqFifoProc0 = rp.IRQ_SIO_IRQ_FIFO sioIrqFifoProc1 = rp.IRQ_SIO_IRQ_FIFO ) + +var sioFifoInterrupt = interrupt.New(sioIrqFifoProc0, handleSIOFifoInterrupt) + +// On RP2350 both cores share IRQ_SIO_IRQ_FIFO, but the NVIC enable and +// priority state is per-core. Each core must enable the shared IRQ on +// its own NVIC, so both Core0 and Core1 call Enable()/SetPriority(). +func enableSIOFifoInterruptCore0() { + sioFifoInterrupt.Enable() + sioFifoInterrupt.SetPriority(0xff) +} + +func enableSIOFifoInterruptCore1() { + sioFifoInterrupt.Enable() + sioFifoInterrupt.SetPriority(0xff) +} + +func handleSIOFifoInterrupt(intr interrupt.Interrupt) { + switch rp.SIO.FIFO_RD.Get() { + case 1: + gcInterruptHandler(currentCPU()) + } +}