mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-26 20:00:32 +00:00
Improve PSRAM detection (#3554)
* Improve PSRAM detection * CHANGELOG.md * Just probe ESP32 PSRAM * Read device ID workaround * Exit QIO mode before trying to read the SPI RAM device id * Last try * Fix * Workaround faulty SVD
This commit is contained in:
parent
6ab240d7ff
commit
00565c39ed
@ -100,6 +100,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Fixed I2C `Timeout` errors experienced during high CPU load (#3458, #3555)
|
||||
- Fix a problem where reading/writing flash didn't work when using PSRAM on ESP32 (#3524)
|
||||
- Fixed `esp_hal::time::Instant::duration_since_epoch` (#3582)
|
||||
- Improve PSRAM size detection for the case when no PSRAM is present or unusable (#3554)
|
||||
|
||||
### Removed
|
||||
|
||||
|
@ -85,6 +85,8 @@ pub(crate) fn init_psram(config: PsramConfig) {
|
||||
utils::psram_init(&config);
|
||||
|
||||
if config.size.is_auto() {
|
||||
const MAX_MEM_SIZE: usize = 4 * 1024 * 1024;
|
||||
|
||||
// Reading the device-id turned out to not work as expected (some bits flipped
|
||||
// for unknown reason)
|
||||
//
|
||||
@ -92,33 +94,24 @@ pub(crate) fn init_psram(config: PsramConfig) {
|
||||
// probe if we can access top of PSRAM - if not we assume it's 2m
|
||||
//
|
||||
// This currently doesn't work as expected because of https://github.com/esp-rs/esp-hal/issues/2182
|
||||
utils::s_mapping(EXTMEM_ORIGIN as u32, 4 * 1024 * 1024);
|
||||
utils::s_mapping(EXTMEM_ORIGIN as u32, MAX_MEM_SIZE as u32);
|
||||
|
||||
let guessed_size = unsafe {
|
||||
let ptr = (EXTMEM_ORIGIN + 4 * 1024 * 1024 - 36 * 1024) as *mut u8;
|
||||
for i in 0..(36 * 1024) {
|
||||
ptr.add(i).write_volatile(0x7f);
|
||||
}
|
||||
|
||||
let ptr = EXTMEM_ORIGIN as *mut u8;
|
||||
for i in 0..(36 * 1024) {
|
||||
for i in (1023..MAX_MEM_SIZE).step_by(1024) {
|
||||
ptr.add(i).write_volatile(0x7f);
|
||||
}
|
||||
|
||||
let mut success = true;
|
||||
let ptr = (EXTMEM_ORIGIN + 4 * 1024 * 1024 - 36 * 1024) as *mut u8;
|
||||
for i in 0..(36 * 1024) {
|
||||
if ptr.add(i).read_volatile() != 0x7f {
|
||||
success = false;
|
||||
let mut last_correctly_read = 0;
|
||||
for i in (1023..MAX_MEM_SIZE).step_by(1024) {
|
||||
if ptr.add(i).read_volatile() == 0x7f {
|
||||
last_correctly_read = i;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if success {
|
||||
4 * 1024 * 1024
|
||||
} else {
|
||||
2 * 1024 * 1024
|
||||
}
|
||||
last_correctly_read + 1
|
||||
};
|
||||
|
||||
info!("Assuming {} bytes of PSRAM", guessed_size);
|
||||
|
@ -215,6 +215,8 @@ pub(crate) mod utils {
|
||||
psram_gpio_config();
|
||||
|
||||
if config.size.is_auto() {
|
||||
psram_disable_qio_mode();
|
||||
|
||||
// read chip id
|
||||
let mut dev_id = 0u32;
|
||||
psram_exec_cmd(
|
||||
@ -233,21 +235,25 @@ pub(crate) mod utils {
|
||||
);
|
||||
info!("chip id = {:x}", dev_id);
|
||||
|
||||
const PSRAM_ID_EID_S: u32 = 16;
|
||||
const PSRAM_ID_EID_M: u32 = 0xff;
|
||||
const PSRAM_EID_SIZE_M: u32 = 0x07;
|
||||
const PSRAM_EID_SIZE_S: u32 = 5;
|
||||
let size = if dev_id != 0xffffff {
|
||||
const PSRAM_ID_EID_S: u32 = 16;
|
||||
const PSRAM_ID_EID_M: u32 = 0xff;
|
||||
const PSRAM_EID_SIZE_M: u32 = 0x07;
|
||||
const PSRAM_EID_SIZE_S: u32 = 5;
|
||||
|
||||
let size_id = ((((dev_id) >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M) >> PSRAM_EID_SIZE_S)
|
||||
& PSRAM_EID_SIZE_M;
|
||||
let size_id = (((dev_id >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M) >> PSRAM_EID_SIZE_S)
|
||||
& PSRAM_EID_SIZE_M;
|
||||
|
||||
const PSRAM_EID_SIZE_32MBITS: u32 = 1;
|
||||
const PSRAM_EID_SIZE_64MBITS: u32 = 2;
|
||||
const PSRAM_EID_SIZE_32MBITS: u32 = 1;
|
||||
const PSRAM_EID_SIZE_64MBITS: u32 = 2;
|
||||
|
||||
let size = match size_id {
|
||||
PSRAM_EID_SIZE_64MBITS => 16 / 8 * 1024 * 1024,
|
||||
PSRAM_EID_SIZE_32MBITS => 16 / 8 * 1024 * 1024,
|
||||
_ => 16 / 8 * 1024 * 1024,
|
||||
match size_id {
|
||||
PSRAM_EID_SIZE_64MBITS => 8 * 1024 * 1024,
|
||||
PSRAM_EID_SIZE_32MBITS => 4 * 1024 * 1024,
|
||||
_ => 2 * 1024 * 1024,
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
info!("size is {}", size);
|
||||
@ -315,6 +321,27 @@ pub(crate) mod utils {
|
||||
);
|
||||
}
|
||||
|
||||
/// Exit QPI mode
|
||||
fn psram_disable_qio_mode() {
|
||||
const PSRAM_EXIT_QMODE: u16 = 0xF5;
|
||||
const CS_PSRAM_SEL: u8 = 1 << 1;
|
||||
|
||||
psram_exec_cmd(
|
||||
CommandMode::PsramCmdQpi,
|
||||
PSRAM_EXIT_QMODE,
|
||||
8, // command and command bit len
|
||||
0,
|
||||
0, // address and address bit len
|
||||
0, // dummy bit len
|
||||
core::ptr::null(),
|
||||
0, // tx data and tx bit len
|
||||
core::ptr::null_mut(),
|
||||
0, // rx data and rx bit len
|
||||
CS_PSRAM_SEL, // cs bit mask
|
||||
false, // whether is program/erase operation
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[allow(unused)]
|
||||
enum CommandMode {
|
||||
@ -451,7 +478,12 @@ pub(crate) mod utils {
|
||||
match mode {
|
||||
CommandMode::PsramCmdQpi => {
|
||||
esp_rom_spi_set_op_mode(1, ESP_ROM_SPIFLASH_QIO_MODE);
|
||||
SPI1::regs().ctrl().modify(|_, w| w.fcmd_quad().set_bit());
|
||||
// this should be `fcmd_quad` - apparently our ESP32-S2 SVD isn't correct for
|
||||
// SPI1 and SPI0. i.e. GP-SPI vs MEM-SPI
|
||||
//
|
||||
// TODO fix the SVD and change this back!
|
||||
// (i.e. in our SVD FCMD_QUAD is bit 9 while it should be bit 8)
|
||||
SPI1::regs().ctrl().modify(|_, w| w.fcmd_dual().set_bit());
|
||||
}
|
||||
CommandMode::PsramCmdSpi => {
|
||||
esp_rom_spi_set_op_mode(1, ESP_ROM_SPIFLASH_SLOWRD_MODE);
|
||||
|
@ -251,6 +251,8 @@ pub(crate) mod utils {
|
||||
psram_set_cs_timing();
|
||||
|
||||
if config.size.is_auto() {
|
||||
psram_disable_qio_mode_spi1();
|
||||
|
||||
// read chip id
|
||||
let mut dev_id = 0u32;
|
||||
psram_exec_cmd(
|
||||
@ -269,21 +271,25 @@ pub(crate) mod utils {
|
||||
);
|
||||
info!("chip id = {:x}", dev_id);
|
||||
|
||||
const PSRAM_ID_EID_S: u32 = 16;
|
||||
const PSRAM_ID_EID_M: u32 = 0xff;
|
||||
const PSRAM_EID_SIZE_M: u32 = 0x07;
|
||||
const PSRAM_EID_SIZE_S: u32 = 5;
|
||||
let size = if dev_id != 0xffffff {
|
||||
const PSRAM_ID_EID_S: u32 = 16;
|
||||
const PSRAM_ID_EID_M: u32 = 0xff;
|
||||
const PSRAM_EID_SIZE_M: u32 = 0x07;
|
||||
const PSRAM_EID_SIZE_S: u32 = 5;
|
||||
|
||||
let size_id = ((((dev_id) >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M) >> PSRAM_EID_SIZE_S)
|
||||
& PSRAM_EID_SIZE_M;
|
||||
let size_id = ((((dev_id) >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M) >> PSRAM_EID_SIZE_S)
|
||||
& PSRAM_EID_SIZE_M;
|
||||
|
||||
const PSRAM_EID_SIZE_32MBITS: u32 = 1;
|
||||
const PSRAM_EID_SIZE_64MBITS: u32 = 2;
|
||||
const PSRAM_EID_SIZE_32MBITS: u32 = 1;
|
||||
const PSRAM_EID_SIZE_64MBITS: u32 = 2;
|
||||
|
||||
let size = match size_id {
|
||||
PSRAM_EID_SIZE_64MBITS => 64 / 8 * 1024 * 1024,
|
||||
PSRAM_EID_SIZE_32MBITS => 32 / 8 * 1024 * 1024,
|
||||
_ => 16 / 8 * 1024 * 1024,
|
||||
match size_id {
|
||||
PSRAM_EID_SIZE_64MBITS => 64 / 8 * 1024 * 1024,
|
||||
PSRAM_EID_SIZE_32MBITS => 32 / 8 * 1024 * 1024,
|
||||
_ => 16 / 8 * 1024 * 1024,
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
info!("size is {}", size);
|
||||
@ -709,6 +715,28 @@ pub(crate) mod utils {
|
||||
}
|
||||
}
|
||||
|
||||
/// Exit QPI mode
|
||||
#[ram]
|
||||
fn psram_disable_qio_mode_spi1() {
|
||||
const PSRAM_EXIT_QMODE: u16 = 0xF5;
|
||||
const CS_PSRAM_SEL: u8 = 1 << 1;
|
||||
|
||||
psram_exec_cmd(
|
||||
CommandMode::PsramCmdQpi,
|
||||
PSRAM_EXIT_QMODE,
|
||||
8, // command and command bit len
|
||||
0,
|
||||
0, // address and address bit len
|
||||
0, // dummy bit len
|
||||
core::ptr::null(),
|
||||
0, // tx data and tx bit len
|
||||
core::ptr::null_mut(),
|
||||
0, // rx data and rx bit len
|
||||
CS_PSRAM_SEL, // cs bit mask
|
||||
false, // whether is program/erase operation
|
||||
);
|
||||
}
|
||||
|
||||
/// Enter QPI mode
|
||||
#[ram]
|
||||
fn psram_enable_qio_mode_spi1() {
|
||||
|
@ -41,6 +41,11 @@ fn main() -> ! {
|
||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||
|
||||
let (start, size) = psram::psram_raw_parts(&peripherals.PSRAM);
|
||||
|
||||
if size == 0 {
|
||||
panic!("No PSRAM detected");
|
||||
}
|
||||
|
||||
init_psram_heap(start, size);
|
||||
|
||||
println!("Going to access PSRAM");
|
||||
|
Loading…
x
Reference in New Issue
Block a user