7ed9e29326
Implement an async flash mode using the XIP background best effort read interface. Only reads are actually async, write and erase remain blocking.
135 lines
4.7 KiB
Rust
135 lines
4.7 KiB
Rust
//! This example test the flash connected to the RP2040 chip.
|
|
|
|
#![no_std]
|
|
#![no_main]
|
|
#![feature(type_alias_impl_trait)]
|
|
|
|
use defmt::*;
|
|
use embassy_executor::Spawner;
|
|
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 _};
|
|
|
|
const ADDR_OFFSET: u32 = 0x100000;
|
|
const FLASH_SIZE: usize = 2 * 1024 * 1024;
|
|
|
|
#[embassy_executor::main]
|
|
async fn main(_spawner: Spawner) {
|
|
let p = embassy_rp::init(Default::default());
|
|
info!("Hello World!");
|
|
|
|
// add some delay to give an attached debug probe time to parse the
|
|
// defmt RTT header. Reading that header might touch flash memory, which
|
|
// interferes with flash write operations.
|
|
// https://github.com/knurling-rs/defmt/pull/683
|
|
Timer::after(Duration::from_millis(10)).await;
|
|
|
|
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();
|
|
info!("jedec id: 0x{:x}", jedec);
|
|
|
|
// Get unique id
|
|
let mut uid = [0; 8];
|
|
flash.unique_id(&mut uid).unwrap();
|
|
info!("unique id: {:?}", uid);
|
|
|
|
erase_write_sector(&mut flash, 0x00);
|
|
|
|
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, 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));
|
|
|
|
info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32);
|
|
info!("Contents start with {=[u8]}", read_buf[0..4]);
|
|
|
|
defmt::unwrap!(flash.erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32));
|
|
|
|
defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf));
|
|
info!("Contents after erase starts with {=[u8]}", read_buf[0..4]);
|
|
if read_buf.iter().any(|x| *x != 0xFF) {
|
|
defmt::panic!("unexpected");
|
|
}
|
|
|
|
defmt::unwrap!(flash.write(ADDR_OFFSET + offset, &[0x01]));
|
|
defmt::unwrap!(flash.write(ADDR_OFFSET + offset + 1, &[0x02]));
|
|
defmt::unwrap!(flash.write(ADDR_OFFSET + offset + 2, &[0x03]));
|
|
defmt::unwrap!(flash.write(ADDR_OFFSET + offset + 3, &[0x04]));
|
|
|
|
defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf));
|
|
info!("Contents after write starts with {=[u8]}", read_buf[0..4]);
|
|
if &read_buf[0..4] != &[0x01, 0x02, 0x03, 0x04] {
|
|
defmt::panic!("unexpected");
|
|
}
|
|
}
|
|
|
|
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));
|
|
|
|
info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32);
|
|
info!("Contents start with {=[u8]}", buf[0..4]);
|
|
|
|
defmt::unwrap!(flash.erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32));
|
|
|
|
defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf));
|
|
info!("Contents after erase starts with {=[u8]}", buf[0..4]);
|
|
if buf.iter().any(|x| *x != 0xFF) {
|
|
defmt::panic!("unexpected");
|
|
}
|
|
|
|
for b in buf.iter_mut() {
|
|
*b = 0xDA;
|
|
}
|
|
|
|
defmt::unwrap!(flash.write(ADDR_OFFSET + offset, &buf));
|
|
|
|
defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf));
|
|
info!("Contents after write starts with {=[u8]}", buf[0..4]);
|
|
if buf.iter().any(|x| *x != 0xDA) {
|
|
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");
|
|
}
|
|
}
|