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::progress::{
16 EraseFlashStyle, EraseRegionStyle, ProgressOperation, ProgressStatus, StubStage,
17};
18use crate::sf32lb56::ram_command::DownloadStub;
19use crate::{Result, SifliTool, SifliToolBase, SifliToolTrait};
20use serialport::SerialPort;
21use std::io::{BufReader, Read};
22use std::time::Duration;
23
24pub struct SF32LB56FrameFormat;
26
27impl ChipFrameFormat for SF32LB56FrameFormat {
28 fn create_header(len: u16) -> Vec<u8> {
29 let mut header = vec![];
30 header.extend_from_slice(&START_WORD);
31 header.extend_from_slice(&len.to_be_bytes());
33 header.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
35 header.push(0x10);
37 header.push(0x00);
39 header.extend_from_slice(&[0x00, 0x00]);
41 header
42 }
43
44 fn parse_frame_header(
45 reader: &mut BufReader<Box<dyn Read + Send>>,
46 ) -> std::result::Result<usize, RecvError> {
47 let mut length_bytes = [0; 2];
49 if let Err(e) = reader.read_exact(&mut length_bytes) {
50 tracing::error!("Failed to read length bytes: {}", e);
51 return Err(RecvError::InvalidHeaderLength);
52 }
53
54 let payload_size = u16::from_be_bytes(length_bytes) as usize;
55
56 let mut timestamp_bytes = [0; 4];
58 if let Err(e) = reader.read_exact(&mut timestamp_bytes) {
59 tracing::error!("Failed to read timestamp bytes: {}", e);
60 return Err(RecvError::InvalidHeaderChannel);
61 }
62
63 let mut channel_crc = [0; 2];
65 if let Err(e) = reader.read_exact(&mut channel_crc) {
66 tracing::error!("Failed to read channel and CRC bytes: {}", e);
67 return Err(RecvError::InvalidHeaderChannel);
68 }
69
70 let mut reserved_bytes = [0; 2];
72 if let Err(e) = reader.read_exact(&mut reserved_bytes) {
73 tracing::error!("Failed to read reserved bytes: {}", e);
74 return Err(RecvError::ReadError(e));
75 }
76
77 Ok(payload_size)
78 }
79
80 fn encode_command_data(command: &SifliUartCommand) -> Vec<u8> {
81 let mut send_data = vec![];
82 match command {
83 SifliUartCommand::Enter => {
84 let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x05, 0x21];
85 send_data.extend_from_slice(&temp);
86 }
87 SifliUartCommand::Exit => {
88 let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x18, 0x21];
89 send_data.extend_from_slice(&temp);
90 }
91 SifliUartCommand::MEMRead { addr, len } => {
92 send_data.push(0x40);
93 send_data.push(0x72);
94 send_data.extend_from_slice(&addr.to_be_bytes());
96 send_data.extend_from_slice(&len.to_be_bytes());
97 }
98 SifliUartCommand::MEMWrite { addr, data } => {
99 send_data.push(0x40);
100 send_data.push(0x77);
101 send_data.extend_from_slice(&addr.to_be_bytes());
103 send_data.extend_from_slice(&(data.len() as u16).to_be_bytes());
104 for d in data.iter() {
105 send_data.extend_from_slice(&d.to_be_bytes());
106 }
107 }
108 }
109 send_data
110 }
111
112 fn decode_response_data(data: &[u8]) -> u32 {
113 u32::from_be_bytes([data[0], data[1], data[2], data[3]])
115 }
116
117 fn map_address(addr: u32) -> u32 {
119 let mut l_addr = addr;
120 if (0xE0000000..0xF0000000).contains(&addr) {
121 l_addr = (addr & 0x0fffffff) | 0xF0000000;
122 } else if (0x00400000..=0x0041FFFF).contains(&addr) {
124 l_addr += 0x20000000;
126 } else if (0x20C00000..=0x20C1FFFF).contains(&addr) {
127 l_addr -= 0x00800000;
129 } else if (0x20000000..=0x200C7FFF).contains(&addr) {
130 l_addr += 0x0A000000;
132 } else if (0x20800000..=0x20BFFFFF).contains(&addr) {
133 l_addr -= 0x20800000;
135 } else if (0x10000000..=0x1FFFFFFF).contains(&addr) {
136 l_addr += 0x50000000;
138 }
139 l_addr
140 }
141}
142
143pub struct SF32LB56Tool {
144 pub base: SifliToolBase,
145 pub port: Box<dyn SerialPort>,
146}
147
148unsafe impl Send for SF32LB56Tool {}
150unsafe impl Sync for SF32LB56Tool {}
151
152impl SifliDebug for SF32LB56Tool {
154 fn debug_command(&mut self, command: SifliUartCommand) -> Result<SifliUartResponse> {
155 common_debug::debug_command_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, command)
156 }
157
158 fn debug_read_word32(&mut self, addr: u32) -> Result<u32> {
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<()> {
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<()> {
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<()> {
171 common_debug::debug_write_core_reg_impl::<SF32LB56Tool, SF32LB56FrameFormat>(
172 self, reg, data,
173 )
174 }
175
176 fn debug_step(&mut self) -> Result<()> {
177 common_debug::debug_step_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
178 }
179
180 fn debug_run(&mut self) -> Result<()> {
181 common_debug::debug_run_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
182 }
183
184 fn debug_halt(&mut self) -> Result<()> {
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<()> {
192 use ram_command::{Command, RamCommand};
193
194 let progress = self.progress();
195 let spinner = progress.create_spinner(ProgressOperation::EraseFlash {
196 address,
197 style: EraseFlashStyle::Addressed,
198 });
199
200 let _ = self.command(Command::EraseAll { address });
202
203 let mut buffer = Vec::new();
204 let now = std::time::SystemTime::now();
205
206 loop {
208 let elapsed = now.elapsed().unwrap().as_millis();
209 if elapsed > 30000 {
210 tracing::error!("response string is {}", String::from_utf8_lossy(&buffer));
212 return Err(
213 std::io::Error::new(std::io::ErrorKind::TimedOut, "Erase timeout").into(),
214 );
215 }
216
217 let mut byte = [0];
218 let ret = self.port().read_exact(&mut byte);
219 if ret.is_err() {
220 continue;
221 }
222 buffer.push(byte[0]);
223
224 if buffer.windows(2).any(|window| window == b"OK") {
226 break;
227 }
228 }
229
230 spinner.finish(ProgressStatus::Success);
231
232 Ok(())
233 }
234
235 pub fn internal_erase_region(&mut self, address: u32, len: u32) -> Result<()> {
237 use ram_command::{Command, RamCommand};
238
239 let progress = self.progress();
240 let spinner = progress.create_spinner(ProgressOperation::EraseRegion {
241 address,
242 len,
243 style: EraseRegionStyle::HexLength,
244 });
245
246 let _ = self.command(Command::Erase { address, len });
248
249 let mut buffer = Vec::new();
250 let now = std::time::SystemTime::now();
251
252 loop {
254 let elapsed = now.elapsed().unwrap().as_millis();
255 if elapsed > 30000 {
256 tracing::error!("response string is {}", String::from_utf8_lossy(&buffer));
258 return Err(
259 std::io::Error::new(std::io::ErrorKind::TimedOut, "Erase timeout").into(),
260 );
261 }
262
263 let mut byte = [0];
264 let ret = self.port().read_exact(&mut byte);
265 if ret.is_err() {
266 continue;
267 }
268 buffer.push(byte[0]);
269
270 if buffer.windows(2).any(|window| window == b"OK") {
272 break;
273 }
274 }
275
276 spinner.finish(ProgressStatus::Success);
277
278 Ok(())
279 }
280
281 pub fn attempt_connect(&mut self) -> Result<()> {
282 use crate::common::sifli_debug::{SifliUartCommand, SifliUartResponse};
283
284 let infinite_attempts = self.base.connect_attempts <= 0;
285 let mut remaining_attempts = if infinite_attempts {
286 None
287 } else {
288 Some(self.base.connect_attempts)
289 };
290 loop {
291 if self.base.before.requires_reset() {
292 self.port.write_request_to_send(true)?;
294 std::thread::sleep(Duration::from_millis(100));
295 self.port.write_request_to_send(false)?;
296 std::thread::sleep(Duration::from_millis(100));
297 }
298 let value: Result<()> = match self.debug_command(SifliUartCommand::Enter) {
299 Ok(SifliUartResponse::Enter) => Ok(()),
300 _ => Err(std::io::Error::other("Failed to enter debug mode").into()),
301 };
302 if let Some(ref mut attempts) = remaining_attempts {
304 if *attempts == 0 {
305 break; }
307 *attempts -= 1;
308 }
309
310 let progress = self.progress();
311 let spinner = progress.create_spinner(ProgressOperation::Connect);
312
313 match value {
315 Ok(_) => {
316 spinner.finish(ProgressStatus::Success);
317 return Ok(());
318 }
319 Err(_) => {
320 spinner.finish(ProgressStatus::Retry);
321 std::thread::sleep(Duration::from_millis(500));
322 }
323 }
324 }
325 Err(std::io::Error::other("Failed to connect to the chip").into())
326 }
327
328 pub fn download_stub_impl(&mut self) -> Result<()> {
329 use crate::common::sifli_debug::SifliUartCommand;
330 use crate::ram_stub::load_stub_file;
331 use probe_rs::MemoryMappedRegister;
332 use probe_rs::architecture::arm::core::armv7m::{Aircr, Demcr};
333 use probe_rs::architecture::arm::core::registers::cortex_m::{PC, SP};
334
335 let progress = self.progress();
336 let spinner = progress.create_spinner(ProgressOperation::DownloadStub {
337 stage: StubStage::Start,
338 });
339
340 self.debug_halt()?;
342 let mut data = self.debug_read_word32(0x4004_0028)?;
344 if data & 0x20 != 0 {
345 data = 0xa05f0003;
346 self.debug_write_word32(0x3000_EDF0, data)?;
348 }
349
350 let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
353 let mut demcr = Demcr(demcr);
354 demcr.set_vc_corereset(true);
355 self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
356
357 let mut aircr = Aircr(0);
359 aircr.vectkey();
360 aircr.set_sysresetreq(true);
361 let _ = self.debug_write_word32(Aircr::get_mmio_address() as u32, aircr.into()); std::thread::sleep(std::time::Duration::from_millis(10));
363
364 self.debug_command(SifliUartCommand::Enter)?;
366
367 self.debug_halt()?;
369
370 let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
372 let mut demcr = Demcr(demcr);
373 demcr.set_vc_corereset(false);
374 self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
375
376 std::thread::sleep(std::time::Duration::from_millis(100));
377 let chip_memory_key = format!("sf32lb56_{}", self.base.memory_type);
379 let stub = match load_stub_file(self.base.external_stub_path.as_deref(), &chip_memory_key) {
380 Ok(s) => s,
381 Err(e) => {
382 spinner.finish(ProgressStatus::NotFound);
383 return Err(e.into());
384 }
385 };
386
387 let packet_size = if self.base.compat { 256 } else { 64 * 1024 };
388
389 let mut addr = 0x2006_7000;
390 let mut data = &stub.data[..];
391 while !data.is_empty() {
392 let chunk = &data[..std::cmp::min(data.len(), packet_size)];
393 self.debug_write_memory(addr, chunk)?;
394 addr += chunk.len() as u32;
395 data = &data[chunk.len()..];
396 }
397
398 let sp = u32::from_le_bytes(
401 stub.data[0..4]
402 .try_into()
403 .expect("slice with exactly 4 bytes"),
404 );
405 let pc = u32::from_le_bytes(
406 stub.data[4..8]
407 .try_into()
408 .expect("slice with exactly 4 bytes"),
409 );
410 self.debug_write_core_reg(PC.id.0, pc)?;
411 self.debug_write_core_reg(SP.id.0, sp)?;
412
413 self.debug_run()?;
415
416 spinner.finish(ProgressStatus::Success);
417
418 Ok(())
419 }
420}
421
422impl SifliTool for SF32LB56Tool {
423 fn create_tool(base: SifliToolBase) -> Box<dyn SifliTool> {
424 let mut port = serialport::new(&base.port_name, 1000000)
425 .timeout(Duration::from_secs(5))
426 .open()
427 .unwrap();
428 port.write_request_to_send(false).unwrap();
429 std::thread::sleep(Duration::from_millis(100));
430
431 let mut tool = Box::new(Self { base, port });
432 if tool.base.before.should_download_stub() {
433 tool.download_stub().expect("Failed to download stub");
434 }
435 tool
436 }
437}
438
439impl SifliToolTrait for SF32LB56Tool {
440 fn port(&mut self) -> &mut Box<dyn SerialPort> {
441 &mut self.port
442 }
443
444 fn base(&self) -> &SifliToolBase {
445 &self.base
446 }
447
448 fn set_speed(&mut self, baud: u32) -> Result<()> {
449 use crate::speed::SpeedTrait;
450 SpeedTrait::set_speed(self, baud)
451 }
452
453 fn soft_reset(&mut self) -> Result<()> {
454 use crate::reset::Reset;
455 Reset::soft_reset(self)
456 }
457}