rp: add async flash

Implement an async flash mode using the XIP background best effort
read interface.  Only reads are actually async, write and erase remain
blocking.
This commit is contained in:
Derek Hageman
2023-07-25 15:54:33 -06:00
parent e3cc0d168c
commit 7ed9e29326
6 changed files with 254 additions and 26 deletions

View File

@ -7,7 +7,7 @@ use core::cell::RefCell;
use defmt_rtt as _;
use embassy_boot_rp::*;
use embassy_executor::Spawner;
use embassy_rp::flash::Flash;
use embassy_rp::flash::{self, Flash};
use embassy_rp::gpio::{Level, Output};
use embassy_rp::watchdog::Watchdog;
use embassy_sync::blocking_mutex::Mutex;
@ -34,7 +34,7 @@ async fn main(_s: Spawner) {
let mut watchdog = Watchdog::new(p.WATCHDOG);
watchdog.start(Duration::from_secs(8));
let flash: Flash<_, FLASH_SIZE> = Flash::new(p.FLASH);
let flash = Flash::<_, flash::Blocking, FLASH_SIZE>::new(p.FLASH);
let flash = Mutex::new(RefCell::new(flash));
let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash);

View File

@ -6,7 +6,7 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE};
use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE};
use embassy_rp::peripherals::FLASH;
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
@ -25,7 +25,7 @@ async fn main(_spawner: Spawner) {
// https://github.com/knurling-rs/defmt/pull/683
Timer::after(Duration::from_millis(10)).await;
let mut flash = embassy_rp::flash::Flash::<_, FLASH_SIZE>::new(p.FLASH);
let mut flash = embassy_rp::flash::Flash::<_, Async, FLASH_SIZE>::new(p.FLASH, p.DMA_CH0);
// Get JEDEC id
let jedec = flash.jedec_id().unwrap();
@ -40,10 +40,12 @@ async fn main(_spawner: Spawner) {
multiwrite_bytes(&mut flash, ERASE_SIZE as u32);
background_read(&mut flash, (ERASE_SIZE * 2) as u32).await;
loop {}
}
fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) {
fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) {
info!(">>>> [multiwrite_bytes]");
let mut read_buf = [0u8; ERASE_SIZE];
defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf));
@ -71,7 +73,7 @@ fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>,
}
}
fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) {
fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) {
info!(">>>> [erase_write_sector]");
let mut buf = [0u8; ERASE_SIZE];
defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf));
@ -99,3 +101,35 @@ fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE
defmt::panic!("unexpected");
}
}
async fn background_read(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) {
info!(">>>> [background_read]");
let mut buf = [0u32; 8];
defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await;
info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32);
info!("Contents start with {=u32:x}", buf[0]);
defmt::unwrap!(flash.erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32));
defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await;
info!("Contents after erase starts with {=u32:x}", buf[0]);
if buf.iter().any(|x| *x != 0xFFFFFFFF) {
defmt::panic!("unexpected");
}
for b in buf.iter_mut() {
*b = 0xDABA1234;
}
defmt::unwrap!(flash.write(ADDR_OFFSET + offset, unsafe {
core::slice::from_raw_parts(buf.as_ptr() as *const u8, buf.len() * 4)
}));
defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await;
info!("Contents after write starts with {=u32:x}", buf[0]);
if buf.iter().any(|x| *x != 0xDABA1234) {
defmt::panic!("unexpected");
}
}