diff options
Diffstat (limited to 'src/machine/machine_rp2.go')
-rw-r--r-- | src/machine/machine_rp2.go | 135 |
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 +} |