Skip to content

Commit

Permalink
Merge pull request #24 from konkers/pr/rp2350
Browse files Browse the repository at this point in the history
Add RP2350 support
  • Loading branch information
9names authored Aug 26, 2024
2 parents 35b9d6f + a72c5cf commit f8ca8ec
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 22 deletions.
File renamed without changes.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RaspberryPi Pico RP2040 flash algorithm
# RaspberryPi Pico RP2 flash algorithm

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

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

`main.rs` has the actual implementation for RP2040.
`main.rs` has the actual implementation for RP2040 and RP2350.

## License

Expand Down
125 changes: 106 additions & 19 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,112 @@

use flash_algorithm::*;

fn find_func<T>(tag: [u8; 2]) -> Option<T> {
let tag = u16::from_le_bytes(tag) as u32;
extern "C" {
/// Enables the redundancy coprocessor (RCP)
///
/// If the RCP is already initialized, `init_rcp` will skip initialization
/// as initializing it twice will cause a fault.
fn init_rcp();
}

// Implementation adapted from the PicoSDK's crt0.S.
core::arch::global_asm!(
r#"
.syntax unified
.cpu cortex-m33
.thumb
.global init_rcp
init_rcp:
// Enable the RCP. To save space, it is assumed that no other
// coprocessors are enabled.
ldr r0, =0xe0000000 + 0x0000ed88 // PPB_BASE + M33_CPACR_OFFSET
movs r1, 0x0000c000 // CPACR_CP7_BITS
str r1, [r0]
// Check that to see if the RCP is already initialized.
//
// Since this check requires passing `r15` to `mrc` and the inline
// assembler will not allow this, we hard code the instruction here:
// `mrc p7, #1, r15, c0, c0, #0`
.byte 0x30
.byte 0xee
.byte 0x10
.byte 0xf7
// Skip initialization if already initialized.
bmi 2f
// Initialize the RCP.
mcrr p7, #8, r0, r0, c0
mcrr p7, #8, r0, r0, c1
// Signal other core.
sev
2:
bx lr
"#,
);

unsafe fn lookup_func_rp2040(tag: u32) -> usize {
type RomTableLookupFn = unsafe extern "C" fn(table: *const u16, code: u32) -> usize;
/// This location in flash holds a 16-bit truncated pointer for the ROM lookup function

/// This location in ROM holds a 16-bit truncated pointer for the ROM lookup function for
/// RP2040 ROMs.
const ROM_TABLE_LOOKUP_PTR: *const u16 = 0x0000_0018 as _;
/// This location in flash holds a 16-bit truncated pointer for the ROM function table

/// This location in ROM holds a 16-bit truncated pointer for the ROM function table
/// (there's also a ROM data table which we don't need)
const FUNC_TABLE: *const u16 = 0x0000_0014 as _;

let lookup_func = ROM_TABLE_LOOKUP_PTR.read() as usize;
let lookup_func: RomTableLookupFn = core::mem::transmute(lookup_func);
let table = FUNC_TABLE.read() as usize;
lookup_func(table as *const u16, tag)
}

unsafe fn lookup_func_235x(tag: u32) -> usize {
type RomTableLookupFn = unsafe extern "C" fn(code: u32, mask: u32) -> usize;

/// This location in ROM holds a 16-bit truncated pointer for the ROM lookup function for
/// RP235x ROMs.
const ROM_TABLE_LOOKUP_PTR: *const u16 = 0x0000_0016 as _;

/// The flash-algo needs to run in secure mode so we need too look up
/// functions in that context
const RT_FLAG_FUNC_ARM_SEC: u32 = 0x0004;

// The RCP (redundancy coprocessor) must be enabled in order to call ROM functions.
init_rcp();

let lookup_func = ROM_TABLE_LOOKUP_PTR.read() as usize;
let lookup_func: RomTableLookupFn = core::mem::transmute(lookup_func);
lookup_func(tag, RT_FLAG_FUNC_ARM_SEC)
}

fn find_func<T>(tag: [u8; 2]) -> Result<T, ErrorCode> {
let tag = u16::from_le_bytes(tag) as u32;

/// This location in ROM holds a 3 byte magic value that confirms the validity of the
/// ROM as well as identifying different interfaces for the RP2040 and RP235x.
const BOOTROM_MAGIC: *const [u8; 3] = 0x0000_0010 as _;

/// Magic value for RP2040 ROMs.
const RP2040_BOOTROM_MAGIC: &[u8; 3] = b"Mu\x01";

/// Magic value for RP235X ROMs.
const RP235X_BOOTROM_MAGIC: &[u8; 3] = b"Mu\x02";

unsafe {
let lookup_func = ROM_TABLE_LOOKUP_PTR.read() as usize;
let lookup_func: RomTableLookupFn = core::mem::transmute(lookup_func);
let table = FUNC_TABLE.read() as usize;
let result = lookup_func(table as *const u16, tag);
let result = match &*BOOTROM_MAGIC {
RP2040_BOOTROM_MAGIC => lookup_func_rp2040(tag),
RP235X_BOOTROM_MAGIC => lookup_func_235x(tag),
_ => return Err(ErrorCode::new(0x1000_0000 | tag).unwrap()),
};
if result == 0 {
return None;
return Err(ErrorCode::new(0x2000_0000 | tag).unwrap());
}
Some(core::mem::transmute_copy(&result))
Ok(core::mem::transmute_copy(&result))
}
}

Expand All @@ -33,8 +122,8 @@ struct ROMFuncs {
}

impl ROMFuncs {
fn load() -> Option<Self> {
Some(ROMFuncs {
fn load() -> Result<Self, ErrorCode> {
Ok(ROMFuncs {
connect_internal_flash: find_func(*b"IF")?,
flash_exit_xip: find_func(*b"EX")?,
flash_range_erase: find_func(*b"RE")?,
Expand All @@ -45,11 +134,11 @@ impl ROMFuncs {
}
}

struct RP2040Algo {
struct RP2Algo {
funcs: ROMFuncs,
}

algorithm!(RP2040Algo, {
algorithm!(RP2Algo, {
flash_address: 0x1000_0000,
flash_size: 0x0100_0000,
page_size: 0x100,
Expand All @@ -64,11 +153,9 @@ const BLOCK_SIZE: u32 = 65536;
const SECTOR_SIZE: u32 = 4096;
const BLOCK_ERASE_CMD: u8 = 0xd8;

impl FlashAlgorithm for RP2040Algo {
impl FlashAlgorithm for RP2Algo {
fn new(_address: u32, _clock: u32, _function: Function) -> Result<Self, ErrorCode> {
let Some(funcs) = ROMFuncs::load() else {
return Err(ErrorCode::new(1).unwrap());
};
let funcs = ROMFuncs::load()?;
(funcs.connect_internal_flash)();
(funcs.flash_exit_xip)();
Ok(Self { funcs })
Expand All @@ -94,7 +181,7 @@ impl FlashAlgorithm for RP2040Algo {
}
}

impl Drop for RP2040Algo {
impl Drop for RP2Algo {
fn drop(&mut self) {
(self.funcs.flash_flush_cache)();
(self.funcs.flash_enter_cmd_xip)();
Expand Down

0 comments on commit f8ca8ec

Please sign in to comment.