6
6
#[ cfg( feature = "52840" ) ]
7
7
use nrf52840_hal as hal;
8
8
9
+ use core:: convert:: TryInto ;
9
10
use embedded_storage:: nor_flash:: NorFlash ;
10
11
use embedded_storage:: nor_flash:: ReadNorFlash ;
11
12
use hal:: nvmc:: Nvmc ;
13
+ use hal:: pac:: NVMC ;
14
+ use panic_probe as _;
12
15
use rtt_target:: { rprintln, rtt_init_print} ;
13
16
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 ;
15
21
extern "C" {
16
22
#[ link_name = "_config" ]
17
23
static mut CONFIG : [ u32 ; CONFIG_SIZE ] ;
18
24
}
19
25
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
21
29
22
30
#[ cortex_m_rt:: entry]
23
31
fn main ( ) -> ! {
@@ -28,23 +36,79 @@ fn main() -> ! {
28
36
#[ cfg( feature = "52840" ) ]
29
37
let mut nvmc = Nvmc :: new ( p. NVMC , unsafe { & mut CONFIG } ) ;
30
38
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 ) ;
37
40
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 ) ;
39
63
40
64
loop {
41
65
cortex_m:: asm:: wfe ( ) ;
42
66
}
43
67
}
44
68
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
+ ) ;
49
81
}
50
82
}
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