Reorganize PSRAM (#3867)

This commit is contained in:
Dániel Buga 2025-07-28 09:24:14 +02:00 committed by GitHub
parent bb50746e9c
commit b2c31a1dac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 150 additions and 205 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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! {

View File

@ -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<u32> = 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();
}
}

View File

@ -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<u32> = 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();
}
}

View File

@ -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<u32> = 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();
}
}

117
esp-hal/src/psram/mod.rs Normal file
View File

@ -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<u32> = 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<usize> {
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<usize>,
}

View File

@ -7,8 +7,6 @@
crate::unstable_module! {
pub mod efuse;
#[cfg(feature = "psram")]
pub mod psram;
pub mod trng;
}
pub mod cpu_control;

View File

@ -11,8 +11,6 @@
crate::unstable_module! {
pub mod efuse;
#[cfg(feature = "psram")]
pub mod psram;
pub mod trng;
pub mod ulp_core;
}

View File

@ -11,8 +11,6 @@
crate::unstable_module! {
pub mod efuse;
#[cfg(feature = "psram")]
pub mod psram;
pub mod trng;
pub mod ulp_core;
}

View File

@ -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<usize> {
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<usize>,
}
// 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<T>(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<T>(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<T>(slice: &[T], range: Range<usize>) -> bool {

View File

@ -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)
}