#![cfg_attr(docsrs, procmacros::doc_replace)]
#![doc = ""]
#![cfg_attr(
psram_octal_spi,
doc = concat!("The ", chip_pretty!(), " can use either Quad SPI or Octal SPI to interface with PSRAM.
`esp-hal` will try to automatically detect the best option, but manual configuration is also possible and more reliable.")
)]
#![doc = ""]
use core::ops::Range;
#[cfg_attr(esp32, path = "esp32.rs")]
#[cfg_attr(esp32s2, path = "esp32s2.rs")]
#[cfg_attr(esp32s3, path = "esp32s3.rs")]
#[cfg_attr(any(esp32c5, esp32c61), path = "esp32c5_c61.rs")]
pub(crate) mod implem;
pub use implem::*;
use portable_atomic::{AtomicUsize, Ordering};
use crate::peripherals::PSRAM;
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub enum PsramSize {
#[default]
AutoDetect,
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)
}
}
const EXTMEM_ORIGIN: usize = property!("psram.extmem_origin");
static MAPPED_PSRAM_START: AtomicUsize = AtomicUsize::new(0);
static MAPPED_PSRAM_END: AtomicUsize = AtomicUsize::new(0);
pub(crate) fn psram_range() -> Range<usize> {
let end = MAPPED_PSRAM_END.load(Ordering::Acquire);
let start = MAPPED_PSRAM_START.load(Ordering::Relaxed);
if end < start { 0..0 } else { start..end }
}
unsafe fn set_psram_range(range: Range<usize>) {
MAPPED_PSRAM_START.store(range.start, Ordering::Relaxed);
MAPPED_PSRAM_END.store(range.end, Ordering::Release);
}
pub struct Psram {
_peri: PSRAM<'static>,
}
impl Psram {
pub fn new(peri: PSRAM<'static>, mut config: PsramConfig) -> Self {
if init_psram(&mut config) {
let range = map_psram(config);
unsafe { set_psram_range(range) };
}
Self { _peri: peri }
}
pub fn raw_parts(&self) -> (*mut u8, usize) {
let range = psram_range();
(range.start as *mut u8, range.end - range.start)
}
}