Skip to content

Commit

Permalink
Auto-initialize PSRAM (#2546)
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani authored Nov 23, 2024
1 parent 09511c7 commit fe482bd
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 37 deletions.
4 changes: 2 additions & 2 deletions esp-alloc/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ macro_rules! heap_allocator {
/// ```
#[macro_export]
macro_rules! psram_allocator {
($peripheral:expr,$psram_module:path) => {{
($peripheral:expr, $psram_module:path) => {{
use $psram_module as _psram;
let (start, size) = _psram::init_psram($peripheral, _psram::PsramConfig::default());
let (start, size) = _psram::psram_raw_parts(&$peripheral);
unsafe {
$crate::HEAP.add_region($crate::HeapRegion::new(
start,
Expand Down
5 changes: 5 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `dma::{Channel, ChannelRx, ChannelTx}::set_priority` for GDMA devices (#2403)
- `esp_hal::asynch::AtomicWaker` that does not hold a global critical section (#2555)
- `esp_hal::sync::RawMutex` for embassy-sync. (#2555)
- ESP32-C6, H2, S3: Added `split` function to the `DmaChannel` trait. (#2526)
- Added PSRAM configuration to `esp_hal::Config` if `quad-psram` or `octal-psram` is enabled (#2546)
- Added `esp_hal::psram::psram_raw_parts` (#2546)

### Changed

Expand All @@ -31,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `dma::{Channel, ChannelRx, ChannelTx}::set_priority` for GDMA devices (#2403)
- `SystemTimer`s `Alarm`s are now type erased (#2576)
- `TimerGroup` `Timer`s are now type erased (#2581)
- PSRAM is now initialized automatically if `quad-psram` or `octal-psram` is enabled (#2546)

### Fixed

Expand All @@ -40,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The DMA channel objects no longer have `tx` and `rx` fields. (#2526)
- `SysTimerAlarms` has been removed, alarms are now part of the `SystemTimer` struct (#2576)
- `FrozenUnit`, `AnyUnit`, `SpecificUnit`, `SpecificComparator`, `AnyComparator` have been removed from `systimer` (#2576)
- `esp_hal::psram::psram_range` (#2546)

## [0.22.0] - 2024-11-20

Expand Down
19 changes: 19 additions & 0 deletions esp-hal/MIGRATING-0.22.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,22 @@ Timer group timers have been type erased.
- timg::Timer<timg::Timer0<crate::peripherals::TIMG0>, Blocking>
+ timg::Timer
```

## PSRAM is now initialized automatically

Calling `esp_hal::initialize` will now configure PSRAM if either the `quad-psram` or `octal-psram`
is enabled. To retrieve the address and size of the initialized external memory, use
`esp_hal::psram::psram_raw_parts`, which returns a pointer and a length.

```diff
-let peripherals = esp_hal::init(esp_hal::Config::default());
-let (start, size) = esp_hal::psram::init_psram(peripherals.PSRAM, psram_config);
+let peripherals = esp_hal::init({
+ let mut config = esp_hal::Config::default();
+ config.psram = psram_config;
+ config
+});
+let (start, size) = esp_hal::psram::psram_raw_parts(&peripherals.PSRAM, psram);
```

The usage of `esp_alloc::psram_allocator!` remains unchanged.
8 changes: 8 additions & 0 deletions esp-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,13 @@ use crate::{
pub struct Config {
/// The CPU clock configuration.
pub cpu_clock: CpuClock,

/// Enable watchdog timer(s).
pub watchdog: WatchdogConfig,

/// PSRAM configuration.
#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
pub psram: psram::PsramConfig,
}

/// Initialize the system.
Expand Down Expand Up @@ -572,5 +577,8 @@ pub fn init(config: Config) -> Peripherals {

crate::gpio::bind_default_interrupt_handler();

#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
crate::psram::init_psram(config.psram);

peripherals
}
10 changes: 4 additions & 6 deletions esp-hal/src/soc/esp32/psram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub struct PsramConfig {
/// Initializes the PSRAM memory on supported devices.
///
/// Returns the start of the mapped memory and the size
pub fn init_psram(_peripheral: crate::peripherals::PSRAM, config: PsramConfig) -> (*mut u8, usize) {
pub(crate) fn init_psram(config: PsramConfig) {
let mut config = config;

utils::psram_init(&config);
Expand Down Expand Up @@ -86,11 +86,9 @@ pub fn init_psram(_peripheral: crate::peripherals::PSRAM, config: PsramConfig) -
utils::s_mapping(EXTMEM_ORIGIN as u32, config.size.get() as u32);
}

crate::soc::MAPPED_PSRAM.with(|mapped_psram| {
mapped_psram.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get();
});

(EXTMEM_ORIGIN as *mut u8, config.size.get())
unsafe {
crate::soc::MAPPED_PSRAM.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get();
}
}

pub(crate) mod utils {
Expand Down
13 changes: 6 additions & 7 deletions esp-hal/src/soc/esp32s2/psram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub struct PsramConfig {
///
/// Returns the start of the mapped memory and the size
#[procmacros::ram]
pub fn init_psram(_peripheral: crate::peripherals::PSRAM, config: PsramConfig) -> (*mut u8, usize) {
pub(crate) fn init_psram(config: PsramConfig) {
let mut config = config;
utils::psram_init(&mut config);

Expand All @@ -65,7 +65,7 @@ pub fn init_psram(_peripheral: crate::peripherals::PSRAM, config: PsramConfig) -
///
/// [`sram0_layout`]: u32 the usage of first 8KB internal memory block,
/// can be CACHE_MEMORY_INVALID,
/// CACHE_MEMORY_ICACHE_LOW,
/// CACHE_MEMORY_ICACHE_LOW,
/// CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_DCACHE_LOW and
/// CACHE_MEMORY_DCACHE_HIGH
/// [`sram1_layout`]: the usage of second 8KB internal memory block,
Expand Down Expand Up @@ -141,11 +141,9 @@ pub fn init_psram(_peripheral: crate::peripherals::PSRAM, config: PsramConfig) -
});
}

crate::soc::MAPPED_PSRAM.with(|mapped_psram| {
mapped_psram.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get();
});

(EXTMEM_ORIGIN as *mut u8, config.size.get())
unsafe {
crate::soc::MAPPED_PSRAM.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get();
}
}

pub(crate) mod utils {
Expand Down Expand Up @@ -366,6 +364,7 @@ pub(crate) mod utils {
miso_bit_len: u32,
) {
#[repr(C)]
#[allow(non_camel_case_types)]
struct esp_rom_spi_cmd_t {
cmd: u16, // Command value
cmd_bit_len: u16, // Command byte length
Expand Down
10 changes: 4 additions & 6 deletions esp-hal/src/soc/esp32s3/psram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub struct PsramConfig {
///
/// Returns the start of the mapped memory and the size
#[procmacros::ram]
pub fn init_psram(_peripheral: crate::peripherals::PSRAM, config: PsramConfig) -> (*mut u8, usize) {
pub(crate) fn init_psram(config: PsramConfig) {
let mut config = config;
utils::psram_init(&mut config);

Expand Down Expand Up @@ -179,11 +179,9 @@ pub fn init_psram(_peripheral: crate::peripherals::PSRAM, config: PsramConfig) -
start
};

crate::soc::MAPPED_PSRAM.with(|mapped_psram| {
mapped_psram.memory_range = start as usize..start as usize + config.size.get();
});

(start as *mut u8, config.size.get())
unsafe {
crate::soc::MAPPED_PSRAM.memory_range = start as usize..start as usize + config.size.get();
}
}

#[cfg(feature = "quad-psram")]
Expand Down
26 changes: 15 additions & 11 deletions esp-hal/src/soc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use core::ops::Range;
use portable_atomic::{AtomicU8, Ordering};

pub use self::implementation::*;
#[cfg(psram)]
use crate::sync::Locked;

#[cfg_attr(esp32, path = "esp32/mod.rs")]
#[cfg_attr(esp32c2, path = "esp32c2/mod.rs")]
Expand All @@ -20,13 +18,19 @@ mod efuse_field;
#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
mod psram_common;

#[cfg(psram)]
static MAPPED_PSRAM: Locked<MappedPsram> = Locked::new(MappedPsram { memory_range: 0..0 });
// 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(any(feature = "quad-psram", feature = "octal-psram"))]
static mut MAPPED_PSRAM: MappedPsram = MappedPsram { memory_range: 0..0 };

fn psram_range() -> Range<usize> {
fn psram_range_internal() -> Range<usize> {
cfg_if::cfg_if! {
if #[cfg(psram)] {
MAPPED_PSRAM.with(|mapped_psram| mapped_psram.memory_range.clone())
if #[cfg(any(feature = "quad-psram", feature = "octal-psram"))] {
unsafe { MAPPED_PSRAM.memory_range.clone() }
} else {
0..0
}
Expand All @@ -35,9 +39,9 @@ fn psram_range() -> Range<usize> {

const DRAM: Range<usize> = self::constants::SOC_DRAM_LOW..self::constants::SOC_DRAM_HIGH;

#[cfg(psram)]
#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
pub struct MappedPsram {
memory_range: core::ops::Range<usize>,
memory_range: Range<usize>,
}

// Indicates the state of setting the mac address
Expand Down Expand Up @@ -108,12 +112,12 @@ pub(crate) fn is_slice_in_dram<T>(slice: &[T]) -> bool {

#[allow(unused)]
pub(crate) fn is_valid_psram_address(address: usize) -> bool {
addr_in_range(address, psram_range())
addr_in_range(address, psram_range_internal())
}

#[allow(unused)]
pub(crate) fn is_slice_in_psram<T>(slice: &[T]) -> bool {
slice_in_range(slice, psram_range())
slice_in_range(slice, psram_range_internal())
}

#[allow(unused)]
Expand Down
15 changes: 15 additions & 0 deletions esp-hal/src/soc/psram_common.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::ops::Range;

/// Size of PSRAM
///
/// [PsramSize::AutoDetect] will try to detect the size of PSRAM
Expand All @@ -23,3 +25,16 @@ impl PsramSize {
matches!(self, PsramSize::AutoDetect)
}
}

/// Returns the address range available in external memory.
#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
pub(crate) fn psram_range(_psram: &crate::peripherals::PSRAM) -> Range<usize> {
unsafe { super::MAPPED_PSRAM.memory_range.clone() }
}

/// Returns the address and size of the available in external memory.
#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
pub fn psram_raw_parts(psram: &crate::peripherals::PSRAM) -> (*mut u8, usize) {
let range = psram_range(psram);
(range.start as *mut u8, range.end - range.start)
}
6 changes: 3 additions & 3 deletions examples/src/bin/dma_extmem2mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ macro_rules! dma_alloc_buffer {
}};
}

fn init_heap(psram: esp_hal::peripherals::PSRAM) {
let (start, size) = esp_hal::psram::init_psram(psram, esp_hal::psram::PsramConfig::default());
fn init_heap(psram: &esp_hal::peripherals::PSRAM) {
let (start, size) = esp_hal::psram::psram_raw_parts(psram);
info!("init_heap: start: {:p}", start);
unsafe {
esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new(
Expand All @@ -59,8 +59,8 @@ fn main() -> ! {
esp_println::logger::init_logger(log::LevelFilter::Info);

let peripherals = esp_hal::init(esp_hal::Config::default());
init_heap(&peripherals.PSRAM);

init_heap(peripherals.PSRAM);
let delay = Delay::new();

let mut extram_buffer: &mut [u8] = dma_alloc_buffer!(DATA_SIZE, 64);
Expand Down
2 changes: 1 addition & 1 deletion examples/src/bin/psram_octal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn main() -> ! {
esp_println::logger::init_logger_from_env();
let peripherals = esp_hal::init(esp_hal::Config::default());

let (start, size) = psram::init_psram(peripherals.PSRAM, psram::PsramConfig::default());
let (start, size) = psram::psram_raw_parts(&peripherals.PSRAM);
init_psram_heap(start, size);

println!("Going to access PSRAM");
Expand Down
2 changes: 1 addition & 1 deletion examples/src/bin/psram_quad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn main() -> ! {
esp_println::logger::init_logger_from_env();
let peripherals = esp_hal::init(esp_hal::Config::default());

let (start, size) = psram::init_psram(peripherals.PSRAM, psram::PsramConfig::default());
let (start, size) = psram::psram_raw_parts(&peripherals.PSRAM);
init_psram_heap(start, size);

println!("Going to access PSRAM");
Expand Down

0 comments on commit fe482bd

Please sign in to comment.