Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `change_bus_frequency` is now available on `SpiDma` (#529)
- Fixed a bug where a GPIO interrupt could erroneously fire again causing the next `await` on that pin to instantly return `Poll::Ok` (#537)
- Set `vecbase` on core 1 (ESP32, ESP32-S3) (#536)
- ESP32-S3: Move PSRAM related function to RAM (#546)

### Changed
- Improve examples documentation (#533)
Expand Down
24 changes: 24 additions & 0 deletions esp-hal-common/src/soc/esp32s3/psram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ pub fn init_psram(_peripheral: impl crate::peripheral::Peripheral<P = crate::per

#[cfg(any(feature = "psram_2m", feature = "psram_4m", feature = "psram_8m"))]
pub(crate) mod utils {
use procmacros::ram;

// these should probably be configurable, relates to https://github.com/esp-rs/esp-hal/issues/42
// probably also the PSRAM size shouldn't get configured via features
const SPI_TIMING_CORE_CLOCK: SpiTimingConfigCoreClock =
Expand Down Expand Up @@ -152,6 +154,7 @@ pub(crate) mod utils {
}
}

#[ram]
pub(crate) fn psram_init() {
psram_gpio_config();
psram_set_cs_timing();
Expand Down Expand Up @@ -261,6 +264,7 @@ pub(crate) mod utils {

// Configure PSRAM SPI0 phase related registers here according to the PSRAM chip
// requirement
#[ram]
fn config_psram_spi_phases() {
// Config CMD phase
clear_peri_reg_mask(SPI0_MEM_CACHE_SCTRL_REG, SPI_MEM_USR_SRAM_DIO_M); // disable dio mode for cache command
Expand Down Expand Up @@ -315,6 +319,7 @@ pub(crate) mod utils {
clear_peri_reg_mask(SPI0_MEM_MISC_REG, SPI_MEM_CS1_DIS_M); // ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
}

#[ram]
fn mspi_timing_psram_tuning() {
// currently we only support !SPI_TIMING_PSRAM_NEEDS_TUNING
// see https://github.com/espressif/esp-idf/blob/4e24516ee2731eb55687182d4e061b5b93a9e33f/components/esp_hw_support/mspi_timing_tuning.c#L391-L415
Expand All @@ -328,6 +333,7 @@ pub(crate) mod utils {
///
/// This function should always be called after `mspi_timing_flash_tuning`
/// or `calculate_best_flash_tuning_config`
#[ram]
fn mspi_timing_enter_high_speed_mode(control_spi1: bool) {
let core_clock: SpiTimingConfigCoreClock = get_mspi_core_clock();
let flash_div: u32 = get_flash_clock_divider();
Expand Down Expand Up @@ -357,6 +363,7 @@ pub(crate) mod utils {
// #endif
}

#[ram]
fn spi0_timing_config_set_core_clock(core_clock: SpiTimingConfigCoreClock) {
let reg_val = match core_clock {
SpiTimingConfigCoreClock::SpiTimingConfigCoreClock80m => 0,
Expand All @@ -368,6 +375,7 @@ pub(crate) mod utils {
set_peri_reg_bits(SPI0_MEM_CORE_CLK_SEL_REG, SPI_MEM_CORE_CLK_SEL, reg_val, 0);
}

#[ram]
fn spi0_timing_config_set_flash_clock(freqdiv: u32) {
if freqdiv == 1 {
write_peri_reg(SPI0_MEM_CLOCK_REG, SPI_MEM_CLK_EQU_SYSCLK);
Expand All @@ -379,6 +387,7 @@ pub(crate) mod utils {
}
}

#[ram]
fn spi1_timing_config_set_flash_clock(freqdiv: u32) {
if freqdiv == 1 {
write_peri_reg(SPI1_MEM_CLOCK_REG, SPI_MEM_CLK_EQU_SYSCLK);
Expand All @@ -390,6 +399,7 @@ pub(crate) mod utils {
}
}

#[ram]
fn spi0_timing_config_set_psram_clock(freqdiv: u32) {
if freqdiv == 1 {
write_peri_reg(SPI0_MEM_SRAM_CLK_REG, SPI_MEM_SCLK_EQU_SYSCLK);
Expand All @@ -401,10 +411,12 @@ pub(crate) mod utils {
}
}

#[ram]
fn get_mspi_core_clock() -> SpiTimingConfigCoreClock {
SPI_TIMING_CORE_CLOCK
}

#[ram]
fn get_flash_clock_divider() -> u32 {
match FLASH_FREQ {
FlashFreq::FlashFreq20m => SPI_TIMING_CORE_CLOCK.mhz() / 20,
Expand All @@ -414,6 +426,7 @@ pub(crate) mod utils {
}
}

#[ram]
fn get_psram_clock_divider() -> u32 {
match SPIRAM_SPEED {
SpiRamFreq::Freq40m => SPI_TIMING_CORE_CLOCK.mhz() / 40,
Expand All @@ -423,6 +436,7 @@ pub(crate) mod utils {
}

// send reset command to psram, in spi mode
#[ram]
fn psram_reset_mode_spi1() {
const PSRAM_RESET_EN: u16 = 0x66;
const PSRAM_RESET: u16 = 0x99;
Expand Down Expand Up @@ -466,6 +480,7 @@ pub(crate) mod utils {
PsramCmdSpi = 1,
}

#[ram]
fn psram_exec_cmd(
mode: CommandMode,
cmd: u16,
Expand Down Expand Up @@ -530,6 +545,7 @@ pub(crate) mod utils {
}
}

#[ram]
fn _psram_exec_cmd(
cmd: u16,
cmd_bit_len: u16,
Expand Down Expand Up @@ -578,6 +594,7 @@ pub(crate) mod utils {
}
}

#[ram]
fn psram_set_op_mode(mode: CommandMode) {
extern "C" {
fn esp_rom_spi_set_op_mode(spi: u32, mode: u32);
Expand All @@ -601,6 +618,7 @@ pub(crate) mod utils {
}

/// Enter QPI mode
#[ram]
fn psram_enable_qio_mode_spi1() {
const PSRAM_ENTER_QMODE: u16 = 0x35;
const CS_PSRAM_SEL: u8 = 1 << 1;
Expand All @@ -621,6 +639,7 @@ pub(crate) mod utils {
);
}

#[ram]
fn psram_set_cs_timing() {
// SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time registers
// for PSRAM, so we only need to set SPI0 related registers here
Expand All @@ -642,6 +661,7 @@ pub(crate) mod utils {
);
}

#[ram]
fn psram_gpio_config() {
// CS1
let cs1_io: u8 = PSRAM_CS_IO;
Expand Down Expand Up @@ -676,18 +696,21 @@ pub(crate) mod utils {
}
}

#[inline(always)]
fn clear_peri_reg_mask(reg: u32, mask: u32) {
unsafe {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() & !mask);
}
}

#[inline(always)]
fn set_peri_reg_mask(reg: u32, mask: u32) {
unsafe {
(reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() | mask);
}
}

#[inline(always)]
fn set_peri_reg_bits(reg: u32, bitmap: u32, value: u32, shift: u32) {
unsafe {
(reg as *mut u32).write_volatile(
Expand All @@ -697,6 +720,7 @@ pub(crate) mod utils {
}
}

#[inline(always)]
fn write_peri_reg(reg: u32, val: u32) {
unsafe {
(reg as *mut u32).write_volatile(val);
Expand Down