aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/machine/machine_rp2.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/machine/machine_rp2.go')
-rw-r--r--src/machine/machine_rp2.go135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/machine/machine_rp2.go b/src/machine/machine_rp2.go
new file mode 100644
index 000000000..6c09fedfe
--- /dev/null
+++ b/src/machine/machine_rp2.go
@@ -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
+}