55 feature( asm_experimental_arch, naked_functions)
66) ]
77
8+ // Target memory configuration
9+
10+ // Decompressor is 43776 bytes, reserve more in case compiler changes layout
11+ const _: [ u8 ; 43776 ] = [ 0 ; core:: mem:: size_of :: < Decompressor > ( ) ] ;
12+
13+ // Placement:
14+ // - Xtensa: Pin stack top first, calculate backwards:
15+ // - 32K stack
16+ // - 32K for data pages
17+ // - 64K for decompressor state
18+ // - RISC-V: At the end of memory, calculate backwards:
19+ // - 64K for data pages (32K needed, but 64K is easier to calculate)
20+ // - 64K for decompressor state
21+ // - stack comes automatically after the loader
22+
23+ // Xtensa | Image IRAM | Image DRAM | STATE_ADDR | data_load_addr | Stack (top)
24+ // ESP32-S2 | 0x4002_C400 | 0x3FFB_C400 | 0x3FFB_E000 | 0x3FFC_E000 | 0x3FFD_F000
25+ // ESP32-S3 | 0x4038_0400 | 0x3FC9_0400 | 0x3FCB_0000 | 0x3FCC_0000 | 0x3FCD_0000
26+
27+ // RISC-V | Image IRAM | Image DRAM | STATE_ADDR | data_load_addr | DRAM end (avoiding cache)
28+ // ESP32-C2 | 0x4038_C000 | 0x3FCA_C000 | 0x3FCB_0000 | 0x3FCC_0000 | 0x3FCD_0000
29+ // ESP32-C3 | 0x4039_0000 | 0x3FC1_0000 | 0x3FCB_0000 | 0x3FCC_0000 | 0x3FCD_0000
30+ // ESP32-C6 | 0x4081_0000 | 0x4081_0000 | 0x4084_0000 | 0x4085_0000 | 0x4086_0000
31+ // ESP32-H2 | 0x4081_0000 | 0x4081_0000 | 0x4082_0000 | 0x4083_0000 | 0x4083_8000 !! has smaller RAM, only reserve 32K for data
32+
33+ // "State" base address
34+ #[ cfg( feature = "esp32s2" ) ]
35+ const STATE_ADDR : usize = 0x3FFB_E000 ;
36+ #[ cfg( feature = "esp32s3" ) ]
37+ const STATE_ADDR : usize = 0x3FCB_0000 ;
38+ #[ cfg( feature = "esp32c2" ) ]
39+ const STATE_ADDR : usize = 0x3FCB_0000 ;
40+ #[ cfg( feature = "esp32c3" ) ]
41+ const STATE_ADDR : usize = 0x3FCB_0000 ;
42+ #[ cfg( feature = "esp32c6" ) ]
43+ const STATE_ADDR : usize = 0x4086_0000 ;
44+ #[ cfg( feature = "esp32h2" ) ]
45+ const STATE_ADDR : usize = 0x4082_0000 ;
46+
47+ // End of target memory configuration
48+
849// Define necessary functions for flash loader
950//
1051// These are taken from the [ARM CMSIS-Pack documentation]
1152//
1253// [ARM CMSIS-Pack documentation]: https://arm-software.github.io/CMSIS_5/Pack/html/algorithmFunc.html
1354
14- use core:: ptr:: addr_of_mut;
15-
1655use panic_never as _;
1756
1857use crate :: tinfl:: {
@@ -25,13 +64,13 @@ mod flash;
2564mod properties;
2665mod tinfl;
2766
67+ #[ cfg( not( any( target_arch = "xtensa" , target_arch = "riscv32" ) ) ) ]
68+ compile_error ! ( "specify the target with `--target`" ) ;
69+
2870const ERROR_BASE_INTERNAL : i32 = -1000 ;
2971const ERROR_BASE_TINFL : i32 = -2000 ;
3072const ERROR_BASE_FLASH : i32 = -4000 ;
3173
32- #[ cfg( not( any( target_arch = "xtensa" , target_arch = "riscv32" ) ) ) ]
33- compile_error ! ( "specify the target with `--target`" ) ;
34-
3574#[ cfg( feature = "log" ) ]
3675mod log {
3776
@@ -75,63 +114,23 @@ macro_rules! dprintln {
75114 ( $fmt: expr, $( $arg: tt) * ) => { } ;
76115}
77116
78- static mut DECOMPRESSOR : Option < Decompressor > = None ;
79-
80- #[ cfg( feature = "esp32s2" ) ]
81- mod chip_specific {
82- use core:: ops:: Range ;
83-
84- pub const OFFSET : isize = 0x4002_8000 - 0x3FFB_8000 ;
85- pub const IRAM : Range < usize > = 0x4000_0000 ..0x4007_2000 ;
86- }
87-
88- #[ cfg( feature = "esp32s3" ) ]
89- mod chip_specific {
90- use core:: ops:: Range ;
91-
92- pub const OFFSET : isize = 0x4037_8000 - 0x3FC8_8000 ;
93- pub const IRAM : Range < usize > = 0x4000_0000 ..0x403E_0000 ;
94- }
95-
96- // We need to access the page buffers and decompressor on the data bus, otherwise we'll run into
97- // LoadStoreError exceptions. This should be removed once probe-rs can place data into the correct
98- // memory region.
99- fn addr_to_data_bus ( addr : usize ) -> usize {
100- #[ cfg( any( feature = "esp32s2" , feature = "esp32s3" ) ) ]
101- {
102- if chip_specific:: IRAM . contains ( & addr) {
103- return ( addr as isize - chip_specific:: OFFSET ) as usize ;
104- }
105- }
106-
107- addr
108- }
109-
110- unsafe fn data_bus < T > ( ptr : * const T ) -> * const T {
111- addr_to_data_bus ( ptr as usize ) as * const T
112- }
113-
114- unsafe fn data_bus_mut < T > ( ptr : * mut T ) -> * mut T {
115- addr_to_data_bus ( ptr as usize ) as * mut T
116- }
117-
118- unsafe fn decompressor < ' a > ( ) -> Option < & ' a mut Decompressor > {
119- let decompressor = addr_of_mut ! ( DECOMPRESSOR ) ;
120- let decompressor = data_bus_mut ( decompressor) ;
117+ const INITED_MAGIC : u32 = 0xAAC0FFEE ;
118+ const INITED : * mut u32 = STATE_ADDR as * mut u32 ;
119+ const DECOMPRESSOR : * mut Decompressor = ( STATE_ADDR + 4 ) as * mut Decompressor ;
121120
122- decompressor. as_mut ( ) . unwrap_unchecked ( ) . as_mut ( )
121+ fn is_inited ( ) -> bool {
122+ unsafe { * INITED == INITED_MAGIC }
123123}
124124
125125/// Setup the device for the flashing process.
126126#[ no_mangle]
127127pub unsafe extern "C" fn Init_impl ( _adr : u32 , _clk : u32 , _fnc : u32 ) -> i32 {
128- if decompressor ( ) . is_none ( ) {
129- dprintln ! ( "INIT" ) ;
128+ dprintln ! ( "INIT" ) ;
130129
131- flash:: attach ( ) ;
130+ flash:: attach ( ) ;
132131
133- DECOMPRESSOR = Some ( Decompressor :: new ( ) ) ;
134- }
132+ * DECOMPRESSOR = Decompressor :: new ( ) ;
133+ * INITED = INITED_MAGIC ;
135134
136135 0
137136}
@@ -141,17 +140,23 @@ pub unsafe extern "C" fn Init_impl(_adr: u32, _clk: u32, _fnc: u32) -> i32 {
141140/// Returns 0 on success, 1 on failure.
142141#[ no_mangle]
143142pub unsafe extern "C" fn EraseSector_impl ( adr : u32 ) -> i32 {
143+ if !is_inited ( ) {
144+ return ERROR_BASE_INTERNAL - 1 ;
145+ } ;
144146 flash:: erase_block ( adr)
145147}
146148
147149#[ no_mangle]
148150pub unsafe extern "C" fn EraseChip_impl ( ) -> i32 {
151+ if !is_inited ( ) {
152+ return ERROR_BASE_INTERNAL - 1 ;
153+ } ;
149154 flash:: erase_chip ( )
150155}
151156
152157#[ no_mangle]
153158pub unsafe extern "C" fn ProgramPage_impl ( adr : u32 , sz : u32 , buf : * const u8 ) -> i32 {
154- let Some ( decompressor ) = decompressor ( ) else {
159+ if ! is_inited ( ) {
155160 return ERROR_BASE_INTERNAL - 1 ;
156161 } ;
157162
@@ -162,24 +167,25 @@ pub unsafe extern "C" fn ProgramPage_impl(adr: u32, sz: u32, buf: *const u8) ->
162167
163168 dprintln ! ( "PROGRAM {} bytes @ {}" , sz, adr) ;
164169
165- // Access data through the data bus
166- let buf = data_bus ( buf) ;
167-
168170 let input = core:: slice:: from_raw_parts ( buf, sz as usize ) ;
169171
170- decompressor . program ( adr, input)
172+ ( * DECOMPRESSOR ) . program ( adr, input)
171173}
172174
173175#[ no_mangle]
174176pub unsafe extern "C" fn UnInit_impl ( _fnc : u32 ) -> i32 {
175- let Some ( decompressor ) = decompressor ( ) else {
177+ if ! is_inited ( ) {
176178 return ERROR_BASE_INTERNAL - 1 ;
177179 } ;
178180
179- decompressor . flush ( ) ;
181+ ( * DECOMPRESSOR ) . flush ( ) ;
180182
181183 // The flash ROM functions don't wait for the end of the last operation.
182- flash:: wait_for_idle ( )
184+ let r = flash:: wait_for_idle ( ) ;
185+
186+ * INITED = 0 ;
187+
188+ r
183189}
184190
185191pub struct Decompressor {
0 commit comments