Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RP2350 support #4459

Merged
merged 27 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
09dcba6
add linker scripts for rp2350
soypat Sep 8, 2024
7502c09
add bootloader
soypat Sep 8, 2024
5934993
add placeholder runtime and machine stubs
soypat Sep 8, 2024
0b8e564
ok, example/blinky1 now compiles...
soypat Sep 8, 2024
87f32ac
begin melding rp2040 and rp2350 APIs
soypat Sep 11, 2024
dabefa4
compiles for rp2350, serial=none
soypat Sep 13, 2024
1ef9859
add UART
soypat Sep 13, 2024
1b9b9c9
add assembly and link; compile error remaining
soypat Sep 13, 2024
c59f472
fix assembly extension, causing C preprocessor to not execute
soypat Sep 14, 2024
161cfaf
begin adding UART initialization
soypat Sep 14, 2024
9245457
extract pin_init into its own macro
soypat Sep 14, 2024
7875cb4
remove binaries
soypat Sep 14, 2024
e34b252
exclude .elf and .uf2 binaries in gitignore
soypat Sep 14, 2024
d8db26e
work on adding IMAGE_DEF patching
soypat Sep 15, 2024
54745c0
add rp2350 boot patching
soypat Sep 22, 2024
65a9c06
Fix RP2350 memory layout (#4626)
cibomahto Nov 25, 2024
ae722c3
gen-device-svd: enclose assembly description with multi-line comment;…
soypat Dec 7, 2024
abd37fc
revert use of tinyboot
soypat Dec 7, 2024
f6e1d35
fix last commit slipup
soypat Dec 7, 2024
d55b7f0
Implement rp2350 init, clock, and uart support
cibomahto Dec 12, 2024
f6f5938
Working USB, but separated
cibomahto Dec 12, 2024
f926eeb
Use uart console for rp2350 since USB console crashes with fmt
cibomahto Dec 12, 2024
3cdcfc0
Fix linting issues
cibomahto Dec 13, 2024
c30dcb4
Correct usb/serial initialization order
cibomahto Dec 13, 2024
d3d3c2d
Implement jump-to-bootloader
cibomahto Dec 16, 2024
ba1919f
Fix linting
cibomahto Dec 16, 2024
677ba11
test: add pico2 to smoketests
deadprogram Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ test.exe
test.gba
test.hex
test.nro
test.uf2
test.wasm
wasm.wasm

*.uf2
*.elf
32 changes: 31 additions & 1 deletion builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,12 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
return fmt.Errorf("could not modify stack sizes: %w", err)
}
}

// Apply patches of bootloader in the order they appear.
if len(config.Target.BootPatches) > 0 {
err = applyPatches(result.Executable, config.Target.BootPatches)
}

if config.RP2040BootPatch() {
// Patch the second stage bootloader CRC into the .boot2 section
err = patchRP2040BootCRC(result.Executable)
Expand Down Expand Up @@ -1434,6 +1440,23 @@ func printStacks(calculatedStacks []string, stackSizes map[string]functionStackS
}
}

func applyPatches(executable string, bootPatches []string) (err error) {
for _, patch := range bootPatches {
switch patch {
case "rp2040":
err = patchRP2040BootCRC(executable)
// case "rp2350":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be commented out here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No patch required for rp2350 from my understanding

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we should remove this, no?

// err = patchRP2350BootIMAGE_DEF(executable)
default:
err = errors.New("undefined boot patch name")
}
if err != nil {
return fmt.Errorf("apply boot patch %q: %w", patch, err)
}
}
return nil
}

// RP2040 second stage bootloader CRC32 calculation
//
// Spec: https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf
Expand All @@ -1445,7 +1468,7 @@ func patchRP2040BootCRC(executable string) error {
}

if len(bytes) != 256 {
return fmt.Errorf("rp2040 .boot2 section must be exactly 256 bytes")
return fmt.Errorf("rp2040 .boot2 section must be exactly 256 bytes, got %d", len(bytes))
}

// From the 'official' RP2040 checksum script:
Expand Down Expand Up @@ -1484,3 +1507,10 @@ func lock(path string) func() {

return func() { flock.Close() }
}

func b2u8(b bool) uint8 {
if b {
return 1
}
return 0
}
1 change: 1 addition & 0 deletions compileopts/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type TargetSpec struct {
LinkerScript string `json:"linkerscript,omitempty"`
ExtraFiles []string `json:"extra-files,omitempty"`
RP2040BootPatch *bool `json:"rp2040-boot-patch,omitempty"` // Patch RP2040 2nd stage bootloader checksum
BootPatches []string `json:"boot-patches,omitempty"` // Bootloader patches to be applied in the order they appear.
Emulator string `json:"emulator,omitempty"`
FlashCommand string `json:"flash-command,omitempty"`
GDB []string `json:"gdb,omitempty"`
Expand Down
88 changes: 88 additions & 0 deletions src/machine/board_pico2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//go:build pico2

package machine

// GPIO pins
const (
GP0 Pin = GPIO0
GP1 Pin = GPIO1
GP2 Pin = GPIO2
GP3 Pin = GPIO3
GP4 Pin = GPIO4
GP5 Pin = GPIO5
GP6 Pin = GPIO6
GP7 Pin = GPIO7
GP8 Pin = GPIO8
GP9 Pin = GPIO9
GP10 Pin = GPIO10
GP11 Pin = GPIO11
GP12 Pin = GPIO12
GP13 Pin = GPIO13
GP14 Pin = GPIO14
GP15 Pin = GPIO15
GP16 Pin = GPIO16
GP17 Pin = GPIO17
GP18 Pin = GPIO18
GP19 Pin = GPIO19
GP20 Pin = GPIO20
GP21 Pin = GPIO21
GP22 Pin = GPIO22
GP26 Pin = GPIO26
GP27 Pin = GPIO27
GP28 Pin = GPIO28

// Onboard LED
LED Pin = GPIO25

// Onboard crystal oscillator frequency, in MHz.
xoscFreq = 12 // MHz
)

// I2C Default pins on Raspberry Pico.
const (
I2C0_SDA_PIN = GP4
I2C0_SCL_PIN = GP5

I2C1_SDA_PIN = GP2
I2C1_SCL_PIN = GP3
)

// SPI default pins
const (
// Default Serial Clock Bus 0 for SPI communications
SPI0_SCK_PIN = GPIO18
// Default Serial Out Bus 0 for SPI communications
SPI0_SDO_PIN = GPIO19 // Tx
// Default Serial In Bus 0 for SPI communications
SPI0_SDI_PIN = GPIO16 // Rx

// Default Serial Clock Bus 1 for SPI communications
SPI1_SCK_PIN = GPIO10
// Default Serial Out Bus 1 for SPI communications
SPI1_SDO_PIN = GPIO11 // Tx
// Default Serial In Bus 1 for SPI communications
SPI1_SDI_PIN = GPIO12 // Rx
)

// UART pins
const (
UART0_TX_PIN = GPIO0
UART0_RX_PIN = GPIO1
UART1_TX_PIN = GPIO8
UART1_RX_PIN = GPIO9
UART_TX_PIN = UART0_TX_PIN
UART_RX_PIN = UART0_RX_PIN
)

var DefaultUART = UART0

// USB identifiers
const (
usb_STRING_PRODUCT = "Pico2"
usb_STRING_MANUFACTURER = "Raspberry Pi"
)

var (
usb_VID uint16 = 0x2E8A
usb_PID uint16 = 0x000A
)
68 changes: 53 additions & 15 deletions src/machine/machine_rp2040.go → src/machine/machine_rp2.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,55 @@
//go:build rp2040
//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 (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should update comment:

Suggested change
// UART on the RP2040
// UART on the RP2040/RP2350

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(rp.RESETS_RESET_IO_QSPI |
rp.RESETS_RESET_PADS_QSPI |
rp.RESETS_RESET_PLL_USB |
rp.RESETS_RESET_USBCTRL |
rp.RESETS_RESET_SYSCFG |
rp.RESETS_RESET_PLL_SYS)
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(rp.RESETS_RESET_ADC |
rp.RESETS_RESET_RTC |
rp.RESETS_RESET_SPI0 |
rp.RESETS_RESET_SPI1 |
rp.RESETS_RESET_UART0 |
rp.RESETS_RESET_UART1 |
rp.RESETS_RESET_USBCTRL)
bits = ^uint32(initUnreset)
unresetBlockWait(bits)

clocks.init()
Expand Down Expand Up @@ -94,4 +111,25 @@ const (
)

// DMA channels usable on the RP2040.
var dmaChannels = (*[12]dmaChannel)(unsafe.Pointer(rp.DMA))
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
}
21 changes: 0 additions & 21 deletions src/machine/machine_rp2040_i2c.go
Original file line number Diff line number Diff line change
Expand Up @@ -631,24 +631,3 @@ func (b i2cAbortError) Reasons() (reasons []string) {
}
return reasons
}

//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
}
2 changes: 1 addition & 1 deletion src/machine/machine_rp2040_rtc.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func toAlarmTime(delay uint32) rtcTime {

func (rtc *rtcType) setDivider() {
// Get clk_rtc freq and make sure it is running
rtcFreq := configuredFreq[clkRTC]
rtcFreq := configuredFreq[ClkRTC]
if rtcFreq == 0 {
panic("can not set RTC divider, clock is not running")
}
Expand Down
Loading
Loading