From 9dea3c158c584d94e9cb7008aea4eee021b47e31 Mon Sep 17 00:00:00 2001 From: rdon Date: Sun, 10 May 2026 02:22:55 +0900 Subject: [PATCH 1/7] runtime, machine: add RP2040 flash-safe section --- src/machine/machine_rp2040_flashsafe.go | 14 +++ src/machine/machine_rp2040_rom.go | 14 +-- src/runtime/runtime_rp2.go | 4 + src/runtime/runtime_rp2040_flashsafe_cores.go | 93 +++++++++++++++++++ .../runtime_rp2040_flashsafe_single.go | 17 ++++ src/runtime/runtime_rp2350_flashsafe_stub.go | 7 ++ 6 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 src/machine/machine_rp2040_flashsafe.go create mode 100644 src/runtime/runtime_rp2040_flashsafe_cores.go create mode 100644 src/runtime/runtime_rp2040_flashsafe_single.go create mode 100644 src/runtime/runtime_rp2350_flashsafe_stub.go diff --git a/src/machine/machine_rp2040_flashsafe.go b/src/machine/machine_rp2040_flashsafe.go new file mode 100644 index 0000000000..c9e7ca6ab2 --- /dev/null +++ b/src/machine/machine_rp2040_flashsafe.go @@ -0,0 +1,14 @@ +//go:build tinygo && rp2040 + +package machine + +import ( + "runtime/interrupt" + _ "unsafe" +) + +//go:linkname rp2040EnterFlashSafeSection runtime.rp2040EnterFlashSafeSection +func rp2040EnterFlashSafeSection() interrupt.State + +//go:linkname rp2040ExitFlashSafeSection runtime.rp2040ExitFlashSafeSection +func rp2040ExitFlashSafeSection(state interrupt.State) diff --git a/src/machine/machine_rp2040_rom.go b/src/machine/machine_rp2040_rom.go index 0f7c6819a5..973792bfd5 100644 --- a/src/machine/machine_rp2040_rom.go +++ b/src/machine/machine_rp2040_rom.go @@ -3,7 +3,6 @@ package machine import ( - "runtime/interrupt" "unsafe" ) @@ -207,6 +206,9 @@ func doFlashCommand(tx []byte, rx []byte) error { return errFlashInvalidWriteLength } + state := rp2040EnterFlashSafeSection() + defer rp2040ExitFlashSafeSection(state) + C.flash_do_cmd( (*C.uint8_t)(unsafe.Pointer(&tx[0])), (*C.uint8_t)(unsafe.Pointer(&rx[0])), @@ -223,15 +225,15 @@ func (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) { return 0, errFlashCannotWritePastEOF } - state := interrupt.Disable() - defer interrupt.Restore(state) - // rp2040 writes to offset, not actual address // e.g. real address 0x10003000 is written to at // 0x00003000 address := writeAddress(off) padded := flashPad(p, int(f.WriteBlockSize())) + state := rp2040EnterFlashSafeSection() + defer rp2040ExitFlashSafeSection(state) + C.flash_range_write(C.uint32_t(address), (*C.uint8_t)(unsafe.Pointer(&padded[0])), C.ulong(len(padded))) @@ -245,8 +247,8 @@ func (f flashBlockDevice) eraseBlocks(start, length int64) error { return errFlashCannotErasePastEOF } - state := interrupt.Disable() - defer interrupt.Restore(state) + state := rp2040EnterFlashSafeSection() + defer rp2040ExitFlashSafeSection(state) C.flash_erase_blocks(C.uint32_t(address), C.ulong(length*f.EraseBlockSize())) diff --git a/src/runtime/runtime_rp2.go b/src/runtime/runtime_rp2.go index 1cd23d6dcb..6941c72cd2 100644 --- a/src/runtime/runtime_rp2.go +++ b/src/runtime/runtime_rp2.go @@ -144,6 +144,8 @@ func startSecondaryCores() { switch rp.SIO.FIFO_RD.Get() { case 1: gcInterruptHandler(0) + case 2: + rp2FlashSafeInterruptHandler(0) } }) intr.Enable() @@ -178,6 +180,8 @@ func runCore1() { switch rp.SIO.FIFO_RD.Get() { case 1: gcInterruptHandler(1) + case 2: + rp2FlashSafeInterruptHandler(1) } }) intr.Enable() diff --git a/src/runtime/runtime_rp2040_flashsafe_cores.go b/src/runtime/runtime_rp2040_flashsafe_cores.go new file mode 100644 index 0000000000..7cd001ce8b --- /dev/null +++ b/src/runtime/runtime_rp2040_flashsafe_cores.go @@ -0,0 +1,93 @@ +//go:build rp2040 && scheduler.cores + +package runtime + +import ( + "device/arm" + "device/rp" + "runtime/interrupt" + "runtime/volatile" +) + +const ( + rp2040FlashSafeFIFOCommand = 2 + + rp2040FlashSafeIdle = 0 + rp2040FlashSafeLocked = 1 + rp2040FlashSafeRelease = 2 +) + +// rp2040FlashSafeState is used to synchronize the core that performs a flash +// operation with the other core that must stop executing from XIP flash. +var rp2040FlashSafeState volatile.Register8 + +// rp2040EnterFlashSafeSection enters a section in which RP2040 flash operations +// may temporarily disable XIP. +// +// The multicore path asks the other core to enter the flash-safe interrupt +// handler and waits until it acknowledges that it is parked. Local interrupts +// are disabled after the other core is parked. +func rp2040EnterFlashSafeSection() interrupt.State { + if !secondaryCoresStarted { + return interrupt.Disable() + } + + core := currentCPU() + rp2040FlashSafeState.Set(rp2040FlashSafeIdle) + + for i := uint32(0); i < numCPU; i++ { + if i == core { + continue + } + rp2040FlashSafePauseCore(i) + } + + for rp2040FlashSafeState.Get() != rp2040FlashSafeLocked { + spinLoopWait() + } + + return interrupt.Disable() +} + +// rp2040ExitFlashSafeSection exits a section entered by +// rp2040EnterFlashSafeSection. +func rp2040ExitFlashSafeSection(state interrupt.State) { + if secondaryCoresStarted { + rp2040FlashSafeState.Set(rp2040FlashSafeRelease) + arm.Asm("sev") + + for rp2040FlashSafeState.Get() != rp2040FlashSafeIdle { + spinLoopWait() + } + } + + interrupt.Restore(state) +} + +func rp2040FlashSafePauseCore(core uint32) { + _ = core // RP2040 SIO FIFO writes to the other core. + rp.SIO.FIFO_WR.Set(rp2040FlashSafeFIFOCommand) + arm.Asm("sev") +} + +// rp2FlashSafeInterruptHandler is called from the SIO FIFO interrupt handler. +// +// NOTE: this first draft keeps the lockout handler in Go. The final version +// should ensure that the wait loop runs from RAM while XIP is disabled. +func rp2FlashSafeInterruptHandler(core uint32) { + _ = core + + state := interrupt.Disable() + + rp2040FlashSafeState.Set(rp2040FlashSafeLocked) + arm.Asm("sev") + + for rp2040FlashSafeState.Get() == rp2040FlashSafeLocked { + arm.Asm("wfe") + } + + interrupt.Restore(state) + + rp2040FlashSafeState.Set(rp2040FlashSafeIdle) + arm.Asm("sev") +} diff --git a/src/runtime/runtime_rp2040_flashsafe_single.go b/src/runtime/runtime_rp2040_flashsafe_single.go new file mode 100644 index 0000000000..b68adbfee9 --- /dev/null +++ b/src/runtime/runtime_rp2040_flashsafe_single.go @@ -0,0 +1,17 @@ +//go:build rp2040 && !scheduler.cores + +package runtime + +import "runtime/interrupt" + +func rp2040EnterFlashSafeSection() interrupt.State { + return interrupt.Disable() +} + +func rp2040ExitFlashSafeSection(state interrupt.State) { + interrupt.Restore(state) +} + +func rp2FlashSafeInterruptHandler(core uint32) { + _ = core +} diff --git a/src/runtime/runtime_rp2350_flashsafe_stub.go b/src/runtime/runtime_rp2350_flashsafe_stub.go new file mode 100644 index 0000000000..211b920cc5 --- /dev/null +++ b/src/runtime/runtime_rp2350_flashsafe_stub.go @@ -0,0 +1,7 @@ +//go:build rp2350 + +package runtime + +func rp2FlashSafeInterruptHandler(core uint32) { + _ = core +} From facb947a65921dc2124468ee6a3c0fe45d9de5fc Mon Sep 17 00:00:00 2001 From: rdon Date: Wed, 20 May 2026 16:10:27 +0900 Subject: [PATCH 2/7] runtime: harden flash-safe section for multicore --- src/machine/machine_rp2040_flashsafe.go | 6 + src/runtime/runtime_rp2040_flashsafe_cores.go | 112 ++++++++++-------- 2 files changed, 71 insertions(+), 47 deletions(-) diff --git a/src/machine/machine_rp2040_flashsafe.go b/src/machine/machine_rp2040_flashsafe.go index c9e7ca6ab2..d071dca1c1 100644 --- a/src/machine/machine_rp2040_flashsafe.go +++ b/src/machine/machine_rp2040_flashsafe.go @@ -1,5 +1,11 @@ //go:build tinygo && rp2040 +// "Flash safe" follows the RP2040/Pico SDK terminology: flash operations +// must run while the other core is not executing from XIP flash. +// +// Use linkname to call runtime hooks from package machine without creating +// an import cycle. + package machine import ( diff --git a/src/runtime/runtime_rp2040_flashsafe_cores.go b/src/runtime/runtime_rp2040_flashsafe_cores.go index 7cd001ce8b..c75daeea34 100644 --- a/src/runtime/runtime_rp2040_flashsafe_cores.go +++ b/src/runtime/runtime_rp2040_flashsafe_cores.go @@ -3,24 +3,33 @@ package runtime import ( - "device/arm" - "device/rp" - "runtime/interrupt" - "runtime/volatile" + "device/arm" + "device/rp" + "runtime/interrupt" + "runtime/volatile" + _ "unsafe" // required for //go:section ) const ( - rp2040FlashSafeFIFOCommand = 2 + rp2040FlashSafeFIFOCommand = 2 - rp2040FlashSafeIdle = 0 - rp2040FlashSafeLocked = 1 - rp2040FlashSafeRelease = 2 + rp2040FlashSafeIdle = 0 + rp2040FlashSafeLocked = 1 + rp2040FlashSafeRelease = 2 ) // rp2040FlashSafeState is used to synchronize the core that performs a flash // operation with the other core that must stop executing from XIP flash. var rp2040FlashSafeState volatile.Register8 +// flashSafeLock serializes Enter/Exit so that only one core at a time +// owns the flash-safe state machine. The other core can still participate +// as a victim through the FIFO interrupt while spinning on this lock. +// +// id: 24 is reserved here. ids 20-23 are already used by printLock, +// schedulerLock, atomicsLock, futexLock (see runtime_rp2.go). +var flashSafeLock = spinLock{id: 24} + // rp2040EnterFlashSafeSection enters a section in which RP2040 flash operations // may temporarily disable XIP. // @@ -28,66 +37,75 @@ var rp2040FlashSafeState volatile.Register8 // handler and waits until it acknowledges that it is parked. Local interrupts // are disabled after the other core is parked. func rp2040EnterFlashSafeSection() interrupt.State { - if !secondaryCoresStarted { - return interrupt.Disable() - } + if !secondaryCoresStarted { + return interrupt.Disable() + } + + flashSafeLock.Lock() - core := currentCPU() - rp2040FlashSafeState.Set(rp2040FlashSafeIdle) + core := currentCPU() + rp2040FlashSafeState.Set(rp2040FlashSafeIdle) - for i := uint32(0); i < numCPU; i++ { - if i == core { - continue - } - rp2040FlashSafePauseCore(i) - } + for i := uint32(0); i < numCPU; i++ { + if i == core { + continue + } + rp2040FlashSafePauseCore(i) + } - for rp2040FlashSafeState.Get() != rp2040FlashSafeLocked { - spinLoopWait() - } + for rp2040FlashSafeState.Get() != rp2040FlashSafeLocked { + spinLoopWait() + } - return interrupt.Disable() + return interrupt.Disable() } // rp2040ExitFlashSafeSection exits a section entered by // rp2040EnterFlashSafeSection. func rp2040ExitFlashSafeSection(state interrupt.State) { - if secondaryCoresStarted { - rp2040FlashSafeState.Set(rp2040FlashSafeRelease) - arm.Asm("sev") + if secondaryCoresStarted { + rp2040FlashSafeState.Set(rp2040FlashSafeRelease) + arm.Asm("sev") - for rp2040FlashSafeState.Get() != rp2040FlashSafeIdle { - spinLoopWait() - } - } + for rp2040FlashSafeState.Get() != rp2040FlashSafeIdle { + spinLoopWait() + } - interrupt.Restore(state) + flashSafeLock.Unlock() + } + + interrupt.Restore(state) } func rp2040FlashSafePauseCore(core uint32) { - _ = core // RP2040 SIO FIFO writes to the other core. - rp.SIO.FIFO_WR.Set(rp2040FlashSafeFIFOCommand) - arm.Asm("sev") + _ = core // RP2040 SIO FIFO writes to the other core. + rp.SIO.FIFO_WR.Set(rp2040FlashSafeFIFOCommand) + arm.Asm("sev") } -// rp2FlashSafeInterruptHandler is called from the SIO FIFO interrupt handler. +// rp2FlashSafeInterruptHandler runs on the other core while this core is +// performing a flash operation that temporarily disables XIP. +// +// This function MUST be placed in RAM (.ramfuncs section). During the +// flash operation the QSPI flash is in non-XIP mode and instruction +// fetches from the 0x10000000 region will fail. The wait loop below +// runs entirely from RAM so that the parked core can keep executing. // -// NOTE: this first draft keeps the lockout handler in Go. The final version -// should ensure that the wait loop runs from RAM while XIP is disabled. +//go:section .ramfuncs func rp2FlashSafeInterruptHandler(core uint32) { - _ = core + _ = core - state := interrupt.Disable() + state := interrupt.Disable() - rp2040FlashSafeState.Set(rp2040FlashSafeLocked) - arm.Asm("sev") + rp2040FlashSafeState.Set(rp2040FlashSafeLocked) + arm.Asm("sev") - for rp2040FlashSafeState.Get() == rp2040FlashSafeLocked { - arm.Asm("wfe") - } + for rp2040FlashSafeState.Get() == rp2040FlashSafeLocked { + arm.Asm("wfe") + } - interrupt.Restore(state) + interrupt.Restore(state) - rp2040FlashSafeState.Set(rp2040FlashSafeIdle) - arm.Asm("sev") + rp2040FlashSafeState.Set(rp2040FlashSafeIdle) + arm.Asm("sev") } From 332d742cc7596f57d87632e2e0304596ba651227 Mon Sep 17 00:00:00 2001 From: rdon Date: Wed, 20 May 2026 17:51:52 +0900 Subject: [PATCH 3/7] machine: copy RP2040 flash write buffer to RAM --- src/machine/machine_rp2040_rom.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_rp2040_rom.go b/src/machine/machine_rp2040_rom.go index 973792bfd5..0b3d056e5b 100644 --- a/src/machine/machine_rp2040_rom.go +++ b/src/machine/machine_rp2040_rom.go @@ -230,15 +230,17 @@ func (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) { // 0x00003000 address := writeAddress(off) padded := flashPad(p, int(f.WriteBlockSize())) + buf := make([]byte, len(padded)) + copy(buf, padded) state := rp2040EnterFlashSafeSection() defer rp2040ExitFlashSafeSection(state) C.flash_range_write(C.uint32_t(address), - (*C.uint8_t)(unsafe.Pointer(&padded[0])), - C.ulong(len(padded))) + (*C.uint8_t)(unsafe.Pointer(&buf[0])), + C.ulong(len(buf))) - return len(padded), nil + return len(buf), nil } func (f flashBlockDevice) eraseBlocks(start, length int64) error { From 505b79c320ce3509094fe53ec403dca287c99fde Mon Sep 17 00:00:00 2001 From: rdon Date: Wed, 20 May 2026 17:57:17 +0900 Subject: [PATCH 4/7] gofmt files --- src/runtime/runtime_rp2040_flashsafe_cores.go | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/runtime/runtime_rp2040_flashsafe_cores.go b/src/runtime/runtime_rp2040_flashsafe_cores.go index c75daeea34..ac2df6796a 100644 --- a/src/runtime/runtime_rp2040_flashsafe_cores.go +++ b/src/runtime/runtime_rp2040_flashsafe_cores.go @@ -3,19 +3,19 @@ package runtime import ( - "device/arm" - "device/rp" - "runtime/interrupt" - "runtime/volatile" - _ "unsafe" // required for //go:section + "device/arm" + "device/rp" + "runtime/interrupt" + "runtime/volatile" + _ "unsafe" // required for //go:section ) const ( - rp2040FlashSafeFIFOCommand = 2 + rp2040FlashSafeFIFOCommand = 2 - rp2040FlashSafeIdle = 0 - rp2040FlashSafeLocked = 1 - rp2040FlashSafeRelease = 2 + rp2040FlashSafeIdle = 0 + rp2040FlashSafeLocked = 1 + rp2040FlashSafeRelease = 2 ) // rp2040FlashSafeState is used to synchronize the core that performs a flash @@ -37,50 +37,50 @@ var flashSafeLock = spinLock{id: 24} // handler and waits until it acknowledges that it is parked. Local interrupts // are disabled after the other core is parked. func rp2040EnterFlashSafeSection() interrupt.State { - if !secondaryCoresStarted { - return interrupt.Disable() - } + if !secondaryCoresStarted { + return interrupt.Disable() + } - flashSafeLock.Lock() + flashSafeLock.Lock() - core := currentCPU() - rp2040FlashSafeState.Set(rp2040FlashSafeIdle) + core := currentCPU() + rp2040FlashSafeState.Set(rp2040FlashSafeIdle) - for i := uint32(0); i < numCPU; i++ { - if i == core { - continue - } - rp2040FlashSafePauseCore(i) - } + for i := uint32(0); i < numCPU; i++ { + if i == core { + continue + } + rp2040FlashSafePauseCore(i) + } - for rp2040FlashSafeState.Get() != rp2040FlashSafeLocked { - spinLoopWait() - } + for rp2040FlashSafeState.Get() != rp2040FlashSafeLocked { + spinLoopWait() + } - return interrupt.Disable() + return interrupt.Disable() } // rp2040ExitFlashSafeSection exits a section entered by // rp2040EnterFlashSafeSection. func rp2040ExitFlashSafeSection(state interrupt.State) { - if secondaryCoresStarted { - rp2040FlashSafeState.Set(rp2040FlashSafeRelease) - arm.Asm("sev") + if secondaryCoresStarted { + rp2040FlashSafeState.Set(rp2040FlashSafeRelease) + arm.Asm("sev") - for rp2040FlashSafeState.Get() != rp2040FlashSafeIdle { - spinLoopWait() - } + for rp2040FlashSafeState.Get() != rp2040FlashSafeIdle { + spinLoopWait() + } - flashSafeLock.Unlock() - } + flashSafeLock.Unlock() + } - interrupt.Restore(state) + interrupt.Restore(state) } func rp2040FlashSafePauseCore(core uint32) { - _ = core // RP2040 SIO FIFO writes to the other core. - rp.SIO.FIFO_WR.Set(rp2040FlashSafeFIFOCommand) - arm.Asm("sev") + _ = core // RP2040 SIO FIFO writes to the other core. + rp.SIO.FIFO_WR.Set(rp2040FlashSafeFIFOCommand) + arm.Asm("sev") } // rp2FlashSafeInterruptHandler runs on the other core while this core is @@ -93,19 +93,19 @@ func rp2040FlashSafePauseCore(core uint32) { // //go:section .ramfuncs func rp2FlashSafeInterruptHandler(core uint32) { - _ = core + _ = core - state := interrupt.Disable() + state := interrupt.Disable() - rp2040FlashSafeState.Set(rp2040FlashSafeLocked) - arm.Asm("sev") + rp2040FlashSafeState.Set(rp2040FlashSafeLocked) + arm.Asm("sev") - for rp2040FlashSafeState.Get() == rp2040FlashSafeLocked { - arm.Asm("wfe") - } + for rp2040FlashSafeState.Get() == rp2040FlashSafeLocked { + arm.Asm("wfe") + } - interrupt.Restore(state) + interrupt.Restore(state) - rp2040FlashSafeState.Set(rp2040FlashSafeIdle) - arm.Asm("sev") + rp2040FlashSafeState.Set(rp2040FlashSafeIdle) + arm.Asm("sev") } From 393a2b4dfdc1b12c614d42e8b99d8f24ca56a8d7 Mon Sep 17 00:00:00 2001 From: rdon Date: Wed, 20 May 2026 18:13:43 +0900 Subject: [PATCH 5/7] copy doFlashCommand tx buffer to RAM --- src/machine/machine_rp2040_rom.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/machine/machine_rp2040_rom.go b/src/machine/machine_rp2040_rom.go index 0b3d056e5b..f66b8cfd51 100644 --- a/src/machine/machine_rp2040_rom.go +++ b/src/machine/machine_rp2040_rom.go @@ -205,14 +205,20 @@ func doFlashCommand(tx []byte, rx []byte) error { if len(tx) != len(rx) { return errFlashInvalidWriteLength } + if len(tx) == 0 { + return nil + } + + txbuf := make([]byte, len(tx)) + copy(txbuf, tx) state := rp2040EnterFlashSafeSection() defer rp2040ExitFlashSafeSection(state) C.flash_do_cmd( - (*C.uint8_t)(unsafe.Pointer(&tx[0])), + (*C.uint8_t)(unsafe.Pointer(&txbuf[0])), (*C.uint8_t)(unsafe.Pointer(&rx[0])), - C.ulong(len(tx))) + C.ulong(len(txbuf))) return nil } From f00930471a602b72141d7cc47ea040a551edcec4 Mon Sep 17 00:00:00 2001 From: rdon Date: Wed, 20 May 2026 18:18:55 +0900 Subject: [PATCH 6/7] handle empty flash buffers --- src/machine/machine_rp2040_rom.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/machine/machine_rp2040_rom.go b/src/machine/machine_rp2040_rom.go index f66b8cfd51..5601ec975c 100644 --- a/src/machine/machine_rp2040_rom.go +++ b/src/machine/machine_rp2040_rom.go @@ -238,6 +238,9 @@ func (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) { padded := flashPad(p, int(f.WriteBlockSize())) buf := make([]byte, len(padded)) copy(buf, padded) + if len(buf) == 0 { + return 0, nil + } state := rp2040EnterFlashSafeSection() defer rp2040ExitFlashSafeSection(state) From 59911c7edd55ea90f7ef0ad28ab1a05f5458f045 Mon Sep 17 00:00:00 2001 From: rdon Date: Wed, 20 May 2026 19:14:13 +0900 Subject: [PATCH 7/7] name RP2 FIFO and flash-safe states --- src/runtime/runtime_rp2.go | 15 ++++++++++----- src/runtime/runtime_rp2040_flashsafe_cores.go | 10 ++++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/runtime/runtime_rp2.go b/src/runtime/runtime_rp2.go index 6941c72cd2..e7f0d7e47e 100644 --- a/src/runtime/runtime_rp2.go +++ b/src/runtime/runtime_rp2.go @@ -13,6 +13,11 @@ import ( "unsafe" ) +const ( + rp2SIOFIFOCommandGC uint32 = iota + 1 + rp2SIOFIFOCommandFlashSafe +) + const numCPU = 2 const numSpinlocks = 32 @@ -142,9 +147,9 @@ func startSecondaryCores() { // second core. intr := interrupt.New(sioIrqFifoProc0, func(intr interrupt.Interrupt) { switch rp.SIO.FIFO_RD.Get() { - case 1: + case rp2SIOFIFOCommandGC: gcInterruptHandler(0) - case 2: + case rp2SIOFIFOCommandFlashSafe: rp2FlashSafeInterruptHandler(0) } }) @@ -178,9 +183,9 @@ func runCore1() { // 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: + case rp2SIOFIFOCommandGC: gcInterruptHandler(1) - case 2: + case rp2SIOFIFOCommandFlashSafe: rp2FlashSafeInterruptHandler(1) } }) @@ -269,7 +274,7 @@ func gcInterruptHandler(hartID uint32) { // Pause the given core by sending it an interrupt. func gcPauseCore(core uint32) { - rp.SIO.FIFO_WR.Set(1) + rp.SIO.FIFO_WR.Set(rp2SIOFIFOCommandGC) } // Signal the given core that it can resume one step. diff --git a/src/runtime/runtime_rp2040_flashsafe_cores.go b/src/runtime/runtime_rp2040_flashsafe_cores.go index ac2df6796a..e58115e1c6 100644 --- a/src/runtime/runtime_rp2040_flashsafe_cores.go +++ b/src/runtime/runtime_rp2040_flashsafe_cores.go @@ -11,11 +11,9 @@ import ( ) const ( - rp2040FlashSafeFIFOCommand = 2 - - rp2040FlashSafeIdle = 0 - rp2040FlashSafeLocked = 1 - rp2040FlashSafeRelease = 2 + rp2040FlashSafeIdle uint8 = iota + rp2040FlashSafeLocked + rp2040FlashSafeRelease ) // rp2040FlashSafeState is used to synchronize the core that performs a flash @@ -79,7 +77,7 @@ func rp2040ExitFlashSafeSection(state interrupt.State) { func rp2040FlashSafePauseCore(core uint32) { _ = core // RP2040 SIO FIFO writes to the other core. - rp.SIO.FIFO_WR.Set(rp2040FlashSafeFIFOCommand) + rp.SIO.FIFO_WR.Set(rp2SIOFIFOCommandFlashSafe) arm.Asm("sev") }