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 erase_page_helper(&self, page_number: usize) {
274 self.registers.config.write(Configuration::WEN::Een);
276
277 self.registers
280 .erasepage
281 .write(ErasePage::ERASEPAGE.val((page_number * PAGE_SIZE) as u32));
282
283 while !self.registers.ready.is_set(Ready::READY) {}
286 }
287
288 fn read_range(
289 &self,
290 page_number: usize,
291 buffer: &'static mut NrfPage,
292 ) -> Result<(), (ErrorCode, &'static mut NrfPage)> {
293 let mut byte: *const u8 = (page_number * PAGE_SIZE) as *const u8;
295 unsafe {
296 for i in 0..buffer.len() {
297 buffer[i] = *byte;
298 byte = byte.offset(1);
299 }
300 }
301
302 self.buffer.replace(buffer);
304
305 self.state.set(FlashState::Read);
308 self.deferred_call.set();
309
310 Ok(())
311 }
312
313 fn write_page(
314 &self,
315 page_number: usize,
316 data: &'static mut NrfPage,
317 ) -> Result<(), (ErrorCode, &'static mut NrfPage)> {
318 self.erase_page_helper(page_number);
320
321 self.registers.config.write(Configuration::WEN::Wen);
323
324 for i in (0..data.len()).step_by(4) {
325 let word: u32 = (data[i + 0] as u32) << 0
326 | (data[i + 1] as u32) << 8
327 | (data[i + 2] as u32) << 16
328 | (data[i + 3] as u32) << 24;
329
330 let address = ((page_number * PAGE_SIZE) + i) as u32;
331 let location = unsafe { &*(address as *const VolatileCell<u32>) };
332 location.set(word);
333 while !self.registers.ready.is_set(Ready::READY) {}
334 }
335
336 while !self.registers.ready.is_set(Ready::READY) {}
339
340 self.buffer.replace(data);
342
343 self.state.set(FlashState::Write);
346 self.deferred_call.set();
347
348 Ok(())
349 }
350
351 fn erase_page(&self, page_number: usize) -> Result<(), ErrorCode> {
352 self.erase_page_helper(page_number);
354
355 self.state.set(FlashState::Erase);
358 self.deferred_call.set();
359
360 Ok(())
361 }
362}
363
364impl<C: hil::flash::Client<Self>> hil::flash::HasClient<'static, C> for Nvmc {
365 fn set_client(&self, client: &'static C) {
366 self.client.set(client);
367 }
368}
369
370impl hil::flash::Flash for Nvmc {
371 type Page = NrfPage;
372
373 fn read_page(
374 &self,
375 page_number: usize,
376 buf: &'static mut Self::Page,
377 ) -> Result<(), (ErrorCode, &'static mut Self::Page)> {
378 self.read_range(page_number, buf)
379 }
380
381 fn write_page(
382 &self,
383 page_number: usize,
384 buf: &'static mut Self::Page,
385 ) -> Result<(), (ErrorCode, &'static mut Self::Page)> {
386 self.write_page(page_number, buf)
387 }
388
389 fn erase_page(&self, page_number: usize) -> Result<(), ErrorCode> {
390 self.erase_page(page_number)
391 }
392}
393
394impl DeferredCallClient for Nvmc {
395 fn handle_deferred_call(&self) {
396 self.handle_interrupt();
397 }
398
399 fn register(&'static self) {
400 self.deferred_call.register(self);
401 }
402}