sftool_lib/common/
erase_flash.rs1use crate::SifliToolTrait;
2use crate::common::ram_command::{Command, RamCommand};
3use crate::utils::Utils;
4
5pub struct EraseOps;
7
8impl EraseOps {
9 pub fn erase_all<T>(tool: &mut T, address: u32) -> Result<(), std::io::Error>
11 where
12 T: SifliToolTrait + RamCommand,
13 {
14 let progress = tool.progress();
15 let progress_bar =
16 progress.create_spinner(format!("Erasing entire flash at 0x{:08X}...", address));
17
18 let _ = tool.command(Command::EraseAll { address });
20
21 let mut buffer = Vec::new();
22 let now = std::time::SystemTime::now();
23
24 loop {
26 let elapsed = now.elapsed().unwrap().as_millis();
27 if elapsed > 30000 {
28 return Err(std::io::Error::new(
29 std::io::ErrorKind::TimedOut,
30 "Erase timeout",
31 ));
32 }
33
34 let mut byte = [0];
35 let ret = tool.port().read_exact(&mut byte);
36 if ret.is_err() {
37 continue;
38 }
39 buffer.push(byte[0]);
40
41 if buffer.windows(2).any(|window| window == b"OK") {
42 break;
43 }
44 }
45
46 progress_bar.finish_with_message("Erase complete");
47
48 Ok(())
49 }
50
51 pub fn erase_region<T>(tool: &mut T, address: u32, len: u32) -> Result<(), std::io::Error>
53 where
54 T: SifliToolTrait + RamCommand,
55 {
56 let progress = tool.progress();
57 let progress_bar = progress.create_spinner(format!(
58 "Erasing region at 0x{:08X} (size: 0x{:08X})...",
59 address, len
60 ));
61
62 let _ = tool.command(Command::Erase { address, len });
64
65 let mut buffer = Vec::new();
66 let now = std::time::SystemTime::now();
67
68 loop {
70 let elapsed = now.elapsed().unwrap().as_millis();
71 if elapsed > 30000 {
72 return Err(std::io::Error::new(
73 std::io::ErrorKind::TimedOut,
74 "Erase timeout",
75 ));
76 }
77
78 let mut byte = [0];
79 let ret = tool.port().read_exact(&mut byte);
80 if ret.is_err() {
81 continue;
82 }
83 buffer.push(byte[0]);
84
85 if buffer.windows(2).any(|window| window == b"OK") {
86 break;
87 }
88 }
89
90 let end_address = address + len - 1;
91 progress_bar.finish_with_message(&format!(
92 "Region erased successfully for 0x{:08X}..0x{:08X}",
93 address, end_address
94 ));
95
96 Ok(())
97 }
98
99 pub fn parse_address(address_str: &str) -> Result<u32, std::io::Error> {
101 Utils::str_to_u32(address_str)
102 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))
103 }
104
105 pub fn parse_region(region_spec: &str) -> Result<(u32, u32), std::io::Error> {
107 let Some((addr_str, size_str)) = region_spec.split_once(':') else {
108 return Err(std::io::Error::new(
109 std::io::ErrorKind::InvalidInput,
110 format!(
111 "Invalid region format: {}. Expected: address:size",
112 region_spec
113 ),
114 ));
115 };
116
117 let address = Utils::str_to_u32(addr_str)
118 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?;
119 let len = Utils::str_to_u32(size_str)
120 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?;
121
122 Ok((address, len))
123 }
124}