mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 14:44:42 +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_export]
|
||||||
macro_rules! psram_allocator {
|
macro_rules! psram_allocator {
|
||||||
($peripheral:expr,$psram_module:path) => {{
|
($peripheral:expr, $psram_module:path) => {{
|
||||||
use $psram_module as _psram;
|
use $psram_module as _psram;
|
||||||
let (start, size) = _psram::init_psram($peripheral, _psram::PsramConfig::default());
|
let (start, size) = _psram::psram_raw_parts(&$peripheral);
|
||||||
unsafe {
|
unsafe {
|
||||||
$crate::HEAP.add_region($crate::HeapRegion::new(
|
$crate::HEAP.add_region($crate::HeapRegion::new(
|
||||||
start,
|
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)
|
- `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::asynch::AtomicWaker` that does not hold a global critical section (#2555)
|
||||||
- `esp_hal::sync::RawMutex` for embassy-sync. (#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
|
### 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)
|
- `dma::{Channel, ChannelRx, ChannelTx}::set_priority` for GDMA devices (#2403)
|
||||||
- `SystemTimer`s `Alarm`s are now type erased (#2576)
|
- `SystemTimer`s `Alarm`s are now type erased (#2576)
|
||||||
- `TimerGroup` `Timer`s are now type erased (#2581)
|
- `TimerGroup` `Timer`s are now type erased (#2581)
|
||||||
|
- PSRAM is now initialized automatically if `quad-psram` or `octal-psram` is enabled (#2546)
|
||||||
|
|
||||||
### Fixed
|
### 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)
|
- 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)
|
- `SysTimerAlarms` has been removed, alarms are now part of the `SystemTimer` struct (#2576)
|
||||||
- `FrozenUnit`, `AnyUnit`, `SpecificUnit`, `SpecificComparator`, `AnyComparator` have been removed from `systimer` (#2576)
|
- `FrozenUnit`, `AnyUnit`, `SpecificUnit`, `SpecificComparator`, `AnyComparator` have been removed from `systimer` (#2576)
|
||||||
|
- `esp_hal::psram::psram_range` (#2546)
|
||||||
|
|
||||||
## [0.22.0] - 2024-11-20
|
## [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<timg::Timer0<crate::peripherals::TIMG0>, Blocking>
|
||||||
+ timg::Timer
|
+ 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 {
|
pub struct Config {
|
||||||
/// The CPU clock configuration.
|
/// The CPU clock configuration.
|
||||||
pub cpu_clock: CpuClock,
|
pub cpu_clock: CpuClock,
|
||||||
|
|
||||||
/// Enable watchdog timer(s).
|
/// Enable watchdog timer(s).
|
||||||
pub watchdog: WatchdogConfig,
|
pub watchdog: WatchdogConfig,
|
||||||
|
|
||||||
|
/// PSRAM configuration.
|
||||||
|
#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
|
||||||
|
pub psram: psram::PsramConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the system.
|
/// Initialize the system.
|
||||||
@ -572,5 +577,8 @@ pub fn init(config: Config) -> Peripherals {
|
|||||||
|
|
||||||
crate::gpio::bind_default_interrupt_handler();
|
crate::gpio::bind_default_interrupt_handler();
|
||||||
|
|
||||||
|
#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
|
||||||
|
crate::psram::init_psram(config.psram);
|
||||||
|
|
||||||
peripherals
|
peripherals
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ pub struct PsramConfig {
|
|||||||
/// Initializes the PSRAM memory on supported devices.
|
/// Initializes the PSRAM memory on supported devices.
|
||||||
///
|
///
|
||||||
/// Returns the start of the mapped memory and the size
|
/// 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;
|
let mut config = config;
|
||||||
|
|
||||||
utils::psram_init(&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);
|
utils::s_mapping(EXTMEM_ORIGIN as u32, config.size.get() as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::soc::MAPPED_PSRAM.with(|mapped_psram| {
|
unsafe {
|
||||||
mapped_psram.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get();
|
crate::soc::MAPPED_PSRAM.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get();
|
||||||
});
|
}
|
||||||
|
|
||||||
(EXTMEM_ORIGIN as *mut u8, config.size.get())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod utils {
|
pub(crate) mod utils {
|
||||||
|
@ -41,7 +41,7 @@ pub struct PsramConfig {
|
|||||||
///
|
///
|
||||||
/// Returns the start of the mapped memory and the size
|
/// Returns the start of the mapped memory and the size
|
||||||
#[procmacros::ram]
|
#[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;
|
let mut config = config;
|
||||||
utils::psram_init(&mut 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,
|
/// [`sram0_layout`]: u32 the usage of first 8KB internal memory block,
|
||||||
/// can be CACHE_MEMORY_INVALID,
|
/// can be CACHE_MEMORY_INVALID,
|
||||||
/// CACHE_MEMORY_ICACHE_LOW,
|
/// CACHE_MEMORY_ICACHE_LOW,
|
||||||
/// CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_DCACHE_LOW and
|
/// CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_DCACHE_LOW and
|
||||||
/// CACHE_MEMORY_DCACHE_HIGH
|
/// CACHE_MEMORY_DCACHE_HIGH
|
||||||
/// [`sram1_layout`]: the usage of second 8KB internal memory block,
|
/// [`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| {
|
unsafe {
|
||||||
mapped_psram.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get();
|
crate::soc::MAPPED_PSRAM.memory_range = EXTMEM_ORIGIN..EXTMEM_ORIGIN + config.size.get();
|
||||||
});
|
}
|
||||||
|
|
||||||
(EXTMEM_ORIGIN as *mut u8, config.size.get())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod utils {
|
pub(crate) mod utils {
|
||||||
@ -366,6 +364,7 @@ pub(crate) mod utils {
|
|||||||
miso_bit_len: u32,
|
miso_bit_len: u32,
|
||||||
) {
|
) {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
struct esp_rom_spi_cmd_t {
|
struct esp_rom_spi_cmd_t {
|
||||||
cmd: u16, // Command value
|
cmd: u16, // Command value
|
||||||
cmd_bit_len: u16, // Command byte length
|
cmd_bit_len: u16, // Command byte length
|
||||||
|
@ -70,7 +70,7 @@ pub struct PsramConfig {
|
|||||||
///
|
///
|
||||||
/// Returns the start of the mapped memory and the size
|
/// Returns the start of the mapped memory and the size
|
||||||
#[procmacros::ram]
|
#[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;
|
let mut config = config;
|
||||||
utils::psram_init(&mut config);
|
utils::psram_init(&mut config);
|
||||||
|
|
||||||
@ -179,11 +179,9 @@ pub fn init_psram(_peripheral: crate::peripherals::PSRAM, config: PsramConfig) -
|
|||||||
start
|
start
|
||||||
};
|
};
|
||||||
|
|
||||||
crate::soc::MAPPED_PSRAM.with(|mapped_psram| {
|
unsafe {
|
||||||
mapped_psram.memory_range = start as usize..start as usize + config.size.get();
|
crate::soc::MAPPED_PSRAM.memory_range = start as usize..start as usize + config.size.get();
|
||||||
});
|
}
|
||||||
|
|
||||||
(start as *mut u8, config.size.get())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "quad-psram")]
|
#[cfg(feature = "quad-psram")]
|
||||||
|
@ -3,8 +3,6 @@ use core::ops::Range;
|
|||||||
use portable_atomic::{AtomicU8, Ordering};
|
use portable_atomic::{AtomicU8, Ordering};
|
||||||
|
|
||||||
pub use self::implementation::*;
|
pub use self::implementation::*;
|
||||||
#[cfg(psram)]
|
|
||||||
use crate::sync::Locked;
|
|
||||||
|
|
||||||
#[cfg_attr(esp32, path = "esp32/mod.rs")]
|
#[cfg_attr(esp32, path = "esp32/mod.rs")]
|
||||||
#[cfg_attr(esp32c2, path = "esp32c2/mod.rs")]
|
#[cfg_attr(esp32c2, path = "esp32c2/mod.rs")]
|
||||||
@ -20,13 +18,19 @@ mod efuse_field;
|
|||||||
#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
|
#[cfg(any(feature = "quad-psram", feature = "octal-psram"))]
|
||||||
mod psram_common;
|
mod psram_common;
|
||||||
|
|
||||||
#[cfg(psram)]
|
// Using static mut should be fine since we are only writing to it once during
|
||||||
static MAPPED_PSRAM: Locked<MappedPsram> = Locked::new(MappedPsram { memory_range: 0..0 });
|
// 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! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(psram)] {
|
if #[cfg(any(feature = "quad-psram", feature = "octal-psram"))] {
|
||||||
MAPPED_PSRAM.with(|mapped_psram| mapped_psram.memory_range.clone())
|
unsafe { MAPPED_PSRAM.memory_range.clone() }
|
||||||
} else {
|
} else {
|
||||||
0..0
|
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;
|
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 {
|
pub struct MappedPsram {
|
||||||
memory_range: core::ops::Range<usize>,
|
memory_range: Range<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indicates the state of setting the mac address
|
// 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)]
|
#[allow(unused)]
|
||||||
pub(crate) fn is_valid_psram_address(address: usize) -> bool {
|
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)]
|
#[allow(unused)]
|
||||||
pub(crate) fn is_slice_in_psram<T>(slice: &[T]) -> bool {
|
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)]
|
#[allow(unused)]
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use core::ops::Range;
|
||||||
|
|
||||||
/// Size of PSRAM
|
/// Size of PSRAM
|
||||||
///
|
///
|
||||||
/// [PsramSize::AutoDetect] will try to detect the size of PSRAM
|
/// [PsramSize::AutoDetect] will try to detect the size of PSRAM
|
||||||
@ -23,3 +25,16 @@ impl PsramSize {
|
|||||||
matches!(self, PsramSize::AutoDetect)
|
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) {
|
fn init_heap(psram: &esp_hal::peripherals::PSRAM) {
|
||||||
let (start, size) = esp_hal::psram::init_psram(psram, esp_hal::psram::PsramConfig::default());
|
let (start, size) = esp_hal::psram::psram_raw_parts(psram);
|
||||||
info!("init_heap: start: {:p}", start);
|
info!("init_heap: start: {:p}", start);
|
||||||
unsafe {
|
unsafe {
|
||||||
esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new(
|
esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new(
|
||||||
@ -59,8 +59,8 @@ fn main() -> ! {
|
|||||||
esp_println::logger::init_logger(log::LevelFilter::Info);
|
esp_println::logger::init_logger(log::LevelFilter::Info);
|
||||||
|
|
||||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||||
|
init_heap(&peripherals.PSRAM);
|
||||||
|
|
||||||
init_heap(peripherals.PSRAM);
|
|
||||||
let delay = Delay::new();
|
let delay = Delay::new();
|
||||||
|
|
||||||
let mut extram_buffer: &mut [u8] = dma_alloc_buffer!(DATA_SIZE, 64);
|
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();
|
esp_println::logger::init_logger_from_env();
|
||||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
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);
|
init_psram_heap(start, size);
|
||||||
|
|
||||||
println!("Going to access PSRAM");
|
println!("Going to access PSRAM");
|
||||||
|
@ -35,7 +35,7 @@ fn main() -> ! {
|
|||||||
esp_println::logger::init_logger_from_env();
|
esp_println::logger::init_logger_from_env();
|
||||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
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);
|
init_psram_heap(start, size);
|
||||||
|
|
||||||
println!("Going to access PSRAM");
|
println!("Going to access PSRAM");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user