@@ -14,6 +14,7 @@ use nucleo_wl55jc_bsp::hal::{
1414} ;
1515use panic_probe as _;
1616use rand:: Rng as RngTrait ;
17+ use static_assertions as sa;
1718
1819const FREQ : u32 = 48_000_000 ;
1920const CYC_PER_MICRO : u32 = FREQ / 1000 / 1000 ;
@@ -39,6 +40,9 @@ mod tests {
3940 struct TestArgs {
4041 flash : pac:: FLASH ,
4142 page : Page ,
43+ // address to use for testing
44+ // incremented by the test after the address is programmed
45+ addr : usize ,
4246 rng : Rng ,
4347 }
4448
@@ -71,6 +75,7 @@ mod tests {
7175 TestArgs {
7276 flash : dp. FLASH ,
7377 page,
78+ addr : page. addr ( ) ,
7479 rng,
7580 }
7681 }
@@ -123,7 +128,7 @@ mod tests {
123128 let mut flash: Flash = Flash :: unlock ( & mut ta. flash ) ;
124129
125130 let start: u32 = DWT :: get_cycle_count ( ) ;
126- unwrap ! ( unsafe { flash. fast_program( BUF . as_ptr( ) , ta. page . addr( ) as * mut u64 ) } ) ;
131+ unwrap ! ( unsafe { flash. fast_program( BUF . as_ptr( ) , ta. addr as * mut u64 ) } ) ;
127132 let end: u32 = DWT :: get_cycle_count ( ) ;
128133 let elapsed: u32 = end. wrapping_sub ( start) ;
129134
@@ -134,35 +139,31 @@ mod tests {
134139
135140 for ( idx, & dw) in unsafe { BUF } . iter ( ) . enumerate ( ) {
136141 let expected: u64 = unsafe {
137- ( ta. page . addr ( ) as * const u64 )
142+ ( ta. addr as * const u64 )
138143 . offset ( unwrap ! ( idx. try_into( ) ) )
139144 . read_volatile ( )
140145 } ;
141146 defmt:: assert_eq!( dw, expected) ;
142147 }
148+
149+ // increment address by program size
150+ ta. addr += 256 ;
143151 }
144152
145153 #[ test]
146154 fn standard_program ( ta : & mut TestArgs ) {
147- let addr: usize = {
148- let unaligned_addr: usize = ta
149- . rng
150- . gen_range ( ta. page . addr ( ) + 256 ..ta. page . addr ( ) + Page :: SIZE - 1 ) ;
151- unaligned_addr - ( unaligned_addr % size_of :: < u64 > ( ) )
152- } ;
153-
154155 let data: u64 = ta. rng . gen_range ( 1 ..u64:: MAX - 1 ) ;
155156 defmt:: assert_ne!( data, u64 :: MAX ) ;
156157 defmt:: assert_ne!( data, 0 ) ;
157158
158- defmt:: info!( "Writing {:#016X} to {:#08X}" , data, addr) ;
159+ defmt:: info!( "Writing {:#016X} to {:#08X}" , data, ta . addr) ;
159160
160- defmt:: assert_eq!( unsafe { read_volatile( addr as * const u64 ) } , u64 :: MAX ) ;
161+ defmt:: assert_eq!( unsafe { read_volatile( ta . addr as * const u64 ) } , u64 :: MAX ) ;
161162
162163 let mut flash: Flash = Flash :: unlock ( & mut ta. flash ) ;
163164
164165 let start: u32 = DWT :: get_cycle_count ( ) ;
165- unwrap ! ( unsafe { flash. standard_program( & data, addr as * mut u64 ) } ) ;
166+ unwrap ! ( unsafe { flash. standard_program( & data, ta . addr as * mut u64 ) } ) ;
166167 let end: u32 = DWT :: get_cycle_count ( ) ;
167168 let elapsed: u32 = end. wrapping_sub ( start) ;
168169
@@ -171,6 +172,82 @@ mod tests {
171172 elapsed / CYC_PER_MICRO
172173 ) ;
173174
174- defmt:: assert_eq!( unsafe { read_volatile( addr as * const u64 ) } , data) ;
175+ defmt:: assert_eq!( unsafe { read_volatile( ta. addr as * const u64 ) } , data) ;
176+
177+ // increment address by program size
178+ ta. addr += size_of :: < u64 > ( ) ;
179+ }
180+
181+ #[ test]
182+ fn standard_program_generic_zero_size ( ta : & mut TestArgs ) {
183+ type ZeroSizeType = ( ) ;
184+
185+ sa:: assert_eq_size!( ZeroSizeType , [ u8 ; 0 ] ) ;
186+
187+ let my_zero_size_type: ZeroSizeType = ( ) ;
188+
189+ let mut flash: Flash = Flash :: unlock ( & mut ta. flash ) ;
190+
191+ // check flash is erased
192+ defmt:: assert_eq!( unsafe { read_volatile( ta. addr as * const u64 ) } , u64 :: MAX ) ;
193+
194+ unwrap ! ( unsafe {
195+ flash. standard_program_generic( & my_zero_size_type, ta. addr as * mut ZeroSizeType )
196+ } ) ;
197+
198+ // check flash was not modified
199+ defmt:: assert_eq!( unsafe { read_volatile( ta. addr as * const u64 ) } , u64 :: MAX ) ;
200+ }
201+
202+ #[ test]
203+ fn standard_program_generic ( ta : & mut TestArgs ) {
204+ #[ derive( defmt:: Format , PartialEq , Eq ) ]
205+ struct Keys {
206+ eui : [ u8 ; 8 ] ,
207+ key : [ u8 ; 16 ] ,
208+ }
209+
210+ #[ derive( defmt:: Format , PartialEq , Eq ) ]
211+ #[ repr( align( 8 ) ) ]
212+ struct TestStruct {
213+ connected : bool ,
214+ keys : Keys ,
215+ framecount_down : u32 ,
216+ framecount_up : u32 ,
217+ }
218+
219+ sa:: assert_eq_align!( TestStruct , u64 ) ;
220+
221+ let data = TestStruct {
222+ connected : false ,
223+ keys : Keys {
224+ eui : [ 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 ] ,
225+ key : [
226+ 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 ,
227+ 0x06 , 0x07 , 0x08 ,
228+ ] ,
229+ } ,
230+ framecount_up : 12 ,
231+ framecount_down : 120 ,
232+ } ;
233+
234+ defmt:: info!( "Writing {} to {:#08X}" , data, ta. addr) ;
235+
236+ let mut flash: Flash = Flash :: unlock ( & mut ta. flash ) ;
237+
238+ let start: u32 = DWT :: get_cycle_count ( ) ;
239+ unwrap ! ( unsafe { flash. standard_program_generic( & data, ta. addr as * mut TestStruct ) } ) ;
240+ let end: u32 = DWT :: get_cycle_count ( ) ;
241+ let elapsed: u32 = end. wrapping_sub ( start) ;
242+
243+ let size = core:: mem:: size_of :: < TestStruct > ( ) ;
244+
245+ defmt:: info!(
246+ "{}B program duration: {=u32:us} seconds" ,
247+ size,
248+ elapsed / CYC_PER_MICRO
249+ ) ;
250+
251+ defmt:: assert_eq!( unsafe { read_volatile( ta. addr as * const TestStruct ) } , data) ;
175252 }
176253}
0 commit comments