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::{Result, 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 ) -> std::result::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 (0xE0000000..0xF0000000).contains(&addr) {
118 l_addr = (addr & 0x0fffffff) | 0xF0000000;
119 } else if (0x00400000..=0x0041FFFF).contains(&addr) {
121 l_addr += 0x20000000;
123 } else if (0x20C00000..=0x20C1FFFF).contains(&addr) {
124 l_addr -= 0x00800000;
126 } else if (0x20000000..=0x200C7FFF).contains(&addr) {
127 l_addr += 0x0A000000;
129 } else if (0x20800000..=0x20BFFFFF).contains(&addr) {
130 l_addr -= 0x20800000;
132 } else if (0x10000000..=0x1FFFFFFF).contains(&addr) {
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(&mut self, command: SifliUartCommand) -> Result<SifliUartResponse> {
152 common_debug::debug_command_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, command)
153 }
154
155 fn debug_read_word32(&mut self, addr: u32) -> Result<u32> {
156 common_debug::debug_read_word32_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, addr)
157 }
158
159 fn debug_write_word32(&mut self, addr: u32, data: u32) -> Result<()> {
160 common_debug::debug_write_word32_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, addr, data)
161 }
162
163 fn debug_write_memory(&mut self, addr: u32, data: &[u8]) -> Result<()> {
164 common_debug::debug_write_memory_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, addr, data)
165 }
166
167 fn debug_write_core_reg(&mut self, reg: u16, data: u32) -> Result<()> {
168 common_debug::debug_write_core_reg_impl::<SF32LB56Tool, SF32LB56FrameFormat>(
169 self, reg, data,
170 )
171 }
172
173 fn debug_step(&mut self) -> Result<()> {
174 common_debug::debug_step_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
175 }
176
177 fn debug_run(&mut self) -> Result<()> {
178 common_debug::debug_run_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
179 }
180
181 fn debug_halt(&mut self) -> Result<()> {
182 common_debug::debug_halt_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
183 }
184}
185
186impl SF32LB56Tool {
187 pub fn internal_erase_all(&mut self, address: u32) -> Result<()> {
189 use ram_command::{Command, RamCommand};
190
191 let progress = self.progress();
192 let spinner =
193 progress.create_spinner(format!("Erasing entire flash at 0x{:08X}...", address));
194
195 let _ = self.command(Command::EraseAll { address });
197
198 let mut buffer = Vec::new();
199 let now = std::time::SystemTime::now();
200
201 loop {
203 let elapsed = now.elapsed().unwrap().as_millis();
204 if elapsed > 30000 {
205 tracing::error!("response string is {}", String::from_utf8_lossy(&buffer));
207 return Err(
208 std::io::Error::new(std::io::ErrorKind::TimedOut, "Erase timeout").into(),
209 );
210 }
211
212 let mut byte = [0];
213 let ret = self.port().read_exact(&mut byte);
214 if ret.is_err() {
215 continue;
216 }
217 buffer.push(byte[0]);
218
219 if buffer.windows(2).any(|window| window == b"OK") {
221 break;
222 }
223 }
224
225 spinner.finish_with_message(format!("Erase flash successfully: 0x{:08X}", address));
226
227 Ok(())
228 }
229
230 pub fn internal_erase_region(&mut self, address: u32, len: u32) -> Result<()> {
232 use ram_command::{Command, RamCommand};
233
234 let progress = self.progress();
235 let spinner = progress.create_spinner(format!(
236 "Erasing region at 0x{:08X} (size: 0x{:08X})...",
237 address, len
238 ));
239
240 let _ = self.command(Command::Erase { address, len });
242
243 let mut buffer = Vec::new();
244 let now = std::time::SystemTime::now();
245
246 loop {
248 let elapsed = now.elapsed().unwrap().as_millis();
249 if elapsed > 30000 {
250 tracing::error!("response string is {}", String::from_utf8_lossy(&buffer));
252 return Err(
253 std::io::Error::new(std::io::ErrorKind::TimedOut, "Erase timeout").into(),
254 );
255 }
256
257 let mut byte = [0];
258 let ret = self.port().read_exact(&mut byte);
259 if ret.is_err() {
260 continue;
261 }
262 buffer.push(byte[0]);
263
264 if buffer.windows(2).any(|window| window == b"OK") {
266 break;
267 }
268 }
269
270 spinner.finish_with_message(format!(
271 "Erase region successfully: 0x{:08X} (length: 0x{:08X})",
272 address, len
273 ));
274
275 Ok(())
276 }
277
278 pub fn attempt_connect(&mut self) -> Result<()> {
279 use crate::Operation;
280 use crate::common::sifli_debug::{SifliUartCommand, SifliUartResponse};
281
282 let infinite_attempts = self.base.connect_attempts <= 0;
283 let mut remaining_attempts = if infinite_attempts {
284 None
285 } else {
286 Some(self.base.connect_attempts)
287 };
288 loop {
289 if self.base.before == Operation::DefaultReset {
290 self.port.write_request_to_send(true)?;
292 std::thread::sleep(Duration::from_millis(100));
293 self.port.write_request_to_send(false)?;
294 std::thread::sleep(Duration::from_millis(100));
295 }
296 let value: Result<()> = match self.debug_command(SifliUartCommand::Enter) {
297 Ok(SifliUartResponse::Enter) => Ok(()),
298 _ => Err(std::io::Error::other("Failed to enter debug mode").into()),
299 };
300 if let Some(ref mut attempts) = remaining_attempts {
302 if *attempts == 0 {
303 break; }
305 *attempts -= 1;
306 }
307
308 let progress = self.progress();
309 let spinner = progress.create_spinner("Connecting to chip...");
310
311 match value {
313 Ok(_) => {
314 spinner.finish_with_message("Connected success!");
315 return Ok(());
316 }
317 Err(_) => {
318 spinner.finish_with_message("Failed to connect to the chip, retrying...");
319 std::thread::sleep(Duration::from_millis(500));
320 }
321 }
322 }
323 Err(std::io::Error::other("Failed to connect to the chip").into())
324 }
325
326 pub fn download_stub_impl(&mut self) -> Result<()> {
327 use crate::common::sifli_debug::SifliUartCommand;
328 use crate::ram_stub::{self, CHIP_FILE_NAME};
329 use probe_rs::MemoryMappedRegister;
330 use probe_rs::architecture::arm::core::armv7m::{Aircr, Demcr};
331 use probe_rs::architecture::arm::core::registers::cortex_m::{PC, SP};
332
333 let progress = self.progress();
334 let spinner = progress.create_spinner("Download stub...");
335
336 self.debug_halt()?;
338 let mut data = self.debug_read_word32(0x4004_0028)?;
340 if data & 0x20 != 0 {
341 data = 0xa05f0003;
342 self.debug_write_word32(0x3000_EDF0, data)?;
344 }
345
346 let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
349 let mut demcr = Demcr(demcr);
350 demcr.set_vc_corereset(true);
351 self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
352
353 let mut aircr = Aircr(0);
355 aircr.vectkey();
356 aircr.set_sysresetreq(true);
357 let _ = self.debug_write_word32(Aircr::get_mmio_address() as u32, aircr.into()); std::thread::sleep(std::time::Duration::from_millis(10));
359
360 self.debug_command(SifliUartCommand::Enter)?;
362
363 self.debug_halt()?;
365
366 let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
368 let mut demcr = Demcr(demcr);
369 demcr.set_vc_corereset(false);
370 self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
371
372 std::thread::sleep(std::time::Duration::from_millis(100));
373 let stub = ram_stub::RamStubFile::get(
375 CHIP_FILE_NAME
376 .get(format!("sf32lb56_{}", self.base.memory_type).as_str())
377 .expect("REASON"),
378 );
379 let Some(stub) = stub else {
380 spinner.finish_with_message("No stub file found for the given chip and memory type");
381 return Err(std::io::Error::new(
382 std::io::ErrorKind::NotFound,
383 "No stub file found for the given chip and memory type",
384 )
385 .into());
386 };
387
388 let packet_size = if self.base.compat { 256 } else { 64 * 1024 };
389
390 let mut addr = 0x2006_7000;
391 let mut data = &stub.data[..];
392 while !data.is_empty() {
393 let chunk = &data[..std::cmp::min(data.len(), packet_size)];
394 self.debug_write_memory(addr, chunk)?;
395 addr += chunk.len() as u32;
396 data = &data[chunk.len()..];
397 }
398
399 let sp = u32::from_le_bytes(
402 stub.data[0..4]
403 .try_into()
404 .expect("slice with exactly 4 bytes"),
405 );
406 let pc = u32::from_le_bytes(
407 stub.data[4..8]
408 .try_into()
409 .expect("slice with exactly 4 bytes"),
410 );
411 self.debug_write_core_reg(PC.id.0, pc)?;
412 self.debug_write_core_reg(SP.id.0, sp)?;
413
414 self.debug_run()?;
416
417 spinner.finish_with_message("Download stub success!");
418
419 Ok(())
420 }
421}
422
423impl SifliTool for SF32LB56Tool {
424 fn create_tool(base: SifliToolBase) -> Box<dyn SifliTool> {
425 let mut port = serialport::new(&base.port_name, 1000000)
426 .timeout(Duration::from_secs(5))
427 .open()
428 .unwrap();
429 port.write_request_to_send(false).unwrap();
430 std::thread::sleep(Duration::from_millis(100));
431
432 let mut tool = Box::new(Self { base, port });
433 tool.download_stub().expect("Failed to download stub");
434 tool
435 }
436}
437
438impl SifliToolTrait for SF32LB56Tool {
439 fn port(&mut self) -> &mut Box<dyn SerialPort> {
440 &mut self.port
441 }
442
443 fn base(&self) -> &SifliToolBase {
444 &self.base
445 }
446
447 fn set_speed(&mut self, baud: u32) -> Result<()> {
448 use crate::speed::SpeedTrait;
449 SpeedTrait::set_speed(self, baud)
450 }
451
452 fn soft_reset(&mut self) -> Result<()> {
453 use crate::reset::Reset;
454 Reset::soft_reset(self)
455 }
456}