1pub mod erase_flash;
4pub mod ram_command;
5pub mod read_flash;
6pub mod reset;
7pub mod sifli_debug;
8pub mod speed;
9pub mod write_flash;
10
11use crate::common::sifli_debug::{
12 ChipFrameFormat, RecvError, START_WORD, SifliDebug, SifliUartCommand, SifliUartResponse,
13 common_debug,
14};
15use crate::sf32lb56::ram_command::DownloadStub;
16use crate::{SifliTool, SifliToolBase, SifliToolTrait};
17use serialport::SerialPort;
18use std::io::{BufReader, Read};
19use std::time::Duration;
20
21pub struct SF32LB56FrameFormat;
23
24impl ChipFrameFormat for SF32LB56FrameFormat {
25 fn create_header(len: u16) -> Vec<u8> {
26 let mut header = vec![];
27 header.extend_from_slice(&START_WORD);
28 header.extend_from_slice(&len.to_be_bytes());
30 header.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
32 header.push(0x10);
34 header.push(0x00);
36 header.extend_from_slice(&[0x00, 0x00]);
38 header
39 }
40
41 fn parse_frame_header(
42 reader: &mut BufReader<Box<dyn Read + Send>>,
43 ) -> Result<usize, RecvError> {
44 let mut length_bytes = [0; 2];
46 if let Err(e) = reader.read_exact(&mut length_bytes) {
47 tracing::error!("Failed to read length bytes: {}", e);
48 return Err(RecvError::InvalidHeaderLength);
49 }
50
51 let payload_size = u16::from_be_bytes(length_bytes) as usize;
52
53 let mut timestamp_bytes = [0; 4];
55 if let Err(e) = reader.read_exact(&mut timestamp_bytes) {
56 tracing::error!("Failed to read timestamp bytes: {}", e);
57 return Err(RecvError::InvalidHeaderChannel);
58 }
59
60 let mut channel_crc = [0; 2];
62 if let Err(e) = reader.read_exact(&mut channel_crc) {
63 tracing::error!("Failed to read channel and CRC bytes: {}", e);
64 return Err(RecvError::InvalidHeaderChannel);
65 }
66
67 let mut reserved_bytes = [0; 2];
69 if let Err(e) = reader.read_exact(&mut reserved_bytes) {
70 tracing::error!("Failed to read reserved bytes: {}", e);
71 return Err(RecvError::ReadError(e));
72 }
73
74 Ok(payload_size)
75 }
76
77 fn encode_command_data(command: &SifliUartCommand) -> Vec<u8> {
78 let mut send_data = vec![];
79 match command {
80 SifliUartCommand::Enter => {
81 let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x05, 0x21];
82 send_data.extend_from_slice(&temp);
83 }
84 SifliUartCommand::Exit => {
85 let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x18, 0x21];
86 send_data.extend_from_slice(&temp);
87 }
88 SifliUartCommand::MEMRead { addr, len } => {
89 send_data.push(0x40);
90 send_data.push(0x72);
91 send_data.extend_from_slice(&addr.to_be_bytes());
93 send_data.extend_from_slice(&len.to_be_bytes());
94 }
95 SifliUartCommand::MEMWrite { addr, data } => {
96 send_data.push(0x40);
97 send_data.push(0x77);
98 send_data.extend_from_slice(&addr.to_be_bytes());
100 send_data.extend_from_slice(&(data.len() as u16).to_be_bytes());
101 for d in data.iter() {
102 send_data.extend_from_slice(&d.to_be_bytes());
103 }
104 }
105 }
106 send_data
107 }
108
109 fn decode_response_data(data: &[u8]) -> u32 {
110 u32::from_be_bytes([data[0], data[1], data[2], data[3]])
112 }
113
114 fn map_address(addr: u32) -> u32 {
116 let mut l_addr = addr;
117 if addr >= 0xE0000000 && addr < 0xF0000000 {
118 l_addr = (addr & 0x0fffffff) | 0xF0000000;
119 } else if addr >= 0x00400000 && addr <= 0x0041FFFF {
121 l_addr += 0x20000000;
123 } else if addr >= 0x20C00000 && addr <= 0x20C1FFFF {
124 l_addr -= 0x00800000;
126 } else if addr >= 0x20000000 && addr <= 0x200C7FFF {
127 l_addr += 0x0A000000;
129 } else if addr >= 0x20800000 && addr <= 0x20BFFFFF {
130 l_addr -= 0x20800000;
132 } else if addr >= 0x10000000 && addr <= 0x1FFFFFFF {
133 l_addr += 0x50000000;
135 }
136 l_addr
137 }
138}
139
140pub struct SF32LB56Tool {
141 pub base: SifliToolBase,
142 pub port: Box<dyn SerialPort>,
143}
144
145unsafe impl Send for SF32LB56Tool {}
147unsafe impl Sync for SF32LB56Tool {}
148
149impl SifliDebug for SF32LB56Tool {
151 fn debug_command(
152 &mut self,
153 command: SifliUartCommand,
154 ) -> Result<SifliUartResponse, std::io::Error> {
155 common_debug::debug_command_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, command)
156 }
157
158 fn debug_read_word32(&mut self, addr: u32) -> Result<u32, std::io::Error> {
159 common_debug::debug_read_word32_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, addr)
160 }
161
162 fn debug_write_word32(&mut self, addr: u32, data: u32) -> Result<(), std::io::Error> {
163 common_debug::debug_write_word32_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, addr, data)
164 }
165
166 fn debug_write_memory(&mut self, addr: u32, data: &[u8]) -> Result<(), std::io::Error> {
167 common_debug::debug_write_memory_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, addr, data)
168 }
169
170 fn debug_write_core_reg(&mut self, reg: u16, data: u32) -> Result<(), std::io::Error> {
171 common_debug::debug_write_core_reg_impl::<SF32LB56Tool, SF32LB56FrameFormat>(
172 self, reg, data,
173 )
174 }
175
176 fn debug_step(&mut self) -> Result<(), std::io::Error> {
177 common_debug::debug_step_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
178 }
179
180 fn debug_run(&mut self) -> Result<(), std::io::Error> {
181 common_debug::debug_run_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
182 }
183
184 fn debug_halt(&mut self) -> Result<(), std::io::Error> {
185 common_debug::debug_halt_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
186 }
187}
188
189impl SF32LB56Tool {
190 pub fn internal_erase_all(&mut self, address: u32) -> Result<(), std::io::Error> {
192 use ram_command::{Command, RamCommand};
193
194 let progress = self.progress();
195 let spinner =
196 progress.create_spinner(format!("Erasing entire flash at 0x{:08X}...", address));
197
198 let _ = self.command(Command::EraseAll { address });
200
201 let mut buffer = Vec::new();
202 let now = std::time::SystemTime::now();
203
204 loop {
206 let elapsed = now.elapsed().unwrap().as_millis();
207 if elapsed > 30000 {
208 tracing::error!("response string is {}", String::from_utf8_lossy(&buffer));
210 return Err(std::io::Error::new(
211 std::io::ErrorKind::TimedOut,
212 "Erase timeout",
213 ));
214 }
215
216 let mut byte = [0];
217 let ret = self.port().read_exact(&mut byte);
218 if ret.is_err() {
219 continue;
220 }
221 buffer.push(byte[0]);
222
223 if buffer.windows(2).any(|window| window == b"OK") {
225 break;
226 }
227 }
228
229 spinner.finish_with_message(format!("Erase flash successfully: 0x{:08X}", address));
230
231 Ok(())
232 }
233
234 pub fn internal_erase_region(&mut self, address: u32, len: u32) -> Result<(), std::io::Error> {
236 use ram_command::{Command, RamCommand};
237
238 let progress = self.progress();
239 let spinner = progress.create_spinner(format!(
240 "Erasing region at 0x{:08X} (size: 0x{:08X})...",
241 address, len
242 ));
243
244 let _ = self.command(Command::Erase { address, len });
246
247 let mut buffer = Vec::new();
248 let now = std::time::SystemTime::now();
249
250 loop {
252 let elapsed = now.elapsed().unwrap().as_millis();
253 if elapsed > 30000 {
254 tracing::error!("response string is {}", String::from_utf8_lossy(&buffer));
256 return Err(std::io::Error::new(
257 std::io::ErrorKind::TimedOut,
258 "Erase timeout",
259 ));
260 }
261
262 let mut byte = [0];
263 let ret = self.port().read_exact(&mut byte);
264 if ret.is_err() {
265 continue;
266 }
267 buffer.push(byte[0]);
268
269 if buffer.windows(2).any(|window| window == b"OK") {
271 break;
272 }
273 }
274
275 spinner.finish_with_message(format!(
276 "Erase region successfully: 0x{:08X} (length: 0x{:08X})",
277 address, len
278 ));
279
280 Ok(())
281 }
282
283 pub fn attempt_connect(&mut self) -> Result<(), std::io::Error> {
284 use crate::Operation;
285 use crate::common::sifli_debug::{SifliUartCommand, SifliUartResponse};
286
287 let infinite_attempts = self.base.connect_attempts <= 0;
288 let mut remaining_attempts = if infinite_attempts {
289 None
290 } else {
291 Some(self.base.connect_attempts)
292 };
293 loop {
294 if self.base.before == Operation::DefaultReset {
295 self.port.write_request_to_send(true)?;
297 std::thread::sleep(Duration::from_millis(100));
298 self.port.write_request_to_send(false)?;
299 std::thread::sleep(Duration::from_millis(100));
300 }
301 let value = match self.debug_command(SifliUartCommand::Enter) {
302 Ok(SifliUartResponse::Enter) => Ok(()),
303 _ => Err(std::io::Error::new(
304 std::io::ErrorKind::Other,
305 "Failed to enter debug mode",
306 )),
307 };
308 if let Some(ref mut attempts) = remaining_attempts {
310 if *attempts == 0 {
311 break; }
313 *attempts -= 1;
314 }
315
316 let progress = self.progress();
317 let spinner = progress.create_spinner("Connecting to chip...");
318
319 match value {
321 Ok(_) => {
322 spinner.finish_with_message("Connected success!");
323 return Ok(());
324 }
325 Err(_) => {
326 spinner.finish_with_message("Failed to connect to the chip, retrying...");
327 std::thread::sleep(Duration::from_millis(500));
328 }
329 }
330 }
331 Err(std::io::Error::new(
332 std::io::ErrorKind::Other,
333 "Failed to connect to the chip",
334 ))
335 }
336
337 pub fn download_stub_impl(&mut self) -> Result<(), std::io::Error> {
338 use crate::common::sifli_debug::SifliUartCommand;
339 use crate::ram_stub::{self, CHIP_FILE_NAME};
340 use probe_rs::MemoryMappedRegister;
341 use probe_rs::architecture::arm::core::armv7m::{Aircr, Demcr};
342 use probe_rs::architecture::arm::core::registers::cortex_m::{PC, SP};
343
344 let progress = self.progress();
345 let spinner = progress.create_spinner("Download stub...");
346
347 self.debug_halt()?;
349 let mut data = self.debug_read_word32(0x4004_0028)?;
351 if data & 0x20 != 0 {
352 data = 0xa05f0003;
353 self.debug_write_word32(0x3000_EDF0, data)?;
355 }
356
357 let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
360 let mut demcr = Demcr(demcr);
361 demcr.set_vc_corereset(true);
362 self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
363
364 let mut aircr = Aircr(0);
366 aircr.vectkey();
367 aircr.set_sysresetreq(true);
368 let _ = self.debug_write_word32(Aircr::get_mmio_address() as u32, aircr.into()); std::thread::sleep(std::time::Duration::from_millis(10));
370
371 self.debug_command(SifliUartCommand::Enter)?;
373
374 self.debug_halt()?;
376
377 let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
379 let mut demcr = Demcr(demcr);
380 demcr.set_vc_corereset(false);
381 self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
382
383 std::thread::sleep(std::time::Duration::from_millis(100));
384 let stub = ram_stub::RamStubFile::get(
386 CHIP_FILE_NAME
387 .get(format!("sf32lb56_{}", self.base.memory_type).as_str())
388 .expect("REASON"),
389 );
390 let Some(stub) = stub else {
391 spinner.finish_with_message("No stub file found for the given chip and memory type");
392 return Err(std::io::Error::new(
393 std::io::ErrorKind::NotFound,
394 "No stub file found for the given chip and memory type",
395 ));
396 };
397
398 let packet_size = if self.base.compat { 256 } else { 64 * 1024 };
399
400 let mut addr = 0x2006_7000;
401 let mut data = &stub.data[..];
402 while !data.is_empty() {
403 let chunk = &data[..std::cmp::min(data.len(), packet_size)];
404 self.debug_write_memory(addr, chunk)?;
405 addr += chunk.len() as u32;
406 data = &data[chunk.len()..];
407 }
408
409 let sp = u32::from_le_bytes(
412 stub.data[0..4]
413 .try_into()
414 .expect("slice with exactly 4 bytes"),
415 );
416 let pc = u32::from_le_bytes(
417 stub.data[4..8]
418 .try_into()
419 .expect("slice with exactly 4 bytes"),
420 );
421 self.debug_write_core_reg(PC.id.0, pc)?;
422 self.debug_write_core_reg(SP.id.0, sp)?;
423
424 self.debug_run()?;
426
427 spinner.finish_with_message("Download stub success!");
428
429 Ok(())
430 }
431}
432
433impl SifliTool for SF32LB56Tool {
434 fn create_tool(base: SifliToolBase) -> Box<dyn SifliTool> {
435 let mut port = serialport::new(&base.port_name, 1000000)
436 .timeout(Duration::from_secs(5))
437 .open()
438 .unwrap();
439 port.write_request_to_send(false).unwrap();
440 std::thread::sleep(Duration::from_millis(100));
441
442 let mut tool = Box::new(Self { base, port });
443 tool.download_stub().expect("Failed to download stub");
444 tool
445 }
446}
447
448impl SifliToolTrait for SF32LB56Tool {
449 fn port(&mut self) -> &mut Box<dyn SerialPort> {
450 &mut self.port
451 }
452
453 fn base(&self) -> &SifliToolBase {
454 &self.base
455 }
456
457 fn set_speed(&mut self, baud: u32) -> Result<(), std::io::Error> {
458 use crate::speed::SpeedTrait;
459 SpeedTrait::set_speed(self, baud)
460 }
461
462 fn soft_reset(&mut self) -> Result<(), std::io::Error> {
463 use crate::reset::Reset;
464 Reset::soft_reset(self)
465 }
466}