1#![cfg_attr(not(feature = "std"), no_std)]
10
11extern crate alloc;
12use alloc::vec::Vec;
13
14use core::convert::TryInto;
15use core::time::Duration;
16#[cfg(feature = "std")]
17use indicatif::{ProgressBar, ProgressStyle};
18#[cfg(feature = "std")]
19use std::time::Instant;
20
21pub mod erase_plan;
22pub mod id;
23pub mod sfdp;
24pub mod sreg;
25
26pub use id::FlashID;
27pub use sfdp::{FlashParams, SFDPAddressBytes, SFDPEraseInst, SFDPStatus1Volatility, SFDPTiming};
28pub use sreg::{StatusRegister1, StatusRegister2, StatusRegister3};
29
30use erase_plan::ErasePlan;
31use sfdp::SFDPHeader;
32
33#[cfg_attr(feature = "std", derive(thiserror::Error, Debug))]
34pub enum Error {
35 #[cfg_attr(feature = "std", error("Mismatch during flash readback verification."))]
36 ReadbackError { address: u32, wrote: u8, read: u8 },
37 #[cfg_attr(feature = "std", error("Invalid manufacturer ID detected."))]
38 InvalidManufacturer,
39 #[cfg_attr(feature = "std", error("Invalid SFDP header."))]
40 InvalidSFDPHeader,
41 #[cfg_attr(feature = "std", error("Invalid parameter in SFDP parameter table."))]
42 InvalidSFDPParams,
43 #[cfg_attr(
44 feature = "std",
45 error("Address out of range for memory: 0x{address:08X}.")
46 )]
47 InvalidAddress { address: u32 },
48 #[cfg_attr(feature = "std", error("No supported reset instruction is available."))]
49 NoResetInstruction,
50 #[cfg_attr(feature = "std", error("No erase instruction has been specified."))]
51 NoEraseInstruction,
52
53 #[cfg(feature = "std")]
54 #[error(transparent)]
55 Access(#[from] anyhow::Error),
56
57 #[cfg(not(feature = "std"))]
58 Access,
59}
60
61pub type Result<T> = core::result::Result<T, Error>;
62
63pub trait FlashAccess {
81 type Error;
82
83 fn write(&mut self, data: &[u8]) -> core::result::Result<(), Self::Error> {
85 self.exchange(data)?;
87 Ok(())
88 }
89
90 fn exchange(&mut self, data: &[u8]) -> core::result::Result<Vec<u8>, Self::Error>;
94
95 fn delay(&mut self, duration: Duration) {
103 #[cfg(feature = "std")]
104 std::thread::sleep(duration);
105 }
106}
107
108pub struct Flash<'a, A: FlashAccess> {
112 access: &'a mut A,
113
114 id: Option<FlashID>,
116
117 params: Option<FlashParams>,
119
120 address_bytes: u8,
124
125 capacity: Option<usize>,
127
128 page_size: Option<usize>,
130
131 erase_size: Option<usize>,
133
134 erase_opcode: u8,
137}
138
139impl<'a, A: FlashAccess> Flash<'a, A>
140where
141 Error: From<<A as FlashAccess>::Error>,
142{
143 #[cfg(feature = "std")]
144 const DATA_PROGRESS_TPL: &'static str =
145 " {msg} [{bar:40.cyan/black}] {bytes}/{total_bytes} ({bytes_per_sec}; {eta_precise})";
146 #[cfg(feature = "std")]
147 const DATA_FINISHED_TPL: &'static str =
148 " {msg} [{bar:40.green/black}] {bytes}/{total_bytes} ({bytes_per_sec}; {eta_precise})";
149 #[cfg(feature = "std")]
150 const DATA_PROGRESS_CHARS: &'static str = "ββΈβ";
151
152 pub fn new(access: &'a mut A) -> Self {
154 Flash {
155 access,
156 id: None,
157 params: None,
158 address_bytes: 3,
159 capacity: None,
160 page_size: None,
161 erase_size: None,
162 erase_opcode: 0x20,
163 }
164 }
165
166 pub fn address_bytes(&self) -> u8 {
168 self.address_bytes
169 }
170
171 pub fn set_address_bytes(&mut self, n: u8) {
176 assert!(n >= 1, "set_address_bytes: n must be at least 1");
177 assert!(n <= 4, "set_address_bytes: n must not exceed 4");
178 self.address_bytes = n;
179 }
180
181 pub fn capacity(&self) -> Option<usize> {
183 self.capacity
184 }
185
186 pub fn set_capacity(&mut self, n: usize) {
191 self.capacity = Some(n);
192 }
193
194 pub fn page_size(&self) -> Option<usize> {
196 self.page_size
197 }
198
199 pub fn set_page_size(&mut self, n: usize) {
203 self.page_size = Some(n);
204 }
205
206 pub fn erase_size(&self) -> Option<usize> {
208 self.erase_size
209 }
210
211 pub fn set_erase_size(&mut self, n: usize) {
215 self.erase_size = Some(n);
216 }
217
218 pub fn erase_opcode(&self) -> u8 {
220 self.erase_opcode
221 }
222
223 pub fn set_erase_opcode(&mut self, opcode: u8) {
227 self.erase_opcode = opcode;
228 }
229
230 pub fn get_id(&self) -> Option<FlashID> {
234 self.id
235 }
236
237 pub fn get_params(&self) -> Option<FlashParams> {
241 self.params
242 }
243
244 pub fn read_id(&mut self) -> Result<FlashID> {
251 log::debug!("Reading SPI Flash ID");
252
253 let legacy_id = self.release_power_down()?;
254 self.reset()?;
255
256 let (bank_long, mfn_id_long, device_id_long) = self.read_jedec_id()?;
257 let (bank_short, mfn_id_short, mut device_id_short) = self.read_device_id()?;
258 let unique_id = self.read_unique_id()?;
259
260 let manufacturer_bank;
265 let manufacturer_id;
266 if mfn_id_long != 0x00 && mfn_id_long != 0xFF {
267 manufacturer_bank = bank_long;
268 manufacturer_id = mfn_id_long;
269 } else if mfn_id_short != 0x00 && mfn_id_short != 0xFF {
270 manufacturer_bank = bank_short;
271 manufacturer_id = mfn_id_short;
272 } else {
273 log::warn!("No valid manufacturer ID found");
274 if legacy_id == 0x00 || legacy_id == 0xFF {
275 log::error!("No device or manufacturer ID found");
276 return Err(Error::InvalidManufacturer);
277 } else {
278 device_id_short = legacy_id;
279 manufacturer_bank = 0;
280 manufacturer_id = 0;
281 }
282 }
283
284 let id = FlashID {
285 manufacturer_bank,
286 manufacturer_id,
287 device_id_long,
288 device_id_short,
289 unique_id,
290 };
291
292 log::debug!("Read ID: {:?}", id);
293 self.id = Some(id);
294 Ok(id)
295 }
296
297 pub fn read_params(&mut self) -> Result<Option<FlashParams>> {
312 log::debug!("Reading SFDP data");
313
314 let data = self.read_sfdp(0, 8)?;
316 let nph = data[6] as usize + 1;
317
318 let data = self.read_sfdp(0, 8 + nph * 8)?;
324 let header = match SFDPHeader::from_bytes(&data) {
325 Ok(header) => header,
326 Err(_) => return Ok(None),
327 };
328
329 let params = header.params[0];
332 if params.parameter_id != 0xFF00 || params.major != 0x01 {
333 log::error!("Unexpected first SFDP parameter header: expected 0xFF00 version 1.");
334 return Err(Error::InvalidSFDPHeader);
335 }
336
337 let data = self.read_sfdp(params.ptp, params.plen * 4)?;
339 let params = FlashParams::from_bytes(params.major, params.minor, &data)?;
340 self.params = Some(params);
341
342 self.address_bytes = match params.address_bytes {
344 SFDPAddressBytes::Three => 3,
345 SFDPAddressBytes::ThreeOrFour => 3,
346 SFDPAddressBytes::Four => 4,
347 _ => 3,
348 };
349 self.capacity = Some(params.capacity_bytes());
350 if let Some(page_size) = params.page_size {
351 self.page_size = Some(page_size as usize);
352 }
353 if let Some((size, opcode)) = params.sector_erase() {
354 self.erase_size = Some(size);
355 self.erase_opcode = opcode;
356 } else if params.legacy_4kb_erase_supported && params.legacy_4kb_erase_inst != 0xFF {
357 self.erase_size = Some(4096);
358 self.erase_opcode = params.legacy_4kb_erase_inst;
359 }
360 log::debug!("Updated settings from parameters:");
361 log::debug!(
362 "Address bytes: {}, capacity: {:?} bytes",
363 self.address_bytes,
364 self.capacity
365 );
366 log::debug!(
367 "Page size: {:?}, erase size: {:?}, erase op: {}",
368 self.page_size,
369 self.erase_size,
370 self.erase_opcode
371 );
372
373 Ok(Some(params))
374 }
375
376 pub fn read(&mut self, address: u32, length: usize) -> Result<Vec<u8>> {
381 self.check_address_length(address, length)?;
382 let mut param = self.make_address(address);
383 param.push(0);
385 self.exchange(Command::FastRead, ¶m, length)
386 }
387
388 pub fn legacy_read(&mut self, address: u32, length: usize) -> Result<Vec<u8>> {
394 self.check_address_length(address, length)?;
395 let param = self.make_address(address);
396 self.exchange(Command::ReadData, ¶m, length)
397 }
398
399 pub fn read_cb<F: Fn(usize)>(&mut self, address: u32, length: usize, cb: F) -> Result<Vec<u8>> {
407 self.check_address_length(address, length)?;
408 let chunk_size = usize::max(1024, length / 128);
409 let start = address as usize;
410 let end = start + length;
411 let mut data = Vec::new();
412 cb(0);
413 for addr in (start..end).step_by(chunk_size) {
414 let size = usize::min(chunk_size, end - addr);
415 let mut param = self.make_address(addr as u32);
416 param.push(0);
417 data.append(&mut self.exchange(Command::FastRead, ¶m, size)?);
418 cb(data.len());
419 }
420 cb(data.len());
421 Ok(data)
422 }
423
424 #[cfg(feature = "std")]
432 pub fn read_progress(&mut self, address: u32, length: usize) -> Result<Vec<u8>> {
433 let pb = ProgressBar::new(length as u64).with_style(
434 ProgressStyle::with_template(Self::DATA_PROGRESS_TPL)
435 .unwrap()
436 .progress_chars(Self::DATA_PROGRESS_CHARS),
437 );
438 pb.set_message("Reading");
439 let result = self.read_cb(address, length, |n| pb.set_position(n as u64));
440 pb.set_style(
441 ProgressStyle::with_template(Self::DATA_FINISHED_TPL)
442 .unwrap()
443 .progress_chars(Self::DATA_PROGRESS_CHARS),
444 );
445 pb.finish();
446 result
447 }
448
449 pub fn erase(&mut self) -> Result<()> {
457 self.write_enable()?;
458 self.command(Command::ChipErase)?;
459 self.wait_while_busy()?;
460 Ok(())
461 }
462
463 #[cfg(feature = "std")]
471 pub fn erase_progress(&mut self) -> Result<()> {
472 let time = self.params.map(|p| p.timing.map(|t| t.chip_erase_time_typ));
473 let pb = if let Some(Some(time)) = time {
474 ProgressBar::new(time.as_millis() as u64).with_style(
475 ProgressStyle::with_template(" {msg} [{bar:40.cyan/black}] {elapsed} < {eta}")
476 .unwrap()
477 .progress_chars(Self::DATA_PROGRESS_CHARS),
478 )
479 } else {
480 ProgressBar::new_spinner()
481 };
482 pb.set_message("Erasing");
483 let t0 = Instant::now();
484 self.write_enable()?;
485 self.command(Command::ChipErase)?;
486 while self.is_busy()? {
487 let t = t0.elapsed().as_millis() as u64;
488 pb.set_position(t);
489 }
490 pb.finish();
491 Ok(())
492 }
493
494 pub fn program(&mut self, address: u32, data: &[u8], verify: bool) -> Result<()> {
512 self.check_address_length(address, data.len())?;
513
514 let erase_plan = self.make_erase_plan(address, data.len())?;
516
517 let full_data = self.make_restore_data(address, data, &erase_plan)?;
519
520 self.run_erase_plan(&erase_plan, |_| {})?;
522
523 let start_addr = erase_plan.0[0].2;
525 self.program_data(start_addr, &full_data)?;
526
527 if verify {
529 let programmed = self.read(start_addr, full_data.len())?;
530 self.verify_readback(start_addr, &full_data, &programmed)?;
531 }
532
533 Ok(())
534 }
535
536 #[cfg(feature = "std")]
540 pub fn program_progress(&mut self, address: u32, data: &[u8], verify: bool) -> Result<()> {
541 self.check_address_length(address, data.len())?;
542
543 let erase_plan = self.make_erase_plan(address, data.len())?;
545
546 let full_data = self.make_restore_data(address, data, &erase_plan)?;
548
549 self.run_erase_plan_progress(&erase_plan)?;
551
552 let start_addr = erase_plan.0[0].2;
554 self.program_data_progress(start_addr, &full_data)?;
555
556 if verify {
558 let programmed = self.read_progress(start_addr, full_data.len())?;
559 self.verify_readback(start_addr, &full_data, &programmed)?;
560 }
561
562 Ok(())
563 }
564
565 pub fn reset(&mut self) -> Result<()> {
571 let mut do_f0 = false;
572 let mut do_66_99 = true;
573
574 if let Some(params) = self.params {
575 if let Some(op_66_99) = params.reset_inst_66_99 {
576 do_66_99 = op_66_99;
577 }
578 if let Some(op_f0) = params.reset_inst_f0 {
579 do_f0 = op_f0;
580 }
581 }
582
583 if do_66_99 {
584 self.command(Command::EnableReset)?;
585 self.command(Command::Reset)
586 } else if do_f0 {
587 self.command(0xF0)
588 } else {
589 log::error!("No reset instruction available.");
590 Err(Error::NoResetInstruction)
591 }
592 }
593
594 pub fn is_protected(&mut self) -> Result<bool> {
596 log::debug!("Checking if BP bits are set");
597 let status1 = self.read_status1()?;
598 let (bp0, bp1, bp2) = status1.get_block_protect();
599 log::debug!("BP0: {}, BP1: {}, BP2: {}", bp0, bp1, bp2);
600 Ok(bp0 || bp1 || bp2)
601 }
602
603 pub fn protect(&mut self, bp0: bool, bp1: bool, bp2: bool) -> Result<()> {
610 log::debug!(
611 "Setting block protection bits to BP0={}, BP1={}, BP2={}",
612 bp0,
613 bp1,
614 bp2
615 );
616 let mut status1 = self.read_status1()?;
617 status1.set_block_protect(bp0, bp1, bp2);
618 self.write_status1(status1)?;
619 self.wait_while_busy()?;
620 Ok(())
621 }
622
623 pub fn unprotect(&mut self) -> Result<()> {
629 log::debug!("Checking if BP bits are set before clearing them");
630 let mut status1 = self.read_status1()?;
631 let (bp0, bp1, bp2) = status1.get_block_protect();
632 if bp0 || bp1 || bp2 {
633 log::debug!("Block protect bits are currently set, clearing.");
634 status1.set_block_protect(false, false, false);
635 self.write_status1(status1)?;
636 self.wait_while_busy()?;
637 }
638 Ok(())
639 }
640
641 pub fn unprotect_wps(&mut self) -> Result<()> {
650 let mut status3 = self.read_status3()?;
651 if status3.get_wps() {
652 log::debug!("WPS bit set, clearing.");
653 status3.set_wps(false);
654 self.write_status3(status3)?;
655 self.wait_while_busy()?;
656 }
657 Ok(())
658 }
659
660 pub fn power_down(&mut self) -> Result<()> {
662 log::debug!("Sending Powerdown command");
663 self.command(Command::Powerdown)
664 }
665
666 pub fn release_power_down(&mut self) -> Result<u8> {
670 log::debug!("Sending Release Powerdown command");
671 let data = self.exchange(Command::ReleasePowerdown, &[0, 0, 0], 1)?;
672 Ok(data[0])
673 }
674
675 pub fn program_data(&mut self, address: u32, data: &[u8]) -> Result<()> {
680 self.program_data_cb(address, data, |_| {})
681 }
682
683 #[cfg(feature = "std")]
689 pub fn program_data_progress(&mut self, address: u32, data: &[u8]) -> Result<()> {
690 let pb = ProgressBar::new(data.len() as u64).with_style(
691 ProgressStyle::with_template(Self::DATA_PROGRESS_TPL)
692 .unwrap()
693 .progress_chars(Self::DATA_PROGRESS_CHARS),
694 );
695 pb.set_message("Writing");
696 self.program_data_cb(address, &data, |n| pb.set_position(n as u64))?;
697 pb.set_style(
698 ProgressStyle::with_template(Self::DATA_FINISHED_TPL)
699 .unwrap()
700 .progress_chars(Self::DATA_PROGRESS_CHARS),
701 );
702 pb.finish();
703 Ok(())
704 }
705
706 pub fn program_data_cb<F: Fn(usize)>(
714 &mut self,
715 address: u32,
716 mut data: &[u8],
717 cb: F,
718 ) -> Result<()> {
719 let page_size = match self.page_size {
720 Some(page_size) => page_size,
721 None => {
722 log::info!("Page size not known. Using a default of 256 bytes.");
723 log::info!("Set a specific page size using `set_page_size()`.");
724 256
725 }
726 };
727
728 log::trace!(
729 "Programming data to 0x{:08X}, page size {} bytes",
730 address,
731 page_size
732 );
733
734 let mut total_bytes = 0;
735 cb(total_bytes);
736
737 let first_write = page_size - ((address as usize) % page_size);
740 if first_write != page_size {
741 log::trace!("Programming partial first page of {} bytes", first_write);
742 self.page_program(address, &data[..first_write])?;
743 total_bytes += first_write;
744 data = &data[first_write..];
745 cb(total_bytes);
746 }
747
748 for page_data in data.chunks(page_size) {
749 self.page_program(address + total_bytes as u32, page_data)?;
750 total_bytes += page_data.len();
751 cb(total_bytes);
752 }
753
754 Ok(())
755 }
756
757 pub fn write_enable(&mut self) -> Result<()> {
759 self.command(Command::WriteEnable)
760 }
761
762 pub fn page_program(&mut self, address: u32, data: &[u8]) -> Result<()> {
770 let mut tx = self.make_address(address);
771 tx.extend(data);
772 self.write_enable()?;
773 self.exchange(Command::PageProgram, &tx, 0)?;
774 if let Some(params) = self.params {
775 if let Some(timing) = params.timing {
776 if timing.page_prog_time_typ > Duration::from_millis(1) {
780 self.access.delay(timing.page_prog_time_typ / 2);
781 }
782 }
783 }
784 self.wait_while_busy()?;
785 Ok(())
786 }
787
788 pub fn read_jedec_id(&mut self) -> Result<(u8, u8, u16)> {
796 let data = self.exchange(Command::ReadJEDECID, &[], 3)?;
798 if data[0] != 0x7F {
799 Ok((0, data[0], u16::from_be_bytes([data[1], data[2]])))
800 } else {
801 let data = self.exchange(Command::ReadJEDECID, &[], 16)?;
804 for n in 1..=13 {
805 if data[n] != 0x7F {
806 return Ok((
807 n as u8,
808 data[n],
809 u16::from_be_bytes([data[n + 1], data[n + 2]]),
810 ));
811 }
812 }
813 log::error!("Found more than 11 continuation bytes in manufacturer ID");
814 Err(Error::InvalidManufacturer)
815 }
816 }
817
818 pub fn read_device_id(&mut self) -> Result<(u8, u8, u8)> {
826 let data = self.exchange(Command::ReadDeviceID, &[0, 0, 0], 2)?;
828 if data[0] != 0x7F {
829 Ok((0, data[0], data[1]))
830 } else {
831 let data = self.exchange(Command::ReadJEDECID, &[0, 0, 0], 15)?;
834 for n in 1..=13 {
835 if data[n] != 0x7F {
836 return Ok((n as u8, data[n], data[n + 1]));
837 }
838 }
839 log::error!("Found more than 11 continuation bytes in manufacturer ID");
840 Err(Error::InvalidManufacturer)
841 }
842 }
843
844 pub fn read_unique_id(&mut self) -> Result<u64> {
846 self.exchange(Command::ReadUniqueID, &[0, 0, 0, 0], 8)
847 .map(|data| u64::from_be_bytes(data.try_into().unwrap()))
848 }
849
850 pub fn read_status1(&mut self) -> Result<StatusRegister1> {
852 self.exchange(Command::ReadStatusRegister1, &[], 1)
853 .map(|data| StatusRegister1(data[0]))
854 }
855
856 pub fn read_status2(&mut self) -> Result<StatusRegister2> {
861 self.exchange(Command::ReadStatusRegister2, &[], 1)
862 .map(|data| StatusRegister2(data[0]))
863 }
864
865 pub fn read_status3(&mut self) -> Result<StatusRegister3> {
870 self.exchange(Command::ReadStatusRegister3, &[], 1)
871 .map(|data| StatusRegister3(data[0]))
872 }
873
874 fn write_status1(&mut self, status1: StatusRegister1) -> Result<()> {
882 let we_opcode = if let Some(params) = self.params {
883 match params.status_1_vol {
884 Some(SFDPStatus1Volatility::NonVolatile06) => 0x06,
885 Some(SFDPStatus1Volatility::Volatile06) => 0x06,
886 Some(SFDPStatus1Volatility::Volatile50) => 0x50,
887 Some(SFDPStatus1Volatility::NonVolatile06Volatile50) => 0x06,
888 Some(SFDPStatus1Volatility::Mixed06) => 0x06,
889 _ => {
890 if params.legacy_block_protect_volatile {
891 params.legacy_volatile_write_en_inst
892 } else {
893 Command::WriteEnable.into()
894 }
895 }
896 }
897 } else {
898 Command::WriteEnable.into()
899 };
900 self.command(we_opcode)?;
901 let s1 = self.read_status1()?;
902 log::debug!("Set WEL, s1 now: {:02X}", s1.0);
903 self.write(Command::WriteStatusRegister1, &[status1.0])
904 }
905
906 pub fn write_status2(&mut self, status2: StatusRegister2) -> Result<()> {
908 self.write_enable()?;
909 self.write(Command::WriteStatusRegister2, &[status2.0])
910 }
911
912 pub fn write_status3(&mut self, status3: StatusRegister3) -> Result<()> {
914 self.write_enable()?;
915 self.write(Command::WriteStatusRegister3, &[status3.0])
916 }
917
918 pub fn is_busy(&mut self) -> Result<bool> {
924 if let Some(params) = self.params {
927 if let Some(busy_poll_flag) = params.busy_poll_flag {
928 if busy_poll_flag {
929 let fsr = self.exchange(Command::ReadFlagStatusRegister, &[], 1)?[0];
930 return Ok(fsr & 0b1000_0000 == 0);
931 }
932 }
933 }
934
935 self.read_status1().map(|status| status.get_busy())
937 }
938
939 pub fn wait_while_busy(&mut self) -> Result<()> {
944 while self.is_busy()? {}
945 Ok(())
946 }
947
948 pub fn read_sfdp(&mut self, addr: u32, len: usize) -> Result<Vec<u8>> {
952 let bytes = addr.to_be_bytes();
953 self.exchange(Command::ReadSFDPRegister, &bytes[1..], 1 + len)
954 .map(|data| data[1..].to_vec())
955 }
956
957 pub fn exchange<C: Into<u8>>(
959 &mut self,
960 command: C,
961 data: &[u8],
962 nbytes: usize,
963 ) -> Result<Vec<u8>> {
964 let mut tx = alloc::vec![command.into()];
965 tx.extend(data);
966 log::trace!("SPI exchange: write {:02X?}, read {} bytes", &tx, nbytes);
967 tx.extend(alloc::vec![0u8; nbytes]);
968 let rx = self.access.exchange(&tx)?;
969 log::trace!("SPI exchange: read {:02X?}", &rx[1 + data.len()..]);
970 Ok(rx[1 + data.len()..].to_vec())
971 }
972
973 pub fn write<C: Into<u8>>(&mut self, command: C, data: &[u8]) -> Result<()> {
975 let mut tx = alloc::vec![command.into()];
976 tx.extend(data);
977 log::trace!("SPI write: {:02X?}", &tx);
978 self.access.write(&tx)?;
979 Ok(())
980 }
981
982 pub fn command<C: Into<u8>>(&mut self, command: C) -> Result<()> {
984 self.write(command, &[])?;
985 Ok(())
986 }
987
988 fn check_address_length(&self, address: u32, length: usize) -> Result<()> {
994 log::trace!("Checking address={:08X} length={}", address, length);
995 let start = address as usize;
996 let end = (address as usize) + length - 1;
997 let max_addr = 1 << (self.address_bytes * 8);
998
999 if (end & (max_addr - 1)) < start {
1000 log::error!("Operation would wrap");
1001 Err(Error::InvalidAddress {
1002 address: end as u32,
1003 })
1004 } else if end > max_addr {
1005 log::error!("Operation would exceed largest address");
1006 Err(Error::InvalidAddress {
1007 address: end as u32,
1008 })
1009 } else {
1010 match self.capacity {
1011 Some(capacity) if (end >= capacity) => {
1012 log::error!("Operation would exceed flash capacity");
1013 Err(Error::InvalidAddress {
1014 address: end as u32,
1015 })
1016 }
1017 _ => Ok(()),
1018 }
1019 }
1020 }
1021
1022 fn make_address(&self, addr: u32) -> Vec<u8> {
1026 let bytes = addr.to_be_bytes();
1027 bytes[(4 - self.address_bytes as usize)..].to_vec()
1028 }
1029
1030 fn make_erase_plan(&self, address: u32, length: usize) -> Result<ErasePlan> {
1033 log::debug!(
1034 "Creating erase plan for address={} length={}",
1035 address,
1036 length
1037 );
1038 let mut insts = Vec::new();
1040
1041 if let Some(params) = self.params {
1043 if params.erase_insts.iter().any(|&inst| inst.is_some()) {
1044 log::trace!("Using SFDP erase instructions.");
1045 for inst in params.erase_insts.iter().flatten() {
1046 insts.push((inst.size as usize, inst.opcode, inst.time_typ));
1047 }
1048 } else if params.legacy_4kb_erase_supported {
1049 log::trace!("No erase instructions in SFDP, using legacy 4kB erase.");
1050 insts.push((4096, params.legacy_4kb_erase_inst, None));
1051 } else {
1052 log::trace!("SFDP indicates no erase instructions available.");
1053 }
1054 }
1055 if insts.is_empty() {
1056 if let Some(erase_size) = self.erase_size {
1057 log::trace!("No SFDP erase instructions found, using `erase_size` parameter.");
1058 insts.push((erase_size, self.erase_opcode, None));
1059 } else {
1060 log::warn!("No erase instructions could be found.");
1061 log::warn!("Try setting one manually using `Flash::set_erase_size()`.");
1062 return Err(Error::NoEraseInstruction);
1063 }
1064 }
1065 insts.sort();
1066
1067 Ok(ErasePlan::new(&insts, address as usize, length))
1069 }
1070
1071 fn read_erase_preamble(&mut self, address: u32, plan: &ErasePlan) -> Result<Vec<u8>> {
1073 let base = plan.0[0].2;
1074 let len = address - base;
1075 if len > 0 {
1076 log::debug!("Reading erase preamble: base={} len={}", base, len);
1077 self.read(base, len as usize)
1078 } else {
1079 Ok(Vec::new())
1080 }
1081 }
1082
1083 fn read_erase_postamble(
1088 &mut self,
1089 address: u32,
1090 length: usize,
1091 plan: &ErasePlan,
1092 ) -> Result<Vec<u8>> {
1093 let (_, size, base, _) = plan.0.last().unwrap();
1094 let start = address + (length as u32);
1095 let len = (*base as usize + *size) - start as usize;
1096 if len > 0 {
1097 log::debug!("Reading erase postamble: addr={} len={}", start, len);
1098 let data = self.read(start, len)?;
1099 if data.iter().all(|x| *x == 0xFF) {
1101 Ok(Vec::new())
1102 } else {
1103 Ok(data)
1104 }
1105 } else {
1106 Ok(Vec::new())
1107 }
1108 }
1109
1110 fn make_restore_data(
1113 &mut self,
1114 address: u32,
1115 data: &[u8],
1116 erase_plan: &ErasePlan,
1117 ) -> Result<Vec<u8>> {
1118 let preamble = self.read_erase_preamble(address, &erase_plan)?;
1119 let postamble = self.read_erase_postamble(address, data.len(), &erase_plan)?;
1120 let mut full_data = preamble;
1121 full_data.extend(data);
1122 full_data.extend(&postamble);
1123 Ok(full_data)
1124 }
1125
1126 fn run_erase_plan<F: Fn(usize)>(&mut self, plan: &ErasePlan, cb: F) -> Result<()> {
1130 let mut total_erased = 0;
1131 cb(total_erased);
1132 for (opcode, size, base, duration) in plan.0.iter() {
1133 log::trace!(
1134 "Executing erase plan: Erase 0x{:02X} ({} bytes) from 0x{:08X}",
1135 opcode,
1136 size,
1137 base
1138 );
1139 let addr = self.make_address(*base);
1140 self.write_enable()?;
1141 self.write(*opcode, &addr)?;
1142 if let Some(duration) = duration {
1143 self.access.delay(*duration / 2);
1144 }
1145 self.wait_while_busy()?;
1146 total_erased += size;
1147 cb(total_erased);
1148 }
1149 cb(total_erased);
1150 Ok(())
1151 }
1152
1153 #[cfg(feature = "std")]
1156 fn run_erase_plan_progress(&mut self, plan: &ErasePlan) -> Result<()> {
1157 let erase_size = plan.total_size() as u64;
1158 let pb = ProgressBar::new(erase_size).with_style(
1159 ProgressStyle::with_template(Self::DATA_PROGRESS_TPL)
1160 .unwrap()
1161 .progress_chars(Self::DATA_PROGRESS_CHARS),
1162 );
1163 pb.set_message("Erasing");
1164 self.run_erase_plan(&plan, |n| pb.set_position(n as u64))?;
1165 pb.set_style(
1166 ProgressStyle::with_template(Self::DATA_FINISHED_TPL)
1167 .unwrap()
1168 .progress_chars(Self::DATA_PROGRESS_CHARS),
1169 );
1170 pb.finish();
1171 Ok(())
1172 }
1173
1174 fn verify_readback(&mut self, address: u32, data: &[u8], new_data: &[u8]) -> Result<()> {
1178 let mismatch = data
1179 .iter()
1180 .zip(new_data)
1181 .enumerate()
1182 .find(|(_, (a, b))| a != b);
1183 match mismatch {
1184 Some((idx, (a, b))) => {
1185 let addr = address + idx as u32;
1186 log::error!(
1187 "Readback mismatch at 0x{:08X}: Wrote 0x{:02X}, read 0x{:02X}",
1188 addr,
1189 a,
1190 b
1191 );
1192 if self.is_protected()? {
1193 log::error!("Flash write protection appears to be enabled, try unprotecting.");
1194 }
1195 Err(Error::ReadbackError {
1196 address: addr,
1197 wrote: *a,
1198 read: *b,
1199 })
1200 }
1201 None => Ok(()),
1202 }
1203 }
1204}
1205
1206#[derive(Copy, Clone, Debug, num_enum::IntoPrimitive)]
1214#[allow(unused)]
1215#[repr(u8)]
1216enum Command {
1217 WriteEnable = 0x06,
1220 WriteDisable = 0x04,
1221 ReadData = 0x03,
1222 PageProgram = 0x02,
1223 ReadStatusRegister1 = 0x05,
1224 WriteStatusRegister1 = 0x01,
1225
1226 ReadJEDECID = 0x9F,
1229 FastRead = 0x0B,
1230 Powerdown = 0xB9,
1231 ReleasePowerdown = 0xAB,
1232 ReadDeviceID = 0x90,
1233 ChipErase = 0xC7,
1234
1235 ReadUniqueID = 0x4B,
1238 ReadSFDPRegister = 0x5A,
1239 ReadStatusRegister2 = 0x35,
1240 ReadStatusRegister3 = 0x15,
1241 ReadFlagStatusRegister = 0x70,
1242 WriteStatusRegister2 = 0x31,
1243 WriteStatusRegister3 = 0x11,
1244 WriteEnableVolatile = 0x50,
1245 EnableReset = 0x66,
1246 Reset = 0x99,
1247 ProgramSuspend = 0x75,
1248 ProgramResume = 0x7A,
1249
1250 SectorErase = 0x20,
1255 BlockErase1 = 0x52,
1256 BlockErase2 = 0xD8,
1257
1258 EraseSecurityRegisters = 0x44,
1260 ProgramSecurityRegisters = 0x42,
1261 ReadSecurityRegisters = 0x48,
1262 IndividualBlockLock = 0x36,
1263 IndividualBlockUnlock = 0x39,
1264 ReadBlockLock = 0x3D,
1265 GlobalBlockLock = 0x7E,
1266 GlobalBlockUnlock = 0x98,
1267}