mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-11 14:33:41 +00:00
Add RP2350 support (#4459)
machine/rp2350: add support * add linker scripts for rp2350 * add bootloader * begin melding rp2040 and rp2350 APIs * add UART * add rp2350 boot patching * Fix RP2350 memory layout (#4626) * Remove rp2040-style second stage bootloader. * Add 'minimum viable' IMAGE_DEF embedded block * Create a pico2 specific target * Implement rp2350 init, clock, and uart support * Merge rp2 reset code back together * Separate chip-specific clock definitions * Clear pad isolation bit on rp2350 * Init UART in rp2350 runtime * Correct usb/serial initialization order * Implement jump-to-bootloader * test: add pico2 to smoketests --------- Signed-off-by: deadprogram <ron@hybridgroup.com> Co-authored-by: Matthew Mets <matt.mets@cibomahto.com> Co-authored-by: Matt Mets <matt@blinkinlabs.com> Co-authored-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
committed by
GitHub
parent
0d13e61d0c
commit
37f35f8c91
@@ -0,0 +1,103 @@
|
||||
//go:build rp2040 || rp2350
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"runtime/interrupt"
|
||||
"runtime/volatile"
|
||||
)
|
||||
|
||||
const numTimers = 4
|
||||
|
||||
// Alarm0 is reserved for sleeping by tinygo runtime code for RP2040.
|
||||
// Alarm0 is also IRQ0
|
||||
const sleepAlarm = 0
|
||||
const sleepAlarmIRQ = 0
|
||||
|
||||
// The minimum sleep duration in μs (ticks)
|
||||
const minSleep = 10
|
||||
|
||||
type timerType struct {
|
||||
timeHW volatile.Register32
|
||||
timeLW volatile.Register32
|
||||
timeHR volatile.Register32
|
||||
timeLR volatile.Register32
|
||||
alarm [numTimers]volatile.Register32
|
||||
armed volatile.Register32
|
||||
timeRawH volatile.Register32
|
||||
timeRawL volatile.Register32
|
||||
dbgPause volatile.Register32
|
||||
pause volatile.Register32
|
||||
locked [rp2350ExtraReg]volatile.Register32
|
||||
source [rp2350ExtraReg]volatile.Register32
|
||||
intR volatile.Register32
|
||||
intE volatile.Register32
|
||||
intF volatile.Register32
|
||||
intS volatile.Register32
|
||||
}
|
||||
|
||||
// TimeElapsed returns time elapsed since power up, in microseconds.
|
||||
func (tmr *timerType) timeElapsed() (us uint64) {
|
||||
// Need to make sure that the upper 32 bits of the timer
|
||||
// don't change, so read that first
|
||||
hi := tmr.timeRawH.Get()
|
||||
var lo, nextHi uint32
|
||||
for {
|
||||
// Read the lower 32 bits
|
||||
lo = tmr.timeRawL.Get()
|
||||
// Now read the upper 32 bits again and
|
||||
// check that it hasn't incremented. If it has, loop around
|
||||
// and read the lower 32 bits again to get an accurate value
|
||||
nextHi = tmr.timeRawH.Get()
|
||||
if hi == nextHi {
|
||||
break
|
||||
}
|
||||
hi = nextHi
|
||||
}
|
||||
return uint64(hi)<<32 | uint64(lo)
|
||||
}
|
||||
|
||||
// lightSleep will put the processor into a sleep state a short period
|
||||
// (up to approx 72mins per RP2040 datasheet, 4.6.3. Alarms).
|
||||
//
|
||||
// This function is a 'light' sleep and will return early if another
|
||||
// interrupt or event triggers. This is intentional since the
|
||||
// primary use-case is for use by the TinyGo scheduler which will
|
||||
// re-sleep if needed.
|
||||
func (tmr *timerType) lightSleep(us uint64) {
|
||||
// minSleep is a way to avoid race conditions for short
|
||||
// sleeps by ensuring there is enough time to setup the
|
||||
// alarm before sleeping. For very short sleeps, this
|
||||
// effectively becomes a 'busy loop'.
|
||||
if us < minSleep {
|
||||
return
|
||||
}
|
||||
|
||||
// Interrupt handler is essentially a no-op, we're just relying
|
||||
// on the side-effect of waking the CPU from "wfe"
|
||||
intr := interrupt.New(sleepAlarmIRQ, func(interrupt.Interrupt) {
|
||||
// Clear the IRQ
|
||||
timer.intR.Set(1 << sleepAlarm)
|
||||
})
|
||||
|
||||
// Reset interrupt flag
|
||||
tmr.intR.Set(1 << sleepAlarm)
|
||||
|
||||
// Enable interrupt
|
||||
tmr.intE.SetBits(1 << sleepAlarm)
|
||||
intr.Enable()
|
||||
|
||||
// Only the low 32 bits of time can be used for alarms
|
||||
target := uint64(tmr.timeRawL.Get()) + us
|
||||
tmr.alarm[sleepAlarm].Set(uint32(target))
|
||||
|
||||
// Wait for sleep (or any other) interrupt
|
||||
arm.Asm("wfe")
|
||||
|
||||
// Disarm timer
|
||||
tmr.armed.Set(1 << sleepAlarm)
|
||||
|
||||
// Disable interrupt
|
||||
intr.Disable()
|
||||
}
|
||||
Reference in New Issue
Block a user