Skip to content

Commit a72c5cf

Browse files
committed
Add RP2350 support
1 parent 8c4ea1e commit a72c5cf

File tree

2 files changed

+109
-22
lines changed

2 files changed

+109
-22
lines changed

Diff for: README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# RaspberryPi Pico RP2040 flash algorithm
1+
# RaspberryPi Pico RP2 flash algorithm
22

3-
This is a flash algorithm for the RP2040 chip, used in the Raspberry Pi Pico board.
3+
This is a flash algorithm for the RP2040 and RP2350 chips, used in the Raspberry Pi Pico board.
44
It implements the CMSIS-Pack ABI, so it's compatible with any tools that use it, including probe-rs.
55

66
## Dependencies
@@ -32,7 +32,7 @@ flash-algo$ ./build.sh
3232
The `algo` module contains the FlashAlgo trait, and an `algo!` macro to generate
3333
the glue functions for a given struct implementing it. This is generic for all chips, so feel free to reuse it!
3434

35-
`main.rs` has the actual implementation for RP2040.
35+
`main.rs` has the actual implementation for RP2040 and RP2350.
3636

3737
## License
3838

Diff for: src/main.rs

+106-19
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,112 @@
33

44
use flash_algorithm::*;
55

6-
fn find_func<T>(tag: [u8; 2]) -> Option<T> {
7-
let tag = u16::from_le_bytes(tag) as u32;
6+
extern "C" {
7+
/// Enables the redundancy coprocessor (RCP)
8+
///
9+
/// If the RCP is already initialized, `init_rcp` will skip initialization
10+
/// as initializing it twice will cause a fault.
11+
fn init_rcp();
12+
}
13+
14+
// Implementation adapted from the PicoSDK's crt0.S.
15+
core::arch::global_asm!(
16+
r#"
17+
.syntax unified
18+
.cpu cortex-m33
19+
.thumb
20+
.global init_rcp
21+
init_rcp:
22+
// Enable the RCP. To save space, it is assumed that no other
23+
// coprocessors are enabled.
24+
ldr r0, =0xe0000000 + 0x0000ed88 // PPB_BASE + M33_CPACR_OFFSET
25+
movs r1, 0x0000c000 // CPACR_CP7_BITS
26+
str r1, [r0]
27+
28+
// Check that to see if the RCP is already initialized.
29+
//
30+
// Since this check requires passing `r15` to `mrc` and the inline
31+
// assembler will not allow this, we hard code the instruction here:
32+
// `mrc p7, #1, r15, c0, c0, #0`
33+
.byte 0x30
34+
.byte 0xee
35+
.byte 0x10
36+
.byte 0xf7
37+
38+
// Skip initialization if already initialized.
39+
bmi 2f
40+
41+
// Initialize the RCP.
42+
mcrr p7, #8, r0, r0, c0
43+
mcrr p7, #8, r0, r0, c1
44+
45+
// Signal other core.
46+
sev
47+
48+
2:
49+
bx lr
50+
"#,
51+
);
52+
53+
unsafe fn lookup_func_rp2040(tag: u32) -> usize {
854
type RomTableLookupFn = unsafe extern "C" fn(table: *const u16, code: u32) -> usize;
9-
/// This location in flash holds a 16-bit truncated pointer for the ROM lookup function
55+
56+
/// This location in ROM holds a 16-bit truncated pointer for the ROM lookup function for
57+
/// RP2040 ROMs.
1058
const ROM_TABLE_LOOKUP_PTR: *const u16 = 0x0000_0018 as _;
11-
/// This location in flash holds a 16-bit truncated pointer for the ROM function table
59+
60+
/// This location in ROM holds a 16-bit truncated pointer for the ROM function table
1261
/// (there's also a ROM data table which we don't need)
1362
const FUNC_TABLE: *const u16 = 0x0000_0014 as _;
63+
64+
let lookup_func = ROM_TABLE_LOOKUP_PTR.read() as usize;
65+
let lookup_func: RomTableLookupFn = core::mem::transmute(lookup_func);
66+
let table = FUNC_TABLE.read() as usize;
67+
lookup_func(table as *const u16, tag)
68+
}
69+
70+
unsafe fn lookup_func_235x(tag: u32) -> usize {
71+
type RomTableLookupFn = unsafe extern "C" fn(code: u32, mask: u32) -> usize;
72+
73+
/// This location in ROM holds a 16-bit truncated pointer for the ROM lookup function for
74+
/// RP235x ROMs.
75+
const ROM_TABLE_LOOKUP_PTR: *const u16 = 0x0000_0016 as _;
76+
77+
/// The flash-algo needs to run in secure mode so we need too look up
78+
/// functions in that context
79+
const RT_FLAG_FUNC_ARM_SEC: u32 = 0x0004;
80+
81+
// The RCP (redundancy coprocessor) must be enabled in order to call ROM functions.
82+
init_rcp();
83+
84+
let lookup_func = ROM_TABLE_LOOKUP_PTR.read() as usize;
85+
let lookup_func: RomTableLookupFn = core::mem::transmute(lookup_func);
86+
lookup_func(tag, RT_FLAG_FUNC_ARM_SEC)
87+
}
88+
89+
fn find_func<T>(tag: [u8; 2]) -> Result<T, ErrorCode> {
90+
let tag = u16::from_le_bytes(tag) as u32;
91+
92+
/// This location in ROM holds a 3 byte magic value that confirms the validity of the
93+
/// ROM as well as identifying different interfaces for the RP2040 and RP235x.
94+
const BOOTROM_MAGIC: *const [u8; 3] = 0x0000_0010 as _;
95+
96+
/// Magic value for RP2040 ROMs.
97+
const RP2040_BOOTROM_MAGIC: &[u8; 3] = b"Mu\x01";
98+
99+
/// Magic value for RP235X ROMs.
100+
const RP235X_BOOTROM_MAGIC: &[u8; 3] = b"Mu\x02";
101+
14102
unsafe {
15-
let lookup_func = ROM_TABLE_LOOKUP_PTR.read() as usize;
16-
let lookup_func: RomTableLookupFn = core::mem::transmute(lookup_func);
17-
let table = FUNC_TABLE.read() as usize;
18-
let result = lookup_func(table as *const u16, tag);
103+
let result = match &*BOOTROM_MAGIC {
104+
RP2040_BOOTROM_MAGIC => lookup_func_rp2040(tag),
105+
RP235X_BOOTROM_MAGIC => lookup_func_235x(tag),
106+
_ => return Err(ErrorCode::new(0x1000_0000 | tag).unwrap()),
107+
};
19108
if result == 0 {
20-
return None;
109+
return Err(ErrorCode::new(0x2000_0000 | tag).unwrap());
21110
}
22-
Some(core::mem::transmute_copy(&result))
111+
Ok(core::mem::transmute_copy(&result))
23112
}
24113
}
25114

@@ -33,8 +122,8 @@ struct ROMFuncs {
33122
}
34123

35124
impl ROMFuncs {
36-
fn load() -> Option<Self> {
37-
Some(ROMFuncs {
125+
fn load() -> Result<Self, ErrorCode> {
126+
Ok(ROMFuncs {
38127
connect_internal_flash: find_func(*b"IF")?,
39128
flash_exit_xip: find_func(*b"EX")?,
40129
flash_range_erase: find_func(*b"RE")?,
@@ -45,11 +134,11 @@ impl ROMFuncs {
45134
}
46135
}
47136

48-
struct RP2040Algo {
137+
struct RP2Algo {
49138
funcs: ROMFuncs,
50139
}
51140

52-
algorithm!(RP2040Algo, {
141+
algorithm!(RP2Algo, {
53142
flash_address: 0x1000_0000,
54143
flash_size: 0x0100_0000,
55144
page_size: 0x100,
@@ -64,11 +153,9 @@ const BLOCK_SIZE: u32 = 65536;
64153
const SECTOR_SIZE: u32 = 4096;
65154
const BLOCK_ERASE_CMD: u8 = 0xd8;
66155

67-
impl FlashAlgorithm for RP2040Algo {
156+
impl FlashAlgorithm for RP2Algo {
68157
fn new(_address: u32, _clock: u32, _function: Function) -> Result<Self, ErrorCode> {
69-
let Some(funcs) = ROMFuncs::load() else {
70-
return Err(ErrorCode::new(1).unwrap());
71-
};
158+
let funcs = ROMFuncs::load()?;
72159
(funcs.connect_internal_flash)();
73160
(funcs.flash_exit_xip)();
74161
Ok(Self { funcs })
@@ -94,7 +181,7 @@ impl FlashAlgorithm for RP2040Algo {
94181
}
95182
}
96183

97-
impl Drop for RP2040Algo {
184+
impl Drop for RP2Algo {
98185
fn drop(&mut self) {
99186
(self.funcs.flash_flush_cache)();
100187
(self.funcs.flash_enter_cmd_xip)();

0 commit comments

Comments
 (0)