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::common::sifli_debug::{SifliUartCommand, SifliUartResponse};
280
281 let infinite_attempts = self.base.connect_attempts <= 0;
282 let mut remaining_attempts = if infinite_attempts {
283 None
284 } else {
285 Some(self.base.connect_attempts)
286 };
287 loop {
288 if self.base.before.requires_reset() {
289 self.port.write_request_to_send(true)?;
291 std::thread::sleep(Duration::from_millis(100));
292 self.port.write_request_to_send(false)?;
293 std::thread::sleep(Duration::from_millis(100));
294 }
295 let value: Result<()> = match self.debug_command(SifliUartCommand::Enter) {
296 Ok(SifliUartResponse::Enter) => Ok(()),
297 _ => Err(std::io::Error::other("Failed to enter debug mode").into()),
298 };
299 if let Some(ref mut attempts) = remaining_attempts {
301 if *attempts == 0 {
302 break; }
304 *attempts -= 1;
305 }
306
307 let progress = self.progress();
308 let spinner = progress.create_spinner("Connecting to chip...");
309
310 match value {
312 Ok(_) => {
313 spinner.finish_with_message("Connected success!");
314 return Ok(());
315 }
316 Err(_) => {
317 spinner.finish_with_message("Failed to connect to the chip, retrying...");
318 std::thread::sleep(Duration::from_millis(500));
319 }
320 }
321 }
322 Err(std::io::Error::other("Failed to connect to the chip").into())
323 }
324
325 pub fn download_stub_impl(&mut self) -> Result<()> {
326 use crate::common::sifli_debug::SifliUartCommand;
327 use crate::ram_stub::load_stub_file;
328 use probe_rs::MemoryMappedRegister;
329 use probe_rs::architecture::arm::core::armv7m::{Aircr, Demcr};
330 use probe_rs::architecture::arm::core::registers::cortex_m::{PC, SP};
331
332 let progress = self.progress();
333 let spinner = progress.create_spinner("Download stub...");
334
335 self.debug_halt()?;
337 let mut data = self.debug_read_word32(0x4004_0028)?;
339 if data & 0x20 != 0 {
340 data = 0xa05f0003;
341 self.debug_write_word32(0x3000_EDF0, data)?;
343 }
344
345 let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
348 let mut demcr = Demcr(demcr);
349 demcr.set_vc_corereset(true);
350 self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
351
352 let mut aircr = Aircr(0);
354 aircr.vectkey();
355 aircr.set_sysresetreq(true);
356 let _ = self.debug_write_word32(Aircr::get_mmio_address() as u32, aircr.into()); std::thread::sleep(std::time::Duration::from_millis(10));
358
359 self.debug_command(SifliUartCommand::Enter)?;
361
362 self.debug_halt()?;
364
365 let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
367 let mut demcr = Demcr(demcr);
368 demcr.set_vc_corereset(false);
369 self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
370
371 std::thread::sleep(std::time::Duration::from_millis(100));
372 let chip_memory_key = format!("sf32lb56_{}", self.base.memory_type);
374 let stub = match load_stub_file(self.base.external_stub_path.as_deref(), &chip_memory_key) {
375 Ok(s) => s,
376 Err(e) => {
377 spinner
378 .finish_with_message("No stub file found for the given chip and memory type");
379 return Err(e.into());
380 }
381 };
382
383 let packet_size = if self.base.compat { 256 } else { 64 * 1024 };
384
385 let mut addr = 0x2006_7000;
386 let mut data = &stub.data[..];
387 while !data.is_empty() {
388 let chunk = &data[..std::cmp::min(data.len(), packet_size)];
389 self.debug_write_memory(addr, chunk)?;
390 addr += chunk.len() as u32;
391 data = &data[chunk.len()..];
392 }
393
394 let sp = u32::from_le_bytes(
397 stub.data[0..4]
398 .try_into()
399 .expect("slice with exactly 4 bytes"),
400 );
401 let pc = u32::from_le_bytes(
402 stub.data[4..8]
403 .try_into()
404 .expect("slice with exactly 4 bytes"),
405 );
406 self.debug_write_core_reg(PC.id.0, pc)?;
407 self.debug_write_core_reg(SP.id.0, sp)?;
408
409 self.debug_run()?;
411
412 spinner.finish_with_message("Download stub success!");
413
414 Ok(())
415 }
416}
417
418impl SifliTool for SF32LB56Tool {
419 fn create_tool(base: SifliToolBase) -> Box<dyn SifliTool> {
420 let mut port = serialport::new(&base.port_name, 1000000)
421 .timeout(Duration::from_secs(5))
422 .open()
423 .unwrap();
424 port.write_request_to_send(false).unwrap();
425 std::thread::sleep(Duration::from_millis(100));
426
427 let mut tool = Box::new(Self { base, port });
428 if tool.base.before.should_download_stub() {
429 tool.download_stub().expect("Failed to download stub");
430 }
431 tool
432 }
433}
434
435impl SifliToolTrait for SF32LB56Tool {
436 fn port(&mut self) -> &mut Box<dyn SerialPort> {
437 &mut self.port
438 }
439
440 fn base(&self) -> &SifliToolBase {
441 &self.base
442 }
443
444 fn set_speed(&mut self, baud: u32) -> Result<()> {
445 use crate::speed::SpeedTrait;
446 SpeedTrait::set_speed(self, baud)
447 }
448
449 fn soft_reset(&mut self) -> Result<()> {
450 use crate::reset::Reset;
451 Reset::soft_reset(self)
452 }
453}