33
44use 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
35124impl 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;
64153const SECTOR_SIZE : u32 = 4096 ;
65154const 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