mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-14 07:53:40 +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,135 @@
|
||||
//go:build rp2040 || rp2350
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/rp"
|
||||
"runtime/interrupt"
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const deviceName = rp.Device
|
||||
|
||||
const (
|
||||
// Number of spin locks available
|
||||
// Note: On RP2350, most spinlocks are unusable due to Errata 2
|
||||
_NUMSPINLOCKS = 32
|
||||
_PICO_SPINLOCK_ID_IRQ = 9
|
||||
)
|
||||
|
||||
// UART on the RP2040
|
||||
var (
|
||||
UART0 = &_UART0
|
||||
_UART0 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: rp.UART0,
|
||||
}
|
||||
|
||||
UART1 = &_UART1
|
||||
_UART1 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: rp.UART1,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
UART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)
|
||||
UART1.Interrupt = interrupt.New(rp.IRQ_UART1_IRQ, _UART1.handleInterrupt)
|
||||
}
|
||||
|
||||
//go:linkname machineInit runtime.machineInit
|
||||
func machineInit() {
|
||||
// Reset all peripherals to put system into a known state,
|
||||
// except for QSPI pads and the XIP IO bank, as this is fatal if running from flash
|
||||
// and the PLLs, as this is fatal if clock muxing has not been reset on this boot
|
||||
// and USB, syscfg, as this disturbs USB-to-SWD on core 1
|
||||
bits := ^uint32(initDontReset)
|
||||
resetBlock(bits)
|
||||
|
||||
// Remove reset from peripherals which are clocked only by clkSys and
|
||||
// clkRef. Other peripherals stay in reset until we've configured clocks.
|
||||
bits = ^uint32(initUnreset)
|
||||
unresetBlockWait(bits)
|
||||
|
||||
clocks.init()
|
||||
|
||||
// Peripheral clocks should now all be running
|
||||
unresetBlockWait(RESETS_RESET_Msk)
|
||||
}
|
||||
|
||||
//go:linkname ticks runtime.machineTicks
|
||||
func ticks() uint64 {
|
||||
return timer.timeElapsed()
|
||||
}
|
||||
|
||||
//go:linkname lightSleep runtime.machineLightSleep
|
||||
func lightSleep(ticks uint64) {
|
||||
timer.lightSleep(ticks)
|
||||
}
|
||||
|
||||
// CurrentCore returns the core number the call was made from.
|
||||
func CurrentCore() int {
|
||||
return int(rp.SIO.CPUID.Get())
|
||||
}
|
||||
|
||||
// NumCores returns number of cores available on the device.
|
||||
func NumCores() int { return 2 }
|
||||
|
||||
// ChipVersion returns the version of the chip. 1 is returned for B0 and B1
|
||||
// chip.
|
||||
func ChipVersion() uint8 {
|
||||
const (
|
||||
SYSINFO_BASE = 0x40000000
|
||||
SYSINFO_CHIP_ID_OFFSET = 0x00000000
|
||||
SYSINFO_CHIP_ID_REVISION_BITS = 0xf0000000
|
||||
SYSINFO_CHIP_ID_REVISION_LSB = 28
|
||||
)
|
||||
|
||||
// First register of sysinfo is chip id
|
||||
chipID := *(*uint32)(unsafe.Pointer(uintptr(SYSINFO_BASE + SYSINFO_CHIP_ID_OFFSET)))
|
||||
// Version 1 == B0/B1
|
||||
version := (chipID & SYSINFO_CHIP_ID_REVISION_BITS) >> SYSINFO_CHIP_ID_REVISION_LSB
|
||||
return uint8(version)
|
||||
}
|
||||
|
||||
// Single DMA channel. See rp.DMA_Type.
|
||||
type dmaChannel struct {
|
||||
READ_ADDR volatile.Register32
|
||||
WRITE_ADDR volatile.Register32
|
||||
TRANS_COUNT volatile.Register32
|
||||
CTRL_TRIG volatile.Register32
|
||||
_ [12]volatile.Register32 // aliases
|
||||
}
|
||||
|
||||
// Static assignment of DMA channels to peripherals.
|
||||
// Allocating them statically is good enough for now. If lots of peripherals use
|
||||
// DMA, these might need to be assigned at runtime.
|
||||
const (
|
||||
spi0DMAChannel = iota
|
||||
spi1DMAChannel
|
||||
)
|
||||
|
||||
// DMA channels usable on the RP2040.
|
||||
var dmaChannels = (*[12 + 4*rp2350ExtraReg]dmaChannel)(unsafe.Pointer(rp.DMA))
|
||||
|
||||
//go:inline
|
||||
func boolToBit(a bool) uint32 {
|
||||
if a {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func u32max(a, b uint32) uint32 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func isReservedI2CAddr(addr uint8) bool {
|
||||
return (addr&0x78) == 0 || (addr&0x78) == 0x78
|
||||
}
|
||||
Reference in New Issue
Block a user