66#[ cfg( feature = "52840" ) ]
77use nrf52840_hal as hal;
88
9+ use core:: convert:: TryInto ;
910use embedded_storage:: nor_flash:: NorFlash ;
1011use embedded_storage:: nor_flash:: ReadNorFlash ;
1112use hal:: nvmc:: Nvmc ;
13+ use hal:: pac:: NVMC ;
14+ use panic_probe as _;
1215use 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 ;
1521extern "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]
2331fn 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