mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-28 04:40:52 +00:00
Reorganize PSRAM (#3867)
This commit is contained in:
parent
bb50746e9c
commit
b2c31a1dac
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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! {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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
117
esp-hal/src/psram/mod.rs
Normal 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>,
|
||||
}
|
@ -7,8 +7,6 @@
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
#[cfg(feature = "psram")]
|
||||
pub mod psram;
|
||||
pub mod trng;
|
||||
}
|
||||
pub mod cpu_control;
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
#[cfg(feature = "psram")]
|
||||
pub mod psram;
|
||||
pub mod trng;
|
||||
pub mod ulp_core;
|
||||
}
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
crate::unstable_module! {
|
||||
pub mod efuse;
|
||||
#[cfg(feature = "psram")]
|
||||
pub mod psram;
|
||||
pub mod trng;
|
||||
pub mod ulp_core;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user