diff --git a/esp-hal/src/dma/buffers.rs b/esp-hal/src/dma/buffers.rs index 5cbe46749..721ae556b 100644 --- a/esp-hal/src/dma/buffers.rs +++ b/esp-hal/src/dma/buffers.rs @@ -4,9 +4,9 @@ use core::{ }; use super::*; -use crate::soc::{is_slice_in_dram, is_slice_in_psram}; +use crate::soc::is_slice_in_dram; #[cfg(psram_dma)] -use crate::soc::{is_valid_psram_address, is_valid_ram_address}; +use crate::soc::{is_slice_in_psram, is_valid_psram_address, is_valid_ram_address}; /// Error returned from Dma[Rx|Tx|RxTx]Buf operations. #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] @@ -321,7 +321,14 @@ impl BurstConfig { ) -> Result<(), DmaBufError> { // buffer can be either DRAM or PSRAM (if supported) let is_in_dram = is_slice_in_dram(buffer); - let is_in_psram = cfg!(psram_dma) && is_slice_in_psram(buffer); + cfg_if::cfg_if! { + if #[cfg(psram_dma)]{ + let is_in_psram = is_slice_in_psram(buffer); + } else { + let is_in_psram = false; + } + } + if !(is_in_dram || is_in_psram) { return Err(DmaBufError::UnsupportedMemoryRegion); } diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 2f4b02d6f..cd0308249 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1901,7 +1901,7 @@ where cfg_if::cfg_if! { if #[cfg(psram_dma)] { let mut uses_psram = false; - let psram_range = crate::soc::psram_range(); + let psram_range = crate::psram::psram_range(); for des in chain.descriptors.iter() { // we are forcing the DMA alignment to the cache line size // required when we are using dcache @@ -2167,7 +2167,7 @@ where cfg_if::cfg_if! { if #[cfg(psram_dma)] { let mut uses_psram = false; - let psram_range = crate::soc::psram_range(); + let psram_range = crate::psram::psram_range(); for des in chain.descriptors.iter() { // we are forcing the DMA alignment to the cache line size // required when we are using dcache diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index e54f7fdb6..f24815886 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -233,9 +233,6 @@ pub use self::soc::efuse; #[instability::unstable] #[cfg_attr(not(feature = "unstable"), allow(unused))] pub use self::soc::lp_core; -#[instability::unstable] -#[cfg(feature = "psram")] -pub use self::soc::psram; #[cfg(ulp_riscv_core)] #[instability::unstable] #[cfg_attr(not(feature = "unstable"), allow(unused))] @@ -334,6 +331,8 @@ unstable_module! { pub mod etm; #[cfg(soc_has_usb0)] pub mod otg_fs; + #[cfg(psram)] // DMA needs some things from here + pub mod psram; } unstable_driver! { diff --git a/esp-hal/src/soc/esp32/psram.rs b/esp-hal/src/psram/esp32.rs similarity index 97% rename from esp-hal/src/soc/esp32/psram.rs rename to esp-hal/src/psram/esp32.rs index 393760480..01ebff47f 100644 --- a/esp-hal/src/soc/esp32/psram.rs +++ b/esp-hal/src/psram/esp32.rs @@ -1,42 +1,4 @@ -#![cfg_attr(docsrs, procmacros::doc_replace)] -//! # PSRAM "virtual peripheral" driver (ESP32) -//! -//! ## Overview -//! -//! The `PSRAM` module provides support for accessing and controlling -//! the `Pseudo Static Random Access Memory (PSRAM)` on the `ESP32`. -//! -//! The `PSRAM` module enables users to interface with the `PSRAM` memory -//! present on the `ESP32` chip. `PSRAM` provides additional external memory to -//! supplement the internal memory of the `ESP32`, allowing for increased -//! storage capacity and improved performance in certain applications. -//! -//! ## Examples -//! -//! ### Quad PSRAM -//! This example shows how to use PSRAM as heap-memory via esp-alloc. -//! You need an ESP32 with at least 2 MB of PSRAM memory. -//! Notice that PSRAM example **must** be built in release mode! -//! -//! ```rust, ignore -//! # {before_snippet} -//! # extern crate alloc; -//! # use alloc::{string::String, vec::Vec}; -//! # -//! // Add PSRAM to the heap. -//! esp_alloc::psram_allocator!(&peripherals.PSRAM, esp_hal::psram); -//! -//! let mut large_vec: Vec = Vec::with_capacity(500 * 1024 / 4); -//! -//! for i in 0..(500 * 1024 / 4) { -//! large_vec.push((i & 0xff) as u32); -//! } -//! -//! let string = String::from("A string allocated in PSRAM"); -//! # {after_snippet} -//! ``` - -pub use crate::soc::psram_common::*; +use super::PsramSize; const EXTMEM_ORIGIN: usize = 0x3F800000; @@ -106,7 +68,7 @@ pub(crate) fn init_psram(config: PsramConfig) { } unsafe { - crate::soc::MAPPED_PSRAM.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get(); + super::MAPPED_PSRAM.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get(); } } diff --git a/esp-hal/src/soc/esp32s2/psram.rs b/esp-hal/src/psram/esp32s2.rs similarity index 93% rename from esp-hal/src/soc/esp32s2/psram.rs rename to esp-hal/src/psram/esp32s2.rs index 4d01d3790..423eae757 100644 --- a/esp-hal/src/soc/esp32s2/psram.rs +++ b/esp-hal/src/psram/esp32s2.rs @@ -1,45 +1,5 @@ -#![cfg_attr(docsrs, procmacros::doc_replace)] -//! # PSRAM "virtual peripheral" driver (ESP32-S2) -//! -//! ## Overview -//! -//! The `PSRAM` module provides support for accessing and controlling the -//! `Pseudo Static Random Access Memory (PSRAM)` on the `ESP32-S2`. -//! -//! The `PSRAM` module enables users to interface with the `PSRAM` memory -//! present on the `ESP32-S2` chip. `PSRAM` provides additional external memory -//! to supplement the internal memory of the `ESP32-S2`, allowing for increased -//! storage capacity and improved performance in certain applications. -//! -//! //! ## Examples -//! -//! ### Quad PSRAM -//! This example shows how to use PSRAM as heap-memory via esp-alloc. -//! You need an ESP32S2 with at least 2 MB of PSRAM memory. -//! Notice that PSRAM example **must** be built in release mode! -//! -//! ```rust, ignore -//! # {before_snippet} -//! # extern crate alloc; -//! # use alloc::{string::String, vec::Vec}; -//! # -//! // Add PSRAM to the heap. -//! esp_alloc::psram_allocator!(&peripherals.PSRAM, esp_hal::psram); -//! -//! init_psram_heap(start, size); -//! -//! let mut large_vec: Vec = Vec::with_capacity(500 * 1024 / 4); -//! -//! for i in 0..(500 * 1024 / 4) { -//! large_vec.push((i & 0xff) as u32); -//! } -//! -//! let string = String::from("A string allocated in PSRAM"); -//! # {after_snippet} -//! ``` - +use super::PsramSize; use crate::peripherals::{EXTMEM, SPI0, SPI1}; -pub use crate::soc::psram_common::*; const EXTMEM_ORIGIN: usize = 0x3f500000; @@ -167,7 +127,7 @@ pub(crate) fn init_psram(config: PsramConfig) { } unsafe { - crate::soc::MAPPED_PSRAM.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get(); + super::MAPPED_PSRAM.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get(); } } diff --git a/esp-hal/src/soc/esp32s3/psram.rs b/esp-hal/src/psram/esp32s3.rs similarity index 97% rename from esp-hal/src/soc/esp32s3/psram.rs rename to esp-hal/src/psram/esp32s3.rs index aaa8f939b..a47925de7 100644 --- a/esp-hal/src/soc/esp32s3/psram.rs +++ b/esp-hal/src/psram/esp32s3.rs @@ -1,49 +1,5 @@ -#![cfg_attr(docsrs, procmacros::doc_replace)] -//! # PSRAM "virtual peripheral" driver (ESP32-S3) -//! -//! ## Overview -//! -//! The `PSRAM` module provides support for accessing and controlling the -//! `Pseudo Static Random Access Memory (PSRAM)` on the `ESP32-S3`. -//! -//! The `PSRAM` module enables users to interface with the `PSRAM` memory -//! present on the `ESP32-S3` chip. `PSRAM` provides additional external memory -//! to supplement the internal memory of the `ESP32-S3`, allowing for increased -//! storage capacity and improved performance in certain applications. -//! -//! The mapped start address for PSRAM depends on the amount of mapped flash -//! memory. -//! -//! ## Examples -//! -//! ### Octal/Quad PSRAM -//! This example shows how to use PSRAM as heap-memory via esp-alloc. -//! You need an ESP32-S3 with at least 2 MB of PSRAM memory. -//! Either `Octal` or `Quad` PSRAM will be used, depending on the -//! setting of `ESP_HAL_CONFIG_PSRAM_MODE`. -//! -//! Notice that PSRAM example **must** be built in release mode! -//! -//! ```rust, ignore -//! # {before_snippet} -//! # extern crate alloc; -//! # use alloc::{string::String, vec::Vec}; -//! # -//! // Add PSRAM to the heap. -//! esp_alloc::psram_allocator!(&peripherals.PSRAM, esp_hal::psram); -//! -//! let mut large_vec: Vec = Vec::with_capacity(500 * 1024 / 4); -//! -//! for i in 0..(500 * 1024 / 4) { -//! large_vec.push((i & 0xff) as u32); -//! } -//! -//! let string = String::from("A string allocated in PSRAM"); -//! # {after_snippet} -//! ``` - +use super::PsramSize; use crate::peripherals::{EXTMEM, IO_MUX, SPI0, SPI1}; -pub use crate::soc::psram_common::*; const EXTMEM_ORIGIN: u32 = 0x3C000000; @@ -220,7 +176,7 @@ pub(crate) fn init_psram(config: PsramConfig) { }; unsafe { - crate::soc::MAPPED_PSRAM.memory_range = start as usize..start as usize + config.size.get(); + super::MAPPED_PSRAM.memory_range = start as usize..start as usize + config.size.get(); } } diff --git a/esp-hal/src/psram/mod.rs b/esp-hal/src/psram/mod.rs new file mode 100644 index 000000000..2c05426bc --- /dev/null +++ b/esp-hal/src/psram/mod.rs @@ -0,0 +1,117 @@ +#![cfg_attr(docsrs, procmacros::doc_replace( + "octal" => { + cfg(octal_psram) => "Either `Octal` or `Quad` PSRAM will be used, depending on the setting of `ESP_HAL_CONFIG_PSRAM_MODE`.", + _ => "" + } +))] +//! # PSRAM (Pseudo-static RAM, SPI RAM) driver +//! +//! ## Overview +//! +//! The `PSRAM` module provides support for accessing and controlling the +//! `Pseudo Static Random Access Memory (PSRAM)`. `PSRAM` provides additional +//! external memory to supplement the internal memory of the MCU, allowing for +//! increased storage capacity and improved performance in certain applications. +//! +//! The mapped start address for PSRAM depends on the amount of mapped flash +//! memory. +//! +//! ## Examples +//! +//! ### PSRAM as heap memory +//! +//! This example shows how to use PSRAM as heap-memory via esp-alloc. +//! You need an MCU with at least 2 MB of PSRAM memory. +//! # {octal} +//! +//! > The PSRAM example **must** be built in release mode! +//! +//! ```rust, ignore +//! # {before_snippet} +//! # extern crate alloc; +//! # use alloc::{string::String, vec::Vec}; +//! # +//! // Add PSRAM to the heap. +//! esp_alloc::psram_allocator!(&peripherals.PSRAM, esp_hal::psram); +//! +//! let mut large_vec: Vec = Vec::with_capacity(500 * 1024 / 4); +//! +//! for i in 0..(500 * 1024 / 4) { +//! large_vec.push((i & 0xff) as u32); +//! } +//! +//! let string = String::from("A string allocated in PSRAM"); +//! # {after_snippet} +//! ``` + +use core::ops::Range; + +#[cfg(feature = "psram")] +#[cfg_attr(esp32, path = "esp32.rs")] +#[cfg_attr(esp32s2, path = "esp32s2.rs")] +#[cfg_attr(esp32s3, path = "esp32s3.rs")] +pub(crate) mod implem; + +#[cfg(feature = "psram")] +pub use implem::*; + +/// Size of PSRAM +/// +/// [PsramSize::AutoDetect] will try to detect the size of PSRAM +#[derive(Copy, Clone, Debug, Default, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[instability::unstable] +pub enum PsramSize { + /// Detect PSRAM size + #[default] + AutoDetect, + /// A fixed PSRAM size + Size(usize), +} + +impl PsramSize { + #[cfg_attr(not(feature = "psram"), expect(unused))] + pub(crate) fn get(&self) -> usize { + match self { + PsramSize::AutoDetect => 0, + PsramSize::Size(size) => *size, + } + } + + #[cfg_attr(not(feature = "psram"), expect(unused))] + pub(crate) fn is_auto(&self) -> bool { + matches!(self, PsramSize::AutoDetect) + } +} + +/// Returns the address and size of the available in external memory. +#[cfg(feature = "psram")] +pub fn psram_raw_parts(_psram: &crate::peripherals::PSRAM<'_>) -> (*mut u8, usize) { + let range = psram_range(); + (range.start as *mut u8, range.end - range.start) +} + +// Using static mut should be fine since we are only writing to it once during +// initialization. As other tasks and interrupts are not running yet, the worst +// that can happen is, that the user creates a DMA buffer before initializing +// the HAL. This will access the PSRAM range, returning an empty range - which +// is, at that point, true. The user has no (safe) means to allocate in PSRAM +// before initializing the HAL. +#[cfg(feature = "psram")] +static mut MAPPED_PSRAM: MappedPsram = MappedPsram { memory_range: 0..0 }; + +pub(crate) fn psram_range() -> Range { + cfg_if::cfg_if! { + if #[cfg(feature = "psram")] { + #[allow(static_mut_refs)] + unsafe { MAPPED_PSRAM.memory_range.clone() } + } else { + 0..0 + } + } +} + +#[cfg(feature = "psram")] +pub(crate) struct MappedPsram { + memory_range: Range, +} diff --git a/esp-hal/src/soc/esp32/mod.rs b/esp-hal/src/soc/esp32/mod.rs index e843cb3bd..748c35d0c 100644 --- a/esp-hal/src/soc/esp32/mod.rs +++ b/esp-hal/src/soc/esp32/mod.rs @@ -7,8 +7,6 @@ crate::unstable_module! { pub mod efuse; - #[cfg(feature = "psram")] - pub mod psram; pub mod trng; } pub mod cpu_control; diff --git a/esp-hal/src/soc/esp32s2/mod.rs b/esp-hal/src/soc/esp32s2/mod.rs index f052b7e3a..f1efd73f7 100644 --- a/esp-hal/src/soc/esp32s2/mod.rs +++ b/esp-hal/src/soc/esp32s2/mod.rs @@ -11,8 +11,6 @@ crate::unstable_module! { pub mod efuse; - #[cfg(feature = "psram")] - pub mod psram; pub mod trng; pub mod ulp_core; } diff --git a/esp-hal/src/soc/esp32s3/mod.rs b/esp-hal/src/soc/esp32s3/mod.rs index 92027583b..39a8e4081 100644 --- a/esp-hal/src/soc/esp32s3/mod.rs +++ b/esp-hal/src/soc/esp32s3/mod.rs @@ -11,8 +11,6 @@ crate::unstable_module! { pub mod efuse; - #[cfg(feature = "psram")] - pub mod psram; pub mod trng; pub mod ulp_core; } diff --git a/esp-hal/src/soc/mod.rs b/esp-hal/src/soc/mod.rs index 96910ca37..1785d8bee 100644 --- a/esp-hal/src/soc/mod.rs +++ b/esp-hal/src/soc/mod.rs @@ -17,34 +17,6 @@ mod implementation; mod efuse_field; -#[cfg(feature = "psram")] -mod psram_common; - -// Using static mut should be fine since we are only writing to it once during -// initialization. As other tasks and interrupts are not running yet, the worst -// that can happen is, that the user creates a DMA buffer before initializing -// the HAL. This will access the PSRAM range, returning an empty range - which -// is, at that point, true. The user has no (safe) means to allocate in PSRAM -// before initializing the HAL. -#[cfg(feature = "psram")] -static mut MAPPED_PSRAM: MappedPsram = MappedPsram { memory_range: 0..0 }; - -pub(crate) fn psram_range() -> Range { - cfg_if::cfg_if! { - if #[cfg(feature = "psram")] { - #[allow(static_mut_refs)] - unsafe { MAPPED_PSRAM.memory_range.clone() } - } else { - 0..0 - } - } -} - -#[cfg(feature = "psram")] -pub struct MappedPsram { - memory_range: Range, -} - // Indicates the state of setting the mac address // 0 -- unset // 1 -- in the process of being set @@ -116,18 +88,28 @@ pub(crate) fn is_slice_in_dram(slice: &[T]) -> bool { } #[allow(unused)] +#[cfg(psram)] pub(crate) fn is_valid_psram_address(address: usize) -> bool { - addr_in_range(address, psram_range()) + addr_in_range(address, crate::psram::psram_range()) } #[allow(unused)] +#[cfg(psram)] pub(crate) fn is_slice_in_psram(slice: &[T]) -> bool { - slice_in_range(slice, psram_range()) + slice_in_range(slice, crate::psram::psram_range()) } #[allow(unused)] pub(crate) fn is_valid_memory_address(address: usize) -> bool { - is_valid_ram_address(address) || is_valid_psram_address(address) + if is_valid_ram_address(address) { + return true; + } + #[cfg(psram)] + if is_valid_psram_address(address) { + return true; + } + + false } fn slice_in_range(slice: &[T], range: Range) -> bool { diff --git a/esp-hal/src/soc/psram_common.rs b/esp-hal/src/soc/psram_common.rs deleted file mode 100644 index 8e052ba57..000000000 --- a/esp-hal/src/soc/psram_common.rs +++ /dev/null @@ -1,32 +0,0 @@ -/// Size of PSRAM -/// -/// [PsramSize::AutoDetect] will try to detect the size of PSRAM -#[derive(Copy, Clone, Debug, Default, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum PsramSize { - /// Detect PSRAM size - #[default] - AutoDetect, - /// A fixed PSRAM size - Size(usize), -} - -impl PsramSize { - pub(crate) fn get(&self) -> usize { - match self { - PsramSize::AutoDetect => 0, - PsramSize::Size(size) => *size, - } - } - - pub(crate) fn is_auto(&self) -> bool { - matches!(self, PsramSize::AutoDetect) - } -} - -/// Returns the address and size of the available in external memory. -#[cfg(feature = "psram")] -pub fn psram_raw_parts(_psram: &crate::peripherals::PSRAM<'_>) -> (*mut u8, usize) { - let range = crate::soc::psram_range(); - (range.start as *mut u8, range.end - range.start) -}