Skip to content

Commit d81b793

Browse files
committed
Improve coverage of NVMC example
1 parent bcd5c5d commit d81b793

File tree

3 files changed

+82
-16
lines changed

3 files changed

+82
-16
lines changed

examples/nvmc-demo/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ cortex-m = "0.7.3"
1212
cortex-m-rt = "0.7.0"
1313
embedded-storage = "0.2.0"
1414
rtt-target = {version = "0.2.0", features = ["cortex-m"] }
15+
panic-probe = { version = "0.3.0", features = ["print-rtt"] }
1516

1617
[dependencies.embedded-hal]
1718
version = "0.2.3"

examples/nvmc-demo/memory.x

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
MEMORY
22
{
3-
/* NOTE 1 K = 1 KiBi = 1024 bytes */
4-
FLASH : ORIGIN = 0x00000000, LENGTH = 1020K
5-
CONFIG : ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 4K /* 4K is the flash page size */
3+
/* NOTE 1 K = 1 KiB = 1024 bytes */
4+
FLASH : ORIGIN = 0x00000000, LENGTH = 1024K - 16K
5+
/* We use 4 pages of 4 KiB each, so 16 KiB */
6+
CONFIG : ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 16K
67
RAM : ORIGIN = 0x20000000, LENGTH = 256K
78
}
89

examples/nvmc-demo/src/main.rs

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,26 @@
66
#[cfg(feature = "52840")]
77
use nrf52840_hal as hal;
88

9+
use core::convert::TryInto;
910
use embedded_storage::nor_flash::NorFlash;
1011
use embedded_storage::nor_flash::ReadNorFlash;
1112
use hal::nvmc::Nvmc;
13+
use hal::pac::NVMC;
14+
use panic_probe as _;
1215
use rtt_target::{rprintln, rtt_init_print};
1316

14-
const CONFIG_SIZE: usize = 1024;
17+
// We use 4 pages to use non-zero offsets.
18+
const PAGE_SIZE: u32 = 4 * 1024;
19+
const LAST_PAGE: u32 = 3 * PAGE_SIZE;
20+
const CONFIG_SIZE: usize = 4 * PAGE_SIZE as usize / 4;
1521
extern "C" {
1622
#[link_name = "_config"]
1723
static mut CONFIG: [u32; CONFIG_SIZE];
1824
}
1925

20-
// To run this: `cargo embed --features "52840" --target thumbv7em-none-eabihf`
26+
// To run this example:
27+
// cargo build --features=52840 --target=thumbv7em-none-eabi && \
28+
// probe-run --chip nRF52840_xxAA ../../target/thumbv7em-none-eabi/debug/nvmc-demo
2129

2230
#[cortex_m_rt::entry]
2331
fn main() -> ! {
@@ -28,23 +36,79 @@ fn main() -> ! {
2836
#[cfg(feature = "52840")]
2937
let mut nvmc = Nvmc::new(p.NVMC, unsafe { &mut CONFIG });
3038

31-
assert!(nvmc.erase(0, CONFIG_SIZE as u32 * 4).is_ok());
32-
let write_buf: [u8; 4] = [1, 2, 3, 4];
33-
assert!(nvmc.write(0, &write_buf).is_ok());
34-
let mut read_buf = [0u8; 2];
35-
assert!(nvmc.read(0, &mut read_buf).is_ok());
36-
assert_eq!(read_buf, write_buf[0..2]);
39+
erase_if_needed(&mut nvmc, LAST_PAGE);
3740

38-
rprintln!("What was written to flash was read!");
41+
let mut write_buf: [u8; 32] = [0; 32];
42+
for (i, x) in write_buf.iter_mut().enumerate() {
43+
*x = i as u8;
44+
}
45+
rprintln!("Writing at {:#x}: {:02x?}", LAST_PAGE, write_buf);
46+
nvmc.write(LAST_PAGE, &write_buf).unwrap();
47+
48+
for i in 0..4 {
49+
compare_read::<11>(&mut nvmc, LAST_PAGE + i);
50+
compare_read::<10>(&mut nvmc, LAST_PAGE + i);
51+
compare_read::<9>(&mut nvmc, LAST_PAGE + i + 4);
52+
compare_read::<8>(&mut nvmc, LAST_PAGE + i + 4);
53+
compare_read::<7>(&mut nvmc, LAST_PAGE + i + 8);
54+
compare_read::<6>(&mut nvmc, LAST_PAGE + i + 8);
55+
compare_read::<5>(&mut nvmc, LAST_PAGE + i + 16);
56+
compare_read::<4>(&mut nvmc, LAST_PAGE + i + 16);
57+
compare_read::<3>(&mut nvmc, LAST_PAGE + i + 20);
58+
compare_read::<2>(&mut nvmc, LAST_PAGE + i + 20);
59+
compare_read::<1>(&mut nvmc, LAST_PAGE + i + 24);
60+
}
61+
62+
erase_if_needed(&mut nvmc, LAST_PAGE);
3963

4064
loop {
4165
cortex_m::asm::wfe();
4266
}
4367
}
4468

45-
#[panic_handler] // panicking behavior
46-
fn panic(_: &core::panic::PanicInfo) -> ! {
47-
loop {
48-
cortex_m::asm::bkpt();
69+
fn compare_read<const LENGTH: usize>(nvmc: &mut Nvmc<NVMC>, offset: u32) {
70+
let actual = read::<LENGTH>(nvmc, offset);
71+
let expected = unsafe { direct_read::<LENGTH>(offset) };
72+
if actual == expected {
73+
rprintln!("Read at {:#x}: {:02x?} as expected", offset, actual);
74+
} else {
75+
rprintln!(
76+
"Error: Read at {:#x}: {:02x?} instead of {:02x?}",
77+
offset,
78+
actual,
79+
expected,
80+
);
4981
}
5082
}
83+
84+
fn read<const LENGTH: usize>(nvmc: &mut Nvmc<NVMC>, offset: u32) -> [u8; LENGTH] {
85+
let mut buf = [0; LENGTH];
86+
nvmc.read(offset, &mut buf).unwrap();
87+
buf
88+
}
89+
90+
unsafe fn direct_read<const LENGTH: usize>(offset: u32) -> [u8; LENGTH] {
91+
let ptr = &CONFIG as *const u32 as *const u8;
92+
let slice = core::slice::from_raw_parts(ptr, CONFIG_SIZE * 4);
93+
slice[offset as usize..][..LENGTH].try_into().unwrap()
94+
}
95+
96+
fn erase_if_needed(nvmc: &mut Nvmc<NVMC>, offset: u32) {
97+
let mut page = [0; PAGE_SIZE as usize];
98+
nvmc.read(offset, &mut page).unwrap();
99+
if page_is_erased(&page) {
100+
return;
101+
}
102+
rprintln!("Erasing at {:#x}", offset);
103+
nvmc.erase(offset, offset + PAGE_SIZE).unwrap();
104+
nvmc.read(offset, &mut page).unwrap();
105+
if page_is_erased(&page) {
106+
rprintln!("The page was correctly erased.");
107+
} else {
108+
rprintln!("Error: The page was not correctly erased.");
109+
}
110+
}
111+
112+
fn page_is_erased(page: &[u8; PAGE_SIZE as usize]) -> bool {
113+
page.iter().all(|&x| x == 0xff)
114+
}

0 commit comments

Comments
 (0)