22#![ no_main]
33#![ cfg_attr( target_arch = "xtensa" , feature( asm_experimental_arch) ) ]
44
5+ // TODO: implement clock frequency setting for ESP32-C5
6+
57// Target memory configuration
68
79// Decompressor is 43776 bytes, reserve more in case compiler changes layout
@@ -78,7 +80,6 @@ const ERROR_BASE_FLASH: i32 = -4000;
7880
7981#[ cfg( feature = "log" ) ]
8082mod log {
81-
8283 extern "C" {
8384 fn uart_tx_one_char ( byte : u8 ) ;
8485 }
@@ -119,22 +120,138 @@ macro_rules! dprintln {
119120 ( $fmt: expr, $( $arg: tt) * ) => { } ;
120121}
121122
123+ #[ cfg( all( feature = "max-cpu-frequency" , not( feature = "esp32c5" ) ) ) ]
124+ mod max_cpu_frequency {
125+ cfg_if:: cfg_if! {
126+ if #[ cfg( feature = "esp32" ) ] {
127+ const SYSTEM_CPU_PER_CONF_REG : * mut u32 = 0x3FF0003C as * mut u32 ;
128+ const SYSTEM_CPUPERIOD_SEL_M : u32 = 3 ;
129+ const SYSTEM_CPUPERIOD_MAX : u32 = 2 ;
130+
131+ const SYSTEM_SYSCLK_CONF_REG : * mut u32 = 0x3FF48070 as * mut u32 ;
132+ const SYSTEM_SOC_CLK_SEL_M : u32 = 3 << 27 ;
133+ const SYSTEM_SOC_CLK_MAX : u32 = 1 << 27 ;
134+ } else if #[ cfg( feature = "esp32s2" ) ] {
135+ const SYSTEM_CPU_PER_CONF_REG : * mut u32 = 0x3F4C0018 as * mut u32 ;
136+ const SYSTEM_CPUPERIOD_SEL_M : u32 = 3 ;
137+ const SYSTEM_CPUPERIOD_MAX : u32 = 2 ;
138+
139+ const SYSTEM_SYSCLK_CONF_REG : * mut u32 = 0x3F4C008C as * mut u32 ;
140+ const SYSTEM_SOC_CLK_SEL_M : u32 = 3 << 10 ;
141+ const SYSTEM_SOC_CLK_MAX : u32 = 1 << 10 ;
142+ } else if #[ cfg( feature = "esp32s3" ) ] {
143+ const SYSTEM_CPU_PER_CONF_REG : * mut u32 = 0x600C0010 as * mut u32 ;
144+ const SYSTEM_CPUPERIOD_SEL_M : u32 = 3 ;
145+ const SYSTEM_CPUPERIOD_MAX : u32 = 2 ;
146+
147+ const SYSTEM_SYSCLK_CONF_REG : * mut u32 = 0x600C0060 as * mut u32 ;
148+ const SYSTEM_SOC_CLK_SEL_M : u32 = 3 << 10 ;
149+ const SYSTEM_SOC_CLK_MAX : u32 = 1 << 10 ;
150+ } else if #[ cfg( any( feature = "esp32c2" , feature = "esp32c3" ) ) ] {
151+ const SYSTEM_CPU_PER_CONF_REG : * mut u32 = 0x600C0008 as * mut u32 ;
152+ const SYSTEM_CPUPERIOD_SEL_M : u32 = 3 ;
153+ const SYSTEM_CPUPERIOD_MAX : u32 = 1 ;
154+
155+ const SYSTEM_SYSCLK_CONF_REG : * mut u32 = 0x600C0058 as * mut u32 ;
156+ const SYSTEM_SOC_CLK_SEL_M : u32 = 3 << 10 ;
157+ const SYSTEM_SOC_CLK_MAX : u32 = 1 << 10 ;
158+ } else if #[ cfg( feature = "esp32h2" ) ] {
159+ const PCR_SYSCLK_CONF_REG : * mut u32 = 0x6009610c as * mut u32 ;
160+
161+ const PCR_SOC_CLK_SEL_M : u32 = 3 << 16 ;
162+ const PCR_SOC_CLK_MAX : u32 = 1 << 16 ;
163+ } else if #[ cfg( feature = "esp32c6" ) ] {
164+ const PCR_SYSCLK_CONF_REG : * mut u32 = 0x60096110 as * mut u32 ;
165+
166+ const PCR_SOC_CLK_SEL_M : u32 = 3 << 16 ;
167+ const PCR_SOC_CLK_MAX : u32 = 1 << 16 ;
168+ }
169+ }
170+
171+ pub struct CpuSaveState {
172+ #[ cfg( not( any( feature = "esp32c6" , feature = "esp32h2" ) ) ) ]
173+ saved_cpu_per_conf_reg : u32 ,
174+ saved_sysclk_conf_reg : u32 ,
175+ }
176+
177+ pub fn set_max_cpu_freq ( state : & mut CpuSaveState ) {
178+ cfg_if:: cfg_if! {
179+ if #[ cfg( any( feature = "esp32c6" , feature = "esp32h2" ) ) ] {
180+ state. saved_sysclk_conf_reg = unsafe { PCR_SYSCLK_CONF_REG . read_volatile( ) } ;
181+ } else {
182+ state. saved_cpu_per_conf_reg = unsafe { SYSTEM_CPU_PER_CONF_REG . read_volatile( ) } ;
183+ state. saved_sysclk_conf_reg = unsafe { SYSTEM_SYSCLK_CONF_REG . read_volatile( ) } ;
184+ }
185+ }
186+
187+ cfg_if:: cfg_if! {
188+ if #[ cfg( any( feature = "esp32c6" , feature = "esp32h2" ) ) ] {
189+ unsafe { PCR_SYSCLK_CONF_REG . write_volatile( ( state. saved_sysclk_conf_reg & !PCR_SOC_CLK_SEL_M ) | PCR_SOC_CLK_MAX ) } ;
190+ } else if #[ cfg( feature = "esp32s3" ) ] {
191+ extern "C" {
192+ fn ets_delay_us( us: u32 ) ;
193+ }
194+
195+ unsafe { SYSTEM_SYSCLK_CONF_REG . write_volatile( ( state. saved_sysclk_conf_reg & !SYSTEM_SOC_CLK_SEL_M ) | SYSTEM_SOC_CLK_MAX ) } ;
196+ // Leave some time for the change to settle, needed for ESP32-S3
197+ unsafe { ets_delay_us( 100 ) } ;
198+ unsafe { SYSTEM_CPU_PER_CONF_REG . write_volatile( ( state. saved_cpu_per_conf_reg & !SYSTEM_CPUPERIOD_SEL_M ) | SYSTEM_CPUPERIOD_MAX ) } ;
199+ } else {
200+ unsafe { SYSTEM_CPU_PER_CONF_REG . write_volatile( ( state. saved_cpu_per_conf_reg & !SYSTEM_CPUPERIOD_SEL_M ) | SYSTEM_CPUPERIOD_MAX ) } ;
201+ unsafe { SYSTEM_SYSCLK_CONF_REG . write_volatile( ( state. saved_sysclk_conf_reg & !SYSTEM_SOC_CLK_SEL_M ) | SYSTEM_SOC_CLK_MAX ) } ;
202+ }
203+ }
204+ }
205+
206+ pub fn restore_max_cpu_freq ( state : & mut CpuSaveState ) {
207+ cfg_if:: cfg_if! {
208+ if #[ cfg( any( feature = "esp32c6" , feature = "esp32h2" ) ) ] {
209+ unsafe { PCR_SYSCLK_CONF_REG . write_volatile( state. saved_sysclk_conf_reg) } ;
210+ } else {
211+ unsafe { SYSTEM_SYSCLK_CONF_REG . write_volatile( state. saved_sysclk_conf_reg) } ;
212+ unsafe { SYSTEM_CPU_PER_CONF_REG . write_volatile( state. saved_cpu_per_conf_reg) } ;
213+ }
214+ }
215+ }
216+ }
217+
218+ #[ cfg( any( not( feature = "max-cpu-frequency" ) , feature = "esp32c5" ) ) ]
219+ mod max_cpu_frequency {
220+ pub struct CpuSaveState { }
221+
222+ pub fn set_max_cpu_freq ( _: & mut CpuSaveState ) { }
223+ pub fn restore_max_cpu_freq ( _: & mut CpuSaveState ) { }
224+ }
225+
226+ use max_cpu_frequency:: * ;
227+
228+ struct FlasherState {
229+ inited : u32 ,
230+ saved_cpu_state : CpuSaveState ,
231+ decompressor : Decompressor ,
232+ }
233+
122234const INITED_MAGIC : u32 = 0xAAC0FFEE ;
123- const INITED : * mut u32 = STATE_ADDR as * mut u32 ;
124- const DECOMPRESSOR : * mut Decompressor = ( STATE_ADDR + 4 ) as * mut Decompressor ;
235+ const STATE_OBJ : * mut FlasherState = STATE_ADDR as * mut FlasherState ;
236+
237+ fn state ( ) -> & ' static mut FlasherState {
238+ unsafe { & mut * STATE_OBJ }
239+ }
125240
126241fn is_inited ( ) -> bool {
127- unsafe { * INITED == INITED_MAGIC }
242+ state ( ) . inited == INITED_MAGIC
128243}
129244
130245/// Setup the device for the flashing process.
131246#[ no_mangle]
132247pub unsafe extern "C" fn Init_impl ( _adr : u32 , _clk : u32 , _fnc : u32 ) -> i32 {
133248 dprintln ! ( "INIT" ) ;
134249
250+ set_max_cpu_freq ( & mut state ( ) . saved_cpu_state ) ;
251+
135252 if flash:: attach ( ) == 0 {
136- * DECOMPRESSOR = Decompressor :: new ( ) ;
137- * INITED = INITED_MAGIC ;
253+ state ( ) . decompressor = Decompressor :: new ( ) ;
254+ state ( ) . inited = INITED_MAGIC ;
138255 0
139256 } else {
140257 1
@@ -175,7 +292,7 @@ pub unsafe extern "C" fn ProgramPage_impl(adr: u32, sz: u32, buf: *const u8) ->
175292
176293 let input = core:: slice:: from_raw_parts ( buf, sz as usize ) ;
177294
178- ( * DECOMPRESSOR ) . program ( adr, input)
295+ state ( ) . decompressor . program ( adr, input)
179296}
180297
181298#[ no_mangle]
@@ -193,7 +310,7 @@ pub unsafe extern "C" fn Verify_impl(adr: u32, sz: u32, buf: *const u8) -> i32 {
193310
194311 let input = core:: slice:: from_raw_parts ( buf, sz as usize ) ;
195312
196- ( * DECOMPRESSOR ) . verify ( adr, input)
313+ state ( ) . decompressor . verify ( adr, input)
197314}
198315
199316#[ no_mangle]
@@ -219,7 +336,8 @@ pub unsafe extern "C" fn UnInit_impl(fnc: u32) -> i32 {
219336 return ERROR_BASE_INTERNAL - 1 ;
220337 } ;
221338
222- * INITED = 0 ;
339+ restore_max_cpu_freq ( & mut state ( ) . saved_cpu_state ) ;
340+ state ( ) . inited = 0 ;
223341
224342 if fnc == 2 {
225343 // The flash ROM functions don't wait for the end of the last operation.
0 commit comments