@@ -11,6 +11,7 @@ use crate::pac::NVMC;
1111#[ cfg( any( feature = "9160" , feature = "5340-app" ) ) ]
1212use crate :: pac:: NVMC_NS as NVMC ;
1313
14+ use core:: convert:: TryInto ;
1415use embedded_storage:: nor_flash:: { NorFlash , ReadNorFlash } ;
1516
1617/// Interface to an NVMC instance.
@@ -97,45 +98,37 @@ where
9798{
9899 type Error = NvmcError ;
99100
100- const READ_SIZE : usize = 4 ;
101+ const READ_SIZE : usize = 1 ;
101102
102- fn read ( & mut self , offset : u32 , bytes : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
103- let offset = offset as usize ;
104- let bytes_len = bytes. len ( ) ;
105- let read_len = bytes_len + ( Self :: READ_SIZE - ( bytes_len % Self :: READ_SIZE ) ) ;
106- let target_offset = offset + read_len;
107- if offset % Self :: READ_SIZE == 0 && target_offset <= self . capacity ( ) {
108- self . wait_ready ( ) ;
109- let last_offset = target_offset - Self :: READ_SIZE ;
110- for offset in ( offset..last_offset) . step_by ( Self :: READ_SIZE ) {
111- let word = self . storage [ offset >> 2 ] ;
112- bytes[ offset] = ( word >> 24 ) as u8 ;
113- bytes[ offset + 1 ] = ( word >> 16 ) as u8 ;
114- bytes[ offset + 2 ] = ( word >> 8 ) as u8 ;
115- bytes[ offset + 3 ] = ( word >> 0 ) as u8 ;
116- }
117- let offset = last_offset;
118- let word = self . storage [ offset >> 2 ] ;
119- let mut bytes_offset = offset;
120- if bytes_offset < bytes_len {
121- bytes[ bytes_offset] = ( word >> 24 ) as u8 ;
122- bytes_offset += 1 ;
123- if bytes_offset < bytes_len {
124- bytes[ bytes_offset] = ( word >> 16 ) as u8 ;
125- bytes_offset += 1 ;
126- if bytes_offset < bytes_len {
127- bytes[ bytes_offset] = ( word >> 8 ) as u8 ;
128- bytes_offset += 1 ;
129- if bytes_offset < bytes_len {
130- bytes[ bytes_offset] = ( word >> 0 ) as u8 ;
131- }
132- }
133- }
103+ fn read ( & mut self , offset : u32 , mut bytes : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
104+ let mut offset = offset as usize ;
105+ if bytes. len ( ) > self . capacity ( ) || offset > self . capacity ( ) - bytes. len ( ) {
106+ return Err ( NvmcError :: OutOfBounds ) ;
107+ }
108+ self . wait_ready ( ) ;
109+ if offset & 3 != 0 {
110+ let word = self . storage [ offset >> 2 ] . to_ne_bytes ( ) ;
111+ let start = offset & 3 ;
112+ let length = 4 - start;
113+ if length > bytes. len ( ) {
114+ bytes. copy_from_slice ( & word[ start..start + bytes. len ( ) ] ) ;
115+ return Ok ( ( ) ) ;
134116 }
135- Ok ( ( ) )
136- } else {
137- Err ( NvmcError :: Unaligned )
117+ bytes[ ..length] . copy_from_slice ( & word[ start..] ) ;
118+ offset = offset + length;
119+ bytes = & mut bytes[ length..] ;
120+ }
121+ let mut word_offset = offset >> 2 ;
122+ let mut chunks = bytes. chunks_exact_mut ( 4 ) ;
123+ for bytes in & mut chunks {
124+ bytes. copy_from_slice ( & self . storage [ word_offset] . to_ne_bytes ( ) ) ;
125+ word_offset += 1 ;
126+ }
127+ let bytes = chunks. into_remainder ( ) ;
128+ if !bytes. is_empty ( ) {
129+ bytes. copy_from_slice ( & self . storage [ word_offset] . to_ne_bytes ( ) [ ..bytes. len ( ) ] ) ;
138130 }
131+ Ok ( ( ) )
139132 }
140133
141134 fn capacity ( & self ) -> usize {
@@ -152,34 +145,39 @@ where
152145 const ERASE_SIZE : usize = 4 * 1024 ;
153146
154147 fn erase ( & mut self , from : u32 , to : u32 ) -> Result < ( ) , Self :: Error > {
155- if from as usize % Self :: ERASE_SIZE == 0 && to as usize % Self :: ERASE_SIZE == 0 {
156- self . enable_erase ( ) ;
157- for offset in ( from..to) . step_by ( Self :: ERASE_SIZE ) {
158- self . erase_page ( offset as usize >> 2 ) ;
159- }
160- self . enable_read ( ) ;
161- Ok ( ( ) )
162- } else {
163- Err ( NvmcError :: Unaligned )
148+ let from = from as usize ;
149+ let to = to as usize ;
150+ if from > to || to > self . capacity ( ) {
151+ return Err ( NvmcError :: OutOfBounds ) ;
152+ }
153+ if from % Self :: ERASE_SIZE != 0 || to % Self :: ERASE_SIZE != 0 {
154+ return Err ( NvmcError :: Unaligned ) ;
155+ }
156+ self . enable_erase ( ) ;
157+ for offset in ( from..to) . step_by ( Self :: ERASE_SIZE ) {
158+ self . erase_page ( offset) ;
164159 }
160+ self . enable_read ( ) ;
161+ Ok ( ( ) )
165162 }
166163
167164 fn write ( & mut self , offset : u32 , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
168165 let offset = offset as usize ;
169- if offset % Self :: WRITE_SIZE == 0 && bytes. len ( ) % Self :: WRITE_SIZE == 0 {
170- self . enable_write ( ) ;
171- for offset in ( offset..( offset + bytes. len ( ) ) ) . step_by ( Self :: WRITE_SIZE ) {
172- let word = ( ( bytes[ offset] as u32 ) << 24 )
173- | ( ( bytes[ offset + 1 ] as u32 ) << 16 )
174- | ( ( bytes[ offset + 2 ] as u32 ) << 8 )
175- | ( ( bytes[ offset + 3 ] as u32 ) << 0 ) ;
176- self . write_word ( offset >> 2 , word) ;
177- }
178- self . enable_read ( ) ;
179- Ok ( ( ) )
180- } else {
181- Err ( NvmcError :: Unaligned )
166+ if bytes. len ( ) > self . capacity ( ) || offset as usize > self . capacity ( ) - bytes. len ( ) {
167+ return Err ( NvmcError :: OutOfBounds ) ;
168+ }
169+ if offset % Self :: WRITE_SIZE != 0 || bytes. len ( ) % Self :: WRITE_SIZE != 0 {
170+ return Err ( NvmcError :: Unaligned ) ;
171+ }
172+ self . enable_write ( ) ;
173+ let mut word_offset = offset >> 2 ;
174+ for bytes in bytes. chunks_exact ( 4 ) {
175+ // The unwrap is correct because chunks_exact always returns the correct size.
176+ self . write_word ( word_offset, u32:: from_ne_bytes ( bytes. try_into ( ) . unwrap ( ) ) ) ;
177+ word_offset += 1 ;
182178 }
179+ self . enable_read ( ) ;
180+ Ok ( ( ) )
183181 }
184182}
185183
@@ -199,4 +197,6 @@ mod sealed {
199197pub enum NvmcError {
200198 /// An operation was attempted on an unaligned boundary
201199 Unaligned ,
200+ /// An operation was attempted outside the boundaries
201+ OutOfBounds ,
202202}
0 commit comments