diff --git a/CHANGELOG.md b/CHANGELOG.md index 50d0cc339f4..1c36b99eeff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ESP32-H2: Fix direct-boot feature - ESP32-C6: Support FOSC CLK calibration for ECO1+ chip revisions - Fixed CI by pinning the log crate to 0.4.18 (#600) +- ESP32-S3: Fix calculation of PSRAM start address ### Changed diff --git a/esp-hal-common/src/soc/esp32/psram.rs b/esp-hal-common/src/soc/esp32/psram.rs index d797c70cff2..f52021506c4 100644 --- a/esp-hal-common/src/soc/esp32/psram.rs +++ b/esp-hal-common/src/soc/esp32/psram.rs @@ -1,5 +1,9 @@ const PSRAM_VADDR: u32 = 0x3F800000; +pub fn psram_vaddr_start() -> usize { + unsafe { PSRAM_VADDR_START as usize } +} + cfg_if::cfg_if! { if #[cfg(feature = "psram_2m")] { const PSRAM_SIZE: u32 = 2; diff --git a/esp-hal-common/src/soc/esp32s2/psram.rs b/esp-hal-common/src/soc/esp32s2/psram.rs index 97370c296e3..0b0b2bf48bc 100644 --- a/esp-hal-common/src/soc/esp32s2/psram.rs +++ b/esp-hal-common/src/soc/esp32s2/psram.rs @@ -1,5 +1,9 @@ const PSRAM_VADDR: u32 = 0x3f500000; +pub fn psram_vaddr_start() -> usize { + unsafe { PSRAM_VADDR_START as usize } +} + cfg_if::cfg_if! { if #[cfg(feature = "psram_2m")] { const PSRAM_SIZE: u32 = 2; diff --git a/esp-hal-common/src/soc/esp32s3/psram.rs b/esp-hal-common/src/soc/esp32s3/psram.rs index 89de2730602..c27db3e698c 100644 --- a/esp-hal-common/src/soc/esp32s3/psram.rs +++ b/esp-hal-common/src/soc/esp32s3/psram.rs @@ -1,4 +1,8 @@ -const PSRAM_VADDR: u32 = 0x3C030000; +static mut PSRAM_VADDR: u32 = 0x3C000000; + +pub fn psram_vaddr_start() -> usize { + unsafe { PSRAM_VADDR as usize } +} cfg_if::cfg_if! { if #[cfg(feature = "psram_2m")] { @@ -14,8 +18,6 @@ cfg_if::cfg_if! { pub const PSRAM_BYTES: usize = PSRAM_SIZE as usize * 1024 * 1024; -pub const PSRAM_VADDR_START: usize = PSRAM_VADDR as usize; - /// Initialize PSRAM to be used for data. /// /// Currently only QSPI is supported. @@ -65,6 +67,25 @@ pub fn init_psram(_peripheral: impl crate::peripheral::Peripheral

i32; } unsafe { + const MMU_PAGE_SIZE: u32 = 0x10000; + const ICACHE_MMU_SIZE: usize = 0x800; + const FLASH_MMU_TABLE_SIZE: usize = ICACHE_MMU_SIZE / core::mem::size_of::(); + const MMU_INVALID: u32 = 1 << 14; + const DR_REG_MMU_TABLE: u32 = 0x600C5000; + + // calculate the PSRAM start address to map + let mut start = PSRAM_VADDR; + let mmu_table_ptr = DR_REG_MMU_TABLE as *const u32; + for i in 0..FLASH_MMU_TABLE_SIZE { + if mmu_table_ptr.add(i).read_volatile() != MMU_INVALID { + start += MMU_PAGE_SIZE; + } else { + break; + } + } + log::debug!("PSRAM start address = {:x}", start); + PSRAM_VADDR = start; + // Configure the mode of instruction cache : cache size, cache line size. rom_config_instruction_cache_mode( CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE, diff --git a/esp32s3-hal/examples/psram.rs b/esp32s3-hal/examples/psram.rs index 1d9d5ba7b06..b4afc775236 100644 --- a/esp32s3-hal/examples/psram.rs +++ b/esp32s3-hal/examples/psram.rs @@ -24,7 +24,7 @@ static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty(); fn init_psram_heap() { unsafe { ALLOCATOR.init( - soc::psram::PSRAM_VADDR_START as *mut u8, + soc::psram::psram_vaddr_start() as *mut u8, soc::psram::PSRAM_BYTES, ); }