Skip to content

Commit 76c5bec

Browse files
authored
Merge pull request #24 from bugadani/fix-s3
S3: initialize memory to make sure an empty device can be flashed
2 parents c101501 + 333690c commit 76c5bec

File tree

2 files changed

+105
-2
lines changed

2 files changed

+105
-2
lines changed

ld/esp32s3.x

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,10 @@ PROVIDE( Enable_QMode = 0x40000d2c );
155155

156156

157157
/* Functions */
158-
ets_efuse_get_spiconfig = 0x40001f74;
158+
ets_efuse_get_spiconfig = 0x40001f74;
159+
ets_efuse_flash_octal_mode = 0x40002004;
160+
161+
/* Data (.data, .bss, .rodata) */
162+
PROVIDE( rom_spiflash_legacy_funcs = 0x3fceffe8 );
163+
PROVIDE( rom_spiflash_legacy_data = 0x3fceffe4 );
164+
PROVIDE( g_flash_guard_ops = 0x3fceffec );

src/flash.rs

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
46100
pub 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

Comments
 (0)