mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-27 12:20:56 +00:00
Auto-initialize PSRAM (#2546)
This commit is contained in:
parent
09511c750a
commit
fe482bdd05
@ -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,
|
||||
|
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
@ -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 {
|
||||
|
@ -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);
|
||||
|
||||
@ -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,
|
||||
@ -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 {
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
||||
@ -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")]
|
||||
|
@ -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")]
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
@ -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)]
|
||||
|
@ -1,3 +1,5 @@
|
||||
use core::ops::Range;
|
||||
|
||||
/// Size of PSRAM
|
||||
///
|
||||
/// [PsramSize::AutoDetect] will try to detect the size of PSRAM
|
||||
@ -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)
|
||||
}
|
||||
|
@ -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(
|
||||
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user