1use core::cell::Cell;
58use core::ops::{Index, IndexMut};
59use kernel::debug;
60use kernel::hil;
61use kernel::hil::time::ConvertTicks;
62use kernel::utilities::cells::TakeCell;
63use kernel::utilities::cells::{MapCell, OptionalCell};
64use kernel::utilities::leasable_buffer::SubSliceMut;
65use kernel::ErrorCode;
66
67pub const TX_BUF_LEN: usize = PAGE_SIZE as usize + 4;
68pub const RX_BUF_LEN: usize = PAGE_SIZE as usize + 4;
69
70const SPI_SPEED: u32 = 8000000;
71pub const SECTOR_SIZE: u32 = 4096;
72pub const PAGE_SIZE: u32 = 256;
73
74pub struct Mx25r6435fSector(pub [u8; SECTOR_SIZE as usize]);
86
87impl Mx25r6435fSector {
88 pub const fn new() -> Self {
89 Self([0; SECTOR_SIZE as usize])
90 }
91}
92
93impl Default for Mx25r6435fSector {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99impl Index<usize> for Mx25r6435fSector {
100 type Output = u8;
101
102 fn index(&self, idx: usize) -> &u8 {
103 &self.0[idx]
104 }
105}
106
107impl IndexMut<usize> for Mx25r6435fSector {
108 fn index_mut(&mut self, idx: usize) -> &mut u8 {
109 &mut self.0[idx]
110 }
111}
112
113impl AsMut<[u8]> for Mx25r6435fSector {
114 fn as_mut(&mut self) -> &mut [u8] {
115 &mut self.0
116 }
117}
118
119#[allow(dead_code)]
120enum Opcodes {
121 WREN = 0x06, WRDI = 0x04, SE = 0x20, READ = 0x03, PP = 0x02, RDID = 0x9f, RDSR = 0x05, }
129
130#[derive(Clone, Copy, PartialEq)]
131enum Operation {
132 Erase,
133 Write { sector_index: u32 },
134}
135
136#[derive(Clone, Copy, PartialEq)]
137enum State {
138 Idle,
139
140 ReadSector {
141 sector_index: u32,
142 page_index: u32,
143 },
144
145 EraseSectorWriteEnable {
146 sector_index: u32,
147 operation: Operation,
148 },
149 EraseSectorErase {
150 operation: Operation,
151 },
152 EraseSectorCheckDone {
153 operation: Operation,
154 },
155 EraseSectorDone,
156
157 WriteSectorWriteEnable {
158 sector_index: u32,
159 page_index: u32,
160 },
161 WriteSectorWrite {
162 sector_index: u32,
163 page_index: u32,
164 },
165 WriteSectorCheckDone {
166 sector_index: u32,
167 page_index: u32,
168 },
169 WriteSectorWaitDone {
170 sector_index: u32,
171 page_index: u32,
172 },
173
174 ReadId,
175}
176
177pub struct MX25R6435F<
178 'a,
179 S: hil::spi::SpiMasterDevice<'a> + 'a,
180 P: hil::gpio::Pin + 'a,
181 A: hil::time::Alarm<'a> + 'a,
182> {
183 spi: &'a S,
184 alarm: &'a A,
185 state: Cell<State>,
186 write_protect_pin: Option<&'a P>,
187 hold_pin: Option<&'a P>,
188 txbuffer: MapCell<SubSliceMut<'static, u8>>,
189 rxbuffer: MapCell<SubSliceMut<'static, u8>>,
190 client: OptionalCell<&'a dyn hil::flash::Client<MX25R6435F<'a, S, P, A>>>,
191 client_sector: TakeCell<'static, Mx25r6435fSector>,
192}
193
194impl<
195 'a,
196 S: hil::spi::SpiMasterDevice<'a> + 'a,
197 P: hil::gpio::Pin + 'a,
198 A: hil::time::Alarm<'a> + 'a,
199 > MX25R6435F<'a, S, P, A>
200{
201 pub fn new(
202 spi: &'a S,
203 alarm: &'a A,
204 txbuffer: &'static mut [u8],
205 rxbuffer: &'static mut [u8],
206 write_protect_pin: Option<&'a P>,
207 hold_pin: Option<&'a P>,
208 ) -> MX25R6435F<'a, S, P, A> {
209 MX25R6435F {
210 spi,
211 alarm,
212 state: Cell::new(State::Idle),
213 write_protect_pin,
214 hold_pin,
215 txbuffer: MapCell::new(txbuffer.into()),
216 rxbuffer: MapCell::new(rxbuffer.into()),
217 client: OptionalCell::empty(),
218 client_sector: TakeCell::empty(),
219 }
220 }
221
222 fn configure_spi(&self) -> Result<(), ErrorCode> {
224 self.hold_pin.map(|pin| {
225 pin.set();
226 });
227 self.spi.configure(
228 hil::spi::ClockPolarity::IdleLow,
229 hil::spi::ClockPhase::SampleLeading,
230 SPI_SPEED,
231 )
232 }
233
234 pub fn read_identification(&self) -> Result<(), ErrorCode> {
237 self.configure_spi()?;
238
239 self.txbuffer
240 .take()
241 .map_or(Err(ErrorCode::RESERVE), |mut txbuffer| {
242 self.rxbuffer
243 .take()
244 .map_or(Err(ErrorCode::RESERVE), move |rxbuffer| {
245 txbuffer.reset();
246 txbuffer[0] = Opcodes::RDID as u8;
247 txbuffer.slice(0..4);
248
249 self.state.set(State::ReadId);
250 if let Err((err, txbuffer, rxbuffer)) =
251 self.spi.read_write_bytes(txbuffer, Some(rxbuffer))
252 {
253 self.txbuffer.replace(txbuffer);
254 self.rxbuffer.replace(rxbuffer.unwrap());
255 Err(err)
256 } else {
257 Ok(())
258 }
259 })
260 })
261 }
262
263 fn enable_write(&self) -> Result<(), ErrorCode> {
264 self.write_protect_pin.map(|pin| {
265 pin.set();
266 });
267 self.txbuffer
268 .take()
269 .map_or(Err(ErrorCode::RESERVE), |mut txbuffer| {
270 txbuffer.reset();
271 txbuffer[0] = Opcodes::WREN as u8;
272 txbuffer.slice(0..1);
273 if let Err((err, txbuffer, _)) = self.spi.read_write_bytes(txbuffer, None) {
274 self.txbuffer.replace(txbuffer);
275 Err(err)
276 } else {
277 Ok(())
278 }
279 })
280 }
281
282 fn erase_sector(&self, sector_index: u32) -> Result<(), ErrorCode> {
283 self.configure_spi()?;
284 self.state.set(State::EraseSectorWriteEnable {
285 sector_index,
286 operation: Operation::Erase,
287 });
288 self.enable_write()
289 }
290
291 fn read_sector(
292 &self,
293 sector_index: u32,
294 sector: &'static mut Mx25r6435fSector,
295 ) -> Result<(), (ErrorCode, &'static mut Mx25r6435fSector)> {
296 match self.configure_spi() {
297 Ok(()) => {
298 let retval =
299 self.txbuffer
300 .take()
301 .map_or(Err(ErrorCode::RESERVE), |mut txbuffer| {
302 self.rxbuffer.take().map_or(
303 Err(ErrorCode::RESERVE),
304 move |mut rxbuffer| {
305 txbuffer.reset();
307 txbuffer[0] = Opcodes::READ as u8;
308 txbuffer[1] = ((sector_index * SECTOR_SIZE) >> 16) as u8;
309 txbuffer[2] = ((sector_index * SECTOR_SIZE) >> 8) as u8;
310 txbuffer[3] = ((sector_index * SECTOR_SIZE) >> 0) as u8;
311 txbuffer.slice(0..(PAGE_SIZE as usize + 4));
312
313 rxbuffer.reset();
314 rxbuffer.slice(0..(PAGE_SIZE as usize + 4));
315
316 self.state.set(State::ReadSector {
318 sector_index,
319 page_index: 0,
320 });
321 if let Err((err, txbuffer, rxbuffer)) =
322 self.spi.read_write_bytes(txbuffer, Some(rxbuffer))
323 {
324 self.txbuffer.replace(txbuffer);
325 self.rxbuffer.replace(rxbuffer.unwrap());
326 Err(err)
327 } else {
328 Ok(())
329 }
330 },
331 )
332 });
333
334 match retval {
335 Ok(()) => {
336 self.client_sector.replace(sector);
337 Ok(())
338 }
339 Err(ecode) => Err((ecode, sector)),
340 }
341 }
342 Err(error) => Err((error, sector)),
343 }
344 }
345
346 fn write_sector(
347 &self,
348 sector_index: u32,
349 sector: &'static mut Mx25r6435fSector,
350 ) -> Result<(), (ErrorCode, &'static mut Mx25r6435fSector)> {
351 match self.configure_spi() {
352 Ok(()) => {
353 self.state.set(State::EraseSectorWriteEnable {
354 sector_index,
355 operation: Operation::Write { sector_index },
356 });
357 let retval = self.enable_write();
358
359 match retval {
360 Ok(()) => {
361 self.client_sector.replace(sector);
362 Ok(())
363 }
364 Err(ecode) => Err((ecode, sector)),
365 }
366 }
367 Err(error) => Err((error, sector)),
368 }
369 }
370}
371
372impl<
373 'a,
374 S: hil::spi::SpiMasterDevice<'a> + 'a,
375 P: hil::gpio::Pin + 'a,
376 A: hil::time::Alarm<'a> + 'a,
377 > hil::spi::SpiMasterClient for MX25R6435F<'a, S, P, A>
378{
379 fn read_write_done(
380 &self,
381 mut write_buffer: SubSliceMut<'static, u8>,
382 read_buffer: Option<SubSliceMut<'static, u8>>,
383 read_write_status: Result<usize, ErrorCode>,
384 ) {
385 match self.state.get() {
386 State::ReadId => {
387 self.txbuffer.replace(write_buffer);
388 read_buffer.map(|read_buffer| {
389 debug!(
390 "id 0x{:02x}{:02x}{:02x}",
391 read_buffer[1], read_buffer[2], read_buffer[3]
392 );
393 self.rxbuffer.replace(read_buffer);
394 });
395 }
396 State::ReadSector {
397 sector_index,
398 page_index,
399 } => {
400 self.client_sector.take().map(|sector| {
401 read_buffer.map(move |read_buffer| {
402 for i in 0..(PAGE_SIZE as usize) {
404 sector[i + (page_index * PAGE_SIZE) as usize] = read_buffer[i + 4];
406 }
407
408 if (page_index + 1) * PAGE_SIZE == SECTOR_SIZE {
409 self.state.set(State::Idle);
411 self.txbuffer.replace(write_buffer);
412 self.rxbuffer.replace(read_buffer);
413
414 self.client.map(move |client| {
415 client.read_complete(
416 sector,
417 read_write_status
418 .and(Ok(()))
419 .or(Err(hil::flash::Error::FlashError)),
420 );
421 });
422 } else {
423 let address =
424 (sector_index * SECTOR_SIZE) + ((page_index + 1) * PAGE_SIZE);
425 write_buffer.reset();
426 write_buffer[0] = Opcodes::READ as u8;
427 write_buffer[1] = (address >> 16) as u8;
428 write_buffer[2] = (address >> 8) as u8;
429 write_buffer[3] = (address >> 0) as u8;
430 write_buffer.slice(0..(PAGE_SIZE as usize + 4));
431
432 self.state.set(State::ReadSector {
433 sector_index,
434 page_index: page_index + 1,
435 });
436 self.client_sector.replace(sector);
437
438 let _ = self.spi.read_write_bytes(write_buffer, Some(read_buffer));
440 }
441 });
442 });
443 }
444 State::EraseSectorWriteEnable {
445 sector_index,
446 operation,
447 } => {
448 self.state.set(State::EraseSectorErase { operation });
449
450 write_buffer.reset();
451 write_buffer[0] = Opcodes::SE as u8;
452 write_buffer[1] = ((sector_index * SECTOR_SIZE) >> 16) as u8;
453 write_buffer[2] = ((sector_index * SECTOR_SIZE) >> 8) as u8;
454 write_buffer[3] = ((sector_index * SECTOR_SIZE) >> 0) as u8;
455 write_buffer.slice(0..4);
456
457 let _ = self.spi.read_write_bytes(write_buffer, None);
459 }
460 State::EraseSectorErase { operation } => {
461 self.state.set(State::EraseSectorCheckDone { operation });
462 self.txbuffer.replace(write_buffer);
463 let delay = self.alarm.ticks_from_ms(58);
466 self.alarm.set_alarm(self.alarm.now(), delay);
467 }
468 State::EraseSectorCheckDone { operation } => {
469 read_buffer.map(move |read_buffer| {
470 let status = read_buffer[1];
471
472 if status & 0x01 == 0x01 {
474 let _ = self.spi.read_write_bytes(write_buffer, Some(read_buffer));
476 } else {
477 let next_state = match operation {
479 Operation::Erase => State::EraseSectorDone,
480 Operation::Write { sector_index } => State::WriteSectorWriteEnable {
481 sector_index,
482 page_index: 0,
483 },
484 };
485 self.state.set(next_state);
486 self.rxbuffer.replace(read_buffer);
487 self.read_write_done(write_buffer, None, read_write_status);
488 }
489 });
490 }
491 State::EraseSectorDone => {
492 self.state.set(State::Idle);
494 self.txbuffer.replace(write_buffer);
495 self.client.map(|client| {
496 client.erase_complete(
497 read_write_status
498 .and(Ok(()))
499 .or(Err(hil::flash::Error::FlashError)),
500 );
501 });
502 }
503 State::WriteSectorWriteEnable {
504 sector_index,
505 page_index,
506 } => {
507 if page_index * PAGE_SIZE == SECTOR_SIZE {
510 self.state.set(State::Idle);
512 self.txbuffer.replace(write_buffer);
513 self.client.map(|client| {
514 self.client_sector.take().map(|sector| {
515 client.write_complete(
516 sector,
517 read_write_status
518 .and(Ok(()))
519 .or(Err(hil::flash::Error::FlashError)),
520 );
521 });
522 });
523 } else {
524 self.state.set(State::WriteSectorWrite {
525 sector_index,
526 page_index,
527 });
528 write_buffer[0] = Opcodes::WREN as u8;
530 write_buffer.slice(0..1);
531 let _ = self.spi.read_write_bytes(write_buffer, None);
533 }
534 }
535 State::WriteSectorWrite {
536 sector_index,
537 page_index,
538 } => {
539 self.state.set(State::WriteSectorCheckDone {
541 sector_index,
542 page_index: page_index + 1,
543 });
544 let address = (sector_index * SECTOR_SIZE) + (page_index * PAGE_SIZE);
545 write_buffer.reset();
546 write_buffer.slice(0..(PAGE_SIZE as usize + 4));
547
548 write_buffer[0] = Opcodes::PP as u8;
549 write_buffer[1] = (address >> 16) as u8;
550 write_buffer[2] = (address >> 8) as u8;
551 write_buffer[3] = (address >> 0) as u8;
552
553 self.client_sector.map(|sector| {
554 for i in 0..(PAGE_SIZE as usize) {
555 write_buffer[i + 4] = sector[i + (page_index * PAGE_SIZE) as usize];
556 }
557 });
558
559 let _ = self.spi.read_write_bytes(write_buffer, None);
560 }
561 State::WriteSectorCheckDone {
562 sector_index,
563 page_index,
564 } => {
565 self.state.set(State::WriteSectorWaitDone {
566 sector_index,
567 page_index,
568 });
569 self.txbuffer.replace(write_buffer);
570 let delay = self.alarm.ticks_from_us(3200);
573 self.alarm.set_alarm(self.alarm.now(), delay);
574 }
575 State::WriteSectorWaitDone {
576 sector_index,
577 page_index,
578 } => {
579 read_buffer.map(move |mut read_buffer| {
580 let status = read_buffer[1];
581
582 read_buffer.slice(0..2);
583
584 if status & 0x01 == 0x01 {
586 let _ = self.spi.read_write_bytes(write_buffer, Some(read_buffer));
588 } else {
589 self.state.set(State::WriteSectorWriteEnable {
591 sector_index,
592 page_index,
593 });
594 self.rxbuffer.replace(read_buffer);
595 self.read_write_done(write_buffer, None, read_write_status);
596 }
597 });
598 }
599 _ => {}
600 }
601 }
602}
603
604impl<
605 'a,
606 S: hil::spi::SpiMasterDevice<'a> + 'a,
607 P: hil::gpio::Pin + 'a,
608 A: hil::time::Alarm<'a> + 'a,
609 > hil::time::AlarmClient for MX25R6435F<'a, S, P, A>
610{
611 fn alarm(&self) {
612 self.txbuffer.take().map(|mut write_buffer| {
615 self.rxbuffer.take().map(move |read_buffer| {
616 write_buffer.reset();
617 write_buffer.slice(0..2);
618 write_buffer[0] = Opcodes::RDSR as u8;
619 let _ = self.spi.read_write_bytes(write_buffer, Some(read_buffer));
620 });
621 });
622 }
623}
624
625impl<
626 'a,
627 S: hil::spi::SpiMasterDevice<'a> + 'a,
628 P: hil::gpio::Pin + 'a,
629 A: hil::time::Alarm<'a> + 'a,
630 C: hil::flash::Client<Self>,
631 > hil::flash::HasClient<'a, C> for MX25R6435F<'a, S, P, A>
632{
633 fn set_client(&self, client: &'a C) {
634 self.client.set(client);
635 }
636}
637
638impl<
639 'a,
640 S: hil::spi::SpiMasterDevice<'a> + 'a,
641 P: hil::gpio::Pin + 'a,
642 A: hil::time::Alarm<'a> + 'a,
643 > hil::flash::Flash for MX25R6435F<'a, S, P, A>
644{
645 type Page = Mx25r6435fSector;
646
647 fn read_page(
648 &self,
649 page_number: usize,
650 buf: &'static mut Self::Page,
651 ) -> Result<(), (ErrorCode, &'static mut Self::Page)> {
652 self.read_sector(page_number as u32, buf)
653 }
654
655 fn write_page(
656 &self,
657 page_number: usize,
658 buf: &'static mut Self::Page,
659 ) -> Result<(), (ErrorCode, &'static mut Self::Page)> {
660 self.write_sector(page_number as u32, buf)
661 }
662
663 fn erase_page(&self, page_number: usize) -> Result<(), ErrorCode> {
664 self.erase_sector(page_number as u32)
665 }
666}