Skip to content

Commit

Permalink
Add flash userland API and a simple test within example-app (#68)
Browse files Browse the repository at this point in the history
* Flash userspace async API and simple test inside example-app

* Cherry-pick specific files from "origin/pbhogaraju/mctp-userlib" branch to leverage the common API of subcribing ro, rw buffer and test framework for better consistency

* flash API test cleanup

* Enhance read/write API to support arbitrary length of request by splitting into chunk-based operations

* Remove debug prints that were not expected to merge.

* Address review comments and relocate flash API under `syscall` folder for consistency
  • Loading branch information
helloxiling authored Jan 10, 2025
1 parent 9077cb2 commit a7181f8
Show file tree
Hide file tree
Showing 8 changed files with 409 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ test-flash-storage-erase = []
test-mctp-ctrl-cmds = []
test-mctp-capsule-loopback = []
test-mctp-user-loopback = []
test-flash-usermode = []
2 changes: 2 additions & 0 deletions runtime/apps/example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ critical-section.workspace = true
embassy-executor.workspace = true
libtock_alarm.workspace = true
libtock_caliptra.workspace = true
libsyscall-caliptra.workspace = true
libtock_console.workspace = true
libtock_debug_panic.workspace = true
libtock_platform.workspace = true
Expand Down Expand Up @@ -38,3 +39,4 @@ test-flash-storage-erase = []
test-mctp-ctrl-cmds = []
test-mctp-capsule-loopback = []
test-mctp-user-loopback = []
test-flash-usermode = []
126 changes: 126 additions & 0 deletions runtime/apps/example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#![allow(static_mut_refs)]

use core::fmt::Write;
#[cfg(feature = "test-flash-usermode")]
use libsyscall_caliptra::flash::{driver_num as par_driver_num, FlashCapacity, SpiFlash};
use libtock::alarm::*;
use libtock_caliptra::mctp::{driver_num, Mctp};
use libtock_console::Console;
Expand Down Expand Up @@ -86,6 +88,34 @@ pub(crate) async fn async_main<S: Syscalls>() {
test_mctp_loopback::<S>().await;
}

#[cfg(feature = "test-flash-usermode")]
{
writeln!(console_writer, "flash usermode test starts").unwrap();
let mut user_r_buf: [u8; flash_test::BUF_LEN] = [0u8; flash_test::BUF_LEN];
// Fill the write buffer with a pattern
let user_w_buf: [u8; flash_test::BUF_LEN] = {
let mut buf = [0u8; flash_test::BUF_LEN];
for i in 0..buf.len() {
buf[i] = (i % 256) as u8;
}
buf
};

let mut test_cfg = flash_test::FlashTestConfig {
drv_num: par_driver_num::IMAGE_PARTITION,
expected_capacity: flash_test::EXPECTED_CAPACITY,
expected_chunk_size: flash_test::EXPECTED_CHUNK_SIZE,
e_offset: 0,
e_len: flash_test::BUF_LEN,
w_offset: 20,
w_len: 1000,
w_buf: &user_w_buf,
r_buf: &mut user_r_buf,
};
flash_test::simple_test::<S>(&mut test_cfg).await;
writeln!(console_writer, "flash usermode test succeeds").unwrap();
}

writeln!(console_writer, "app finished").unwrap();
}

Expand All @@ -112,6 +142,102 @@ async fn test_mctp_loopback<S: Syscalls>() {
}
}

#[cfg(feature = "test-flash-usermode")]
pub mod flash_test {
use super::*;
pub const BUF_LEN: usize = 1024;
pub const EXPECTED_CAPACITY: FlashCapacity = FlashCapacity(0x200_0000);
pub const EXPECTED_CHUNK_SIZE: usize = 512;

pub struct FlashTestConfig<'a> {
pub drv_num: u32,
pub expected_capacity: FlashCapacity,
pub expected_chunk_size: usize,
pub e_offset: usize,
pub e_len: usize,
pub w_offset: usize,
pub w_len: usize,
pub w_buf: &'a [u8],
pub r_buf: &'a mut [u8],
}

pub async fn simple_test<'a, S: Syscalls>(test_cfg: &'a mut FlashTestConfig<'a>) {
let flash_par = SpiFlash::<S>::new(test_cfg.drv_num);
assert_eq!(
flash_par.get_capacity().unwrap(),
test_cfg.expected_capacity
);
assert_eq!(
flash_par.get_chunk_size().unwrap(),
test_cfg.expected_chunk_size
);

let ret = flash_par.erase(test_cfg.e_offset, test_cfg.e_len).await;
assert_eq!(ret, Ok(()));

// Write test region partially
let ret = flash_par
.write(test_cfg.w_offset, test_cfg.w_len, test_cfg.w_buf as &[u8])
.await;
assert_eq!(ret, Ok(()));

// Read the written region
let ret = flash_par
.read(
test_cfg.w_offset,
test_cfg.w_len,
test_cfg.r_buf as &mut [u8],
)
.await;
assert_eq!(ret, Ok(()));

// Data compare read and write
for i in 0..test_cfg.w_len {
assert_eq!(
test_cfg.r_buf[i], test_cfg.w_buf[i],
"data mismatch at {}",
i
);
}

// Reset read buffer
test_cfg.r_buf.iter_mut().for_each(|x| *x = 0);

// Read whole test region
let ret = flash_par
.read(
test_cfg.e_offset,
test_cfg.e_len,
test_cfg.r_buf as &mut [u8],
)
.await;
assert_eq!(ret, Ok(()));

// Data integrity check
{
for i in 0..test_cfg.w_offset.min(test_cfg.r_buf.len()) {
assert_eq!(test_cfg.r_buf[i], 0xFF, "data mismatch at {}", i);
}
for i in
test_cfg.w_offset..(test_cfg.w_offset + test_cfg.w_len).min(test_cfg.r_buf.len())
{
assert_eq!(
test_cfg.r_buf[i],
test_cfg.w_buf[i - test_cfg.w_offset],
"data mismatch at {}",
i
);
}

for i in (test_cfg.w_offset + test_cfg.w_len).min(test_cfg.r_buf.len())
..test_cfg.e_len.min(test_cfg.r_buf.len())
{
assert_eq!(test_cfg.r_buf[i], 0xFF, "data mismatch at {}", i);
}
}
}
}

// -----------------------------------------------------------------------------
// Driver number and command IDs
// -----------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit a7181f8

Please sign in to comment.