1use core::cell::Cell;
10use core::ops::{Index, IndexMut};
11use kernel::deferred_call::{DeferredCall, DeferredCallClient};
12use kernel::hil;
13use kernel::utilities::cells::OptionalCell;
14use kernel::utilities::cells::TakeCell;
15use kernel::utilities::cells::VolatileCell;
16use kernel::utilities::registers::interfaces::{Readable, Writeable};
17use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
18use kernel::utilities::StaticRef;
19use kernel::ErrorCode;
20
21const NVMC_BASE: StaticRef<NvmcRegisters> =
22 unsafe { StaticRef::new(0x4001E400 as *const NvmcRegisters) };
23
24#[repr(C)]
25struct NvmcRegisters {
26 pub ready: ReadOnly<u32, Ready::Register>,
29 _reserved0: [u32; 4],
30 pub ready_next: ReadOnly<u32, Ready::Register>,
33 _reserved1: [u32; 59],
35 pub config: ReadWrite<u32, Configuration::Register>,
38 pub erasepage: ReadWrite<u32, ErasePage::Register>,
41 pub eraseall: ReadWrite<u32, EraseAll::Register>,
44 _reserved2: u32,
45 pub eraseuicr: ReadWrite<u32, EraseUicr::Register>,
48 _reserved3: [u32; 10],
50 pub icachecnf: ReadWrite<u32, CacheConfiguration::Register>,
53 _reserved4: u32,
55 pub ihit: ReadWrite<u32, CacheHit::Register>,
58 pub imiss: ReadWrite<u32, CacheMiss::Register>,
61}
62
63register_bitfields! [u32,
64 Ready [
66 READY OFFSET(0) NUMBITS(1) [
68 BUSY = 0,
70 READY = 1
72 ]
73 ],
74 Configuration [
76 WEN OFFSET(0) NUMBITS(2) [
81 Ren = 0,
83 Wen = 1,
85 Een = 2
87 ]
88 ],
89 ErasePage [
91 ERASEPAGE OFFSET(0) NUMBITS(32) []
93 ],
94 EraseAll [
96 ERASEALL OFFSET(0) NUMBITS(1) [
100 NOOPERATION = 0,
102 ERASE = 1
104 ]
105 ],
106 EraseUicr [
108 ERASEUICR OFFSET(0) NUMBITS(1) [
111 NOOPERATION = 0,
113 ERASE = 1
115 ]
116 ],
117 CacheConfiguration [
119 CACHEEN OFFSET(0) NUMBITS(1) [
121 DISABLED = 0,
123 ENABLED = 1
125 ],
126 CACHEPROFEN OFFSET(8) NUMBITS(1) [
128 DISABLED = 0,
130 ENABLED = 1
132 ]
133 ],
134 CacheHit [
136 HITS OFFSET(0) NUMBITS(32) []
138 ],
139 CacheMiss [
141 MISSES OFFSET(0) NUMBITS(32) []
143 ]
144];
145
146const PAGE_SIZE: usize = 4096;
147
148pub struct NrfPage(pub [u8; PAGE_SIZE]);
162
163impl Default for NrfPage {
164 fn default() -> Self {
165 Self([0; PAGE_SIZE])
166 }
167}
168impl NrfPage {
169 fn len(&self) -> usize {
170 self.0.len()
171 }
172}
173
174impl Index<usize> for NrfPage {
175 type Output = u8;
176
177 fn index(&self, idx: usize) -> &u8 {
178 &self.0[idx]
179 }
180}
181
182impl IndexMut<usize> for NrfPage {
183 fn index_mut(&mut self, idx: usize) -> &mut u8 {
184 &mut self.0[idx]
185 }
186}
187
188impl AsMut<[u8]> for NrfPage {
189 fn as_mut(&mut self) -> &mut [u8] {
190 &mut self.0
191 }
192}
193
194#[derive(Clone, Copy, PartialEq)]
196pub enum FlashState {
197 Ready, Read, Write, Erase, }
202
203pub struct Nvmc {
204 registers: StaticRef<NvmcRegisters>,
205 client: OptionalCell<&'static dyn hil::flash::Client<Nvmc>>,
206 buffer: TakeCell<'static, NrfPage>,
207 state: Cell<FlashState>,
208 deferred_call: DeferredCall,
209}
210
211impl Nvmc {
212 pub fn new() -> Self {
213 Self {
214 registers: NVMC_BASE,
215 client: OptionalCell::empty(),
216 buffer: TakeCell::empty(),
217 state: Cell::new(FlashState::Ready),
218 deferred_call: DeferredCall::new(),
219 }
220 }
221
222 pub fn configure_writeable(&self) {
224 self.registers.config.write(Configuration::WEN::Wen);
225 }
226
227 pub fn configure_eraseable(&self) {
228 self.registers.config.write(Configuration::WEN::Een);
229 }
230
231 pub fn erase_uicr(&self) {
232 self.registers.config.write(Configuration::WEN::Een);
233 while !self.is_ready() {}
234 self.registers
235 .erasepage
236 .write(ErasePage::ERASEPAGE.val(0x10001000));
237 while !self.is_ready() {}
238 }
239
240 pub fn is_ready(&self) -> bool {
242 self.registers.ready.is_set(Ready::READY)
243 }
244
245 pub fn handle_interrupt(&self) {
246 let state = self.state.get();
247 self.state.set(FlashState::Ready);
248
249 match state {
250 FlashState::Read => {
251 self.client.map(|client| {
252 self.buffer.take().map(|buffer| {
253 client.read_complete(buffer, Ok(()));
254 });
255 });
256 }
257 FlashState::Write => {
258 self.client.map(|client| {
259 self.buffer.take().map(|buffer| {
260 client.write_complete(buffer, Ok(()));
261 });
262 });
263 }
264 FlashState::Erase => {
265 self.client.map(|client| {
266 client.erase_complete(Ok(()));
267 });
268 }
269 _ => {}
270 }
271 }
272
273 fn is_page_blank(&self, page_number: usize) -> bool {
274 let address = (page_number * PAGE_SIZE) as *const u32;
275 for i in 0..(PAGE_SIZE / 4) {
276 if unsafe { core::ptr::read(address.add(i)) } != 0xFFFFFFFF {
277 return false;
278 }
279 }
280 true
281 }
282
283 fn erase_page_helper(&self, page_number: usize) {
284 self.registers.config.write(Configuration::WEN::Een);
286
287 self.registers
290 .erasepage
291 .write(ErasePage::ERASEPAGE.val((page_number * PAGE_SIZE) as u32));
292
293 while !self.registers.ready.is_set(Ready::READY) {}
296 }
297
298 fn read_range(
299 &self,
300 page_number: usize,
301 buffer: &'static mut NrfPage,
302 ) -> Result<(), (ErrorCode, &'static mut NrfPage)> {
303 let mut byte: *const u8 = (page_number * PAGE_SIZE) as *const u8;
305 unsafe {
306 for i in 0..buffer.len() {
307 buffer[i] = *byte;
308 byte = byte.offset(1);
309 }
310 }
311
312 self.buffer.replace(buffer);
314
315 self.state.set(FlashState::Read);
318 self.deferred_call.set();
319
320 Ok(())
321 }
322
323 fn write_page(
324 &self,
325 page_number: usize,
326 data: &'static mut NrfPage,
327 ) -> Result<(), (ErrorCode, &'static mut NrfPage)> {
328 if !self.is_page_blank(page_number) {
331 self.erase_page_helper(page_number);
332 }
333
334 self.registers.config.write(Configuration::WEN::Wen);
336
337 for i in (0..data.len()).step_by(4) {
338 let word: u32 = (data[i + 0] as u32) << 0
339 | (data[i + 1] as u32) << 8
340 | (data[i + 2] as u32) << 16
341 | (data[i + 3] as u32) << 24;
342
343 let address = ((page_number * PAGE_SIZE) + i) as u32;
344 let location = unsafe { &*(address as *const VolatileCell<u32>) };
345 location.set(word);
346 while !self.registers.ready.is_set(Ready::READY) {}
347 }
348
349 while !self.registers.ready.is_set(Ready::READY) {}
352
353 self.buffer.replace(data);
355
356 self.state.set(FlashState::Write);
359 self.deferred_call.set();
360
361 Ok(())
362 }
363
364 fn erase_page(&self, page_number: usize) -> Result<(), ErrorCode> {
365 if !self.is_page_blank(page_number) {
367 self.erase_page_helper(page_number);
368 }
369
370 self.state.set(FlashState::Erase);
373 self.deferred_call.set();
374
375 Ok(())
376 }
377}
378
379impl<C: hil::flash::Client<Self>> hil::flash::HasClient<'static, C> for Nvmc {
380 fn set_client(&self, client: &'static C) {
381 self.client.set(client);
382 }
383}
384
385impl hil::flash::Flash for Nvmc {
386 type Page = NrfPage;
387
388 fn read_page(
389 &self,
390 page_number: usize,
391 buf: &'static mut Self::Page,
392 ) -> Result<(), (ErrorCode, &'static mut Self::Page)> {
393 self.read_range(page_number, buf)
394 }
395
396 fn write_page(
397 &self,
398 page_number: usize,
399 buf: &'static mut Self::Page,
400 ) -> Result<(), (ErrorCode, &'static mut Self::Page)> {
401 self.write_page(page_number, buf)
402 }
403
404 fn erase_page(&self, page_number: usize) -> Result<(), ErrorCode> {
405 self.erase_page(page_number)
406 }
407}
408
409impl DeferredCallClient for Nvmc {
410 fn handle_deferred_call(&self) {
411 self.handle_interrupt();
412 }
413
414 fn register(&'static self) {
415 self.deferred_call.register(self);
416 }
417}