@@ -43,6 +43,60 @@ extern "C" {
4343 fn ets_efuse_get_spiconfig ( ) -> u32 ;
4444}
4545
46+ #[ cfg( feature = "esp32s3" ) ]
47+ #[ allow( non_camel_case_types) ]
48+ mod s3 {
49+
50+ type spi_flash_func_t = unsafe extern "C" fn ( ) ;
51+ type spi_flash_op_t = unsafe extern "C" fn ( ) -> i32 ;
52+ type spi_flash_erase_t = unsafe extern "C" fn ( u32 ) -> i32 ;
53+ type spi_flash_rd_t = unsafe extern "C" fn ( u32 , * mut ( ) , i32 ) -> i32 ;
54+ type spi_flash_wr_t = unsafe extern "C" fn ( u32 , * const u32 , i32 ) -> i32 ;
55+ type spi_flash_ewr_t = unsafe extern "C" fn ( u32 , * const ( ) , u32 ) -> i32 ;
56+ type spi_flash_wren_t = unsafe extern "C" fn ( * mut ( ) ) -> i32 ;
57+ type spi_flash_erase_area_t = unsafe extern "C" fn ( u32 , u32 ) -> i32 ;
58+
59+ #[ repr( C ) ]
60+ pub struct spiflash_legacy_funcs_t {
61+ pub pp_addr_bit_len : u8 ,
62+ pub se_addr_bit_len : u8 ,
63+ pub be_addr_bit_len : u8 ,
64+ pub rd_addr_bit_len : u8 ,
65+ pub read_sub_len : u32 ,
66+ pub write_sub_len : u32 ,
67+ pub unlock : Option < spi_flash_op_t > ,
68+ pub erase_sector : Option < spi_flash_erase_t > ,
69+ pub erase_block : Option < spi_flash_erase_t > ,
70+ pub read : Option < spi_flash_rd_t > ,
71+ pub write : Option < spi_flash_wr_t > ,
72+ pub encrypt_write : Option < spi_flash_ewr_t > ,
73+ pub check_sus : Option < spi_flash_func_t > ,
74+ pub wren : Option < spi_flash_wren_t > ,
75+ pub wait_idle : Option < spi_flash_op_t > ,
76+ pub erase_area : Option < spi_flash_erase_area_t > ,
77+ }
78+ }
79+
80+ #[ cfg( feature = "esp32s3" ) ]
81+ use s3:: * ;
82+
83+ #[ cfg( feature = "esp32s3" ) ]
84+ extern "C" {
85+
86+ static mut rom_spiflash_legacy_funcs: * const spiflash_legacy_funcs_t ;
87+ static mut rom_spiflash_legacy_data: * mut ( ) ;
88+
89+ fn ets_efuse_flash_octal_mode ( ) -> bool ;
90+
91+ fn esp_rom_opiflash_wait_idle ( ) -> i32 ;
92+ fn esp_rom_opiflash_erase_block_64k ( addr : u32 ) -> i32 ;
93+ fn esp_rom_opiflash_erase_sector ( addr : u32 ) -> i32 ;
94+ fn esp_rom_opiflash_read ( addr : u32 , buf : * mut ( ) , len : i32 ) -> i32 ;
95+ fn esp_rom_opiflash_write ( addr : u32 , data : * const u32 , len : i32 ) -> i32 ;
96+ fn esp_rom_opiflash_wren ( p : * mut ( ) ) -> i32 ;
97+ fn esp_rom_opiflash_erase_area ( start_addr : u32 , end_addr : u32 ) -> i32 ;
98+ }
99+
46100pub fn attach ( ) -> i32 {
47101 #[ cfg( any(
48102 feature = "esp32" ,
@@ -57,6 +111,22 @@ pub fn attach() -> i32 {
57111
58112 // TODO: raise CPU frequency
59113
114+ unsafe { esp_rom_spiflash_attach ( spiconfig, false ) } ;
115+
116+ #[ cfg( feature = "esp32s3" ) ]
117+ if unsafe { ets_efuse_flash_octal_mode ( ) } {
118+ init_ospi_funcs ( ) ;
119+ } else {
120+ // For some reason, the default pointers are not set on boot. I'm not sure if
121+ // probe-rs does something wrong, or the ROM bootloader doesn't initialize memory properly under some conditions.
122+ // Leaving these uninitialized ends up with a division by zero exception. These addresses have been mined out of
123+ // the ROM elf, these supposed to be the default values of these variables.
124+ unsafe {
125+ rom_spiflash_legacy_funcs = 0x3FCEF670 as _ ;
126+ rom_spiflash_legacy_data = 0x3FCEF6A4 as _ ;
127+ }
128+ }
129+
60130 let config_result = unsafe {
61131 esp_rom_spiflash_config_param (
62132 0 ,
@@ -69,7 +139,6 @@ pub fn attach() -> i32 {
69139 } ;
70140
71141 if config_result == 0 {
72- unsafe { esp_rom_spiflash_attach ( spiconfig, false ) } ;
73142 0
74143 } else {
75144 -1
@@ -115,3 +184,31 @@ pub fn wait_for_idle() -> i32 {
115184
116185 0
117186}
187+
188+ #[ cfg( feature = "esp32s3" ) ]
189+ fn init_ospi_funcs ( ) {
190+ static FUNCS : spiflash_legacy_funcs_t = spiflash_legacy_funcs_t {
191+ pp_addr_bit_len : 24 ,
192+ se_addr_bit_len : 24 ,
193+ be_addr_bit_len : 24 ,
194+ rd_addr_bit_len : 24 ,
195+ read_sub_len : 16 ,
196+ write_sub_len : 32 ,
197+ unlock : Some ( esp_rom_opiflash_wait_idle) ,
198+ erase_block : Some ( esp_rom_opiflash_erase_block_64k) ,
199+ erase_sector : Some ( esp_rom_opiflash_erase_sector) ,
200+ read : Some ( esp_rom_opiflash_read) ,
201+ write : Some ( esp_rom_opiflash_write) ,
202+ encrypt_write : None ,
203+ check_sus : None ,
204+ wait_idle : Some ( esp_rom_opiflash_wait_idle) ,
205+ wren : Some ( esp_rom_opiflash_wren) ,
206+ erase_area : Some ( esp_rom_opiflash_erase_area) ,
207+ } ;
208+
209+ unsafe {
210+ let funcs_iram = & raw const FUNCS ;
211+ rom_spiflash_legacy_funcs =
212+ ( ( funcs_iram as usize ) - 0x4038_0400 + 0x3FC9_0400 ) as * const spiflash_legacy_funcs_t ;
213+ }
214+ }
0 commit comments