3
3
4
4
use flash_algorithm:: * ;
5
5
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 {
8
54
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.
10
58
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
12
61
/// (there's also a ROM data table which we don't need)
13
62
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
+
14
102
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
+ } ;
19
108
if result == 0 {
20
- return None ;
109
+ return Err ( ErrorCode :: new ( 0x2000_0000 | tag ) . unwrap ( ) ) ;
21
110
}
22
- Some ( core:: mem:: transmute_copy ( & result) )
111
+ Ok ( core:: mem:: transmute_copy ( & result) )
23
112
}
24
113
}
25
114
@@ -33,8 +122,8 @@ struct ROMFuncs {
33
122
}
34
123
35
124
impl ROMFuncs {
36
- fn load ( ) -> Option < Self > {
37
- Some ( ROMFuncs {
125
+ fn load ( ) -> Result < Self , ErrorCode > {
126
+ Ok ( ROMFuncs {
38
127
connect_internal_flash : find_func ( * b"IF" ) ?,
39
128
flash_exit_xip : find_func ( * b"EX" ) ?,
40
129
flash_range_erase : find_func ( * b"RE" ) ?,
@@ -45,11 +134,11 @@ impl ROMFuncs {
45
134
}
46
135
}
47
136
48
- struct RP2040Algo {
137
+ struct RP2Algo {
49
138
funcs : ROMFuncs ,
50
139
}
51
140
52
- algorithm ! ( RP2040Algo , {
141
+ algorithm ! ( RP2Algo , {
53
142
flash_address: 0x1000_0000 ,
54
143
flash_size: 0x0100_0000 ,
55
144
page_size: 0x100 ,
@@ -64,11 +153,9 @@ const BLOCK_SIZE: u32 = 65536;
64
153
const SECTOR_SIZE : u32 = 4096 ;
65
154
const BLOCK_ERASE_CMD : u8 = 0xd8 ;
66
155
67
- impl FlashAlgorithm for RP2040Algo {
156
+ impl FlashAlgorithm for RP2Algo {
68
157
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 ( ) ?;
72
159
( funcs. connect_internal_flash ) ( ) ;
73
160
( funcs. flash_exit_xip ) ( ) ;
74
161
Ok ( Self { funcs } )
@@ -94,7 +181,7 @@ impl FlashAlgorithm for RP2040Algo {
94
181
}
95
182
}
96
183
97
- impl Drop for RP2040Algo {
184
+ impl Drop for RP2Algo {
98
185
fn drop ( & mut self ) {
99
186
( self . funcs . flash_flush_cache ) ( ) ;
100
187
( self . funcs . flash_enter_cmd_xip ) ( ) ;
0 commit comments