mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-16 02:33:28 +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,100 @@
|
||||
//go:build rp2040 || rp2350
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/rp"
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type pll struct {
|
||||
cs volatile.Register32
|
||||
pwr volatile.Register32
|
||||
fbDivInt volatile.Register32
|
||||
prim volatile.Register32
|
||||
}
|
||||
|
||||
var (
|
||||
pllSys = (*pll)(unsafe.Pointer(rp.PLL_SYS))
|
||||
pllUSB = (*pll)(unsafe.Pointer(rp.PLL_USB))
|
||||
)
|
||||
|
||||
// init initializes pll (Sys or USB) given the following parameters.
|
||||
//
|
||||
// Input clock divider, refdiv.
|
||||
//
|
||||
// Requested output frequency from the VCO (voltage controlled oscillator), vcoFreq.
|
||||
//
|
||||
// Post Divider 1, postDiv1 with range 1-7 and be >= postDiv2.
|
||||
//
|
||||
// Post Divider 2, postDiv2 with range 1-7.
|
||||
func (pll *pll) init(refdiv, vcoFreq, postDiv1, postDiv2 uint32) {
|
||||
refFreq := xoscFreq / refdiv
|
||||
|
||||
// What are we multiplying the reference clock by to get the vco freq
|
||||
// (The regs are called div, because you divide the vco output and compare it to the refclk)
|
||||
fbdiv := vcoFreq / (refFreq * MHz)
|
||||
|
||||
// Check fbdiv range
|
||||
if !(fbdiv >= 16 && fbdiv <= 320) {
|
||||
panic("fbdiv should be in the range [16,320]")
|
||||
}
|
||||
|
||||
// Check divider ranges
|
||||
if !((postDiv1 >= 1 && postDiv1 <= 7) && (postDiv2 >= 1 && postDiv2 <= 7)) {
|
||||
panic("postdiv1, postdiv1 should be in the range [1,7]")
|
||||
}
|
||||
|
||||
// postDiv1 should be >= postDiv2
|
||||
// from appnote page 11
|
||||
// postdiv1 is designed to operate with a higher input frequency
|
||||
// than postdiv2
|
||||
if postDiv1 < postDiv2 {
|
||||
panic("postdiv1 should be greater than or equal to postdiv2")
|
||||
}
|
||||
|
||||
// Check that reference frequency is no greater than vco / 16
|
||||
if refFreq > vcoFreq/16 {
|
||||
panic("reference frequency should not be greater than vco frequency divided by 16")
|
||||
}
|
||||
|
||||
// div1 feeds into div2 so if div1 is 5 and div2 is 2 then you get a divide by 10
|
||||
pdiv := postDiv1<<rp.PLL_SYS_PRIM_POSTDIV1_Pos | postDiv2<<rp.PLL_SYS_PRIM_POSTDIV2_Pos
|
||||
|
||||
if pll.cs.HasBits(rp.PLL_SYS_CS_LOCK) &&
|
||||
refdiv == pll.cs.Get()&rp.PLL_SYS_CS_REFDIV_Msk &&
|
||||
fbdiv == pll.fbDivInt.Get()&rp.PLL_SYS_FBDIV_INT_FBDIV_INT_Msk &&
|
||||
pdiv == pll.prim.Get()&(rp.PLL_SYS_PRIM_POSTDIV1_Msk&rp.PLL_SYS_PRIM_POSTDIV2_Msk) {
|
||||
// do not disrupt PLL that is already correctly configured and operating
|
||||
return
|
||||
}
|
||||
|
||||
var pllRst uint32
|
||||
if pll == pllSys {
|
||||
pllRst = rp.RESETS_RESET_PLL_SYS
|
||||
} else {
|
||||
pllRst = rp.RESETS_RESET_PLL_USB
|
||||
}
|
||||
resetBlock(pllRst)
|
||||
unresetBlockWait(pllRst)
|
||||
|
||||
// Load VCO-related dividers before starting VCO
|
||||
pll.cs.Set(refdiv)
|
||||
pll.fbDivInt.Set(fbdiv)
|
||||
|
||||
// Turn on PLL
|
||||
pwr := uint32(rp.PLL_SYS_PWR_PD | rp.PLL_SYS_PWR_VCOPD)
|
||||
pll.pwr.ClearBits(pwr)
|
||||
|
||||
// Wait for PLL to lock
|
||||
for !(pll.cs.HasBits(rp.PLL_SYS_CS_LOCK)) {
|
||||
}
|
||||
|
||||
// Set up post dividers
|
||||
pll.prim.Set(pdiv)
|
||||
|
||||
// Turn on post divider
|
||||
pll.pwr.ClearBits(rp.PLL_SYS_PWR_POSTDIVPD)
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user