sftool_lib/sf32lb56/
mod.rs

1//! SF32LB56 芯片特定实现模块
2
3pub 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
21// Define SF32LB56FrameFormat here to avoid import issues
22pub 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        // SF32LB56 uses big-endian for data length
29        header.extend_from_slice(&len.to_be_bytes());
30        // SF32LB56 adds 4-byte timestamp (fixed to 0)
31        header.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
32        // Channel number fixed to 0x10
33        header.push(0x10);
34        // CRC fixed to 0x00
35        header.push(0x00);
36        // reserved field (2 bytes, fixed to 0x00)
37        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        // 读取长度 (2字节) - SF32LB56 uses big-endian
45        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        // 读取时间戳 (4字节) - SF32LB56 specific
54        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        // 读取通道和CRC (2字节)
61        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        // SF32LB56: Read 2-byte reserved field
68        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                // SF32LB56 uses big-endian for address and length
92                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                // SF32LB56 uses big-endian for address and data length
99                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        // SF32LB56 uses big-endian
111        u32::from_be_bytes([data[0], data[1], data[2], data[3]])
112    }
113
114    // SF32LB56 specific address mapping function
115    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            // l_addr = addr
120        } else if addr >= 0x00400000 && addr <= 0x0041FFFF {
121            // L_RAM
122            l_addr += 0x20000000;
123        } else if addr >= 0x20C00000 && addr <= 0x20C1FFFF {
124            // L_RAM
125            l_addr -= 0x00800000;
126        } else if addr >= 0x20000000 && addr <= 0x200C7FFF {
127            // H_RAM
128            l_addr += 0x0A000000;
129        } else if addr >= 0x20800000 && addr <= 0x20BFFFFF {
130            // H_RAM
131            l_addr -= 0x20800000;
132        } else if addr >= 0x10000000 && addr <= 0x1FFFFFFF {
133            // EXT_MEM
134            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
145// 为 SF32LB56Tool 实现 Send 和 Sync
146unsafe impl Send for SF32LB56Tool {}
147unsafe impl Sync for SF32LB56Tool {}
148
149// SifliDebug trait implementation for SF32LB56Tool
150impl 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    /// 执行全部flash擦除的内部方法
191    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        // 发送擦除所有命令
199        let _ = self.command(Command::EraseAll { address });
200
201        let mut buffer = Vec::new();
202        let now = std::time::SystemTime::now();
203
204        // 等待擦除完成
205        loop {
206            let elapsed = now.elapsed().unwrap().as_millis();
207            if elapsed > 30000 {
208                // 擦除可能需要更长时间
209                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            // 检查擦除完成响应
224            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    /// 执行区域擦除的内部方法
235    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        // 发送擦除区域命令
245        let _ = self.command(Command::Erase { address, len });
246
247        let mut buffer = Vec::new();
248        let now = std::time::SystemTime::now();
249
250        // 等待擦除完成
251        loop {
252            let elapsed = now.elapsed().unwrap().as_millis();
253            if elapsed > 30000 {
254                // 擦除可能需要更长时间
255                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            // 检查擦除完成响应
270            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                // 使用RTS引脚复位
296                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            // 如果有限重试,检查是否还有机会
309            if let Some(ref mut attempts) = remaining_attempts {
310                if *attempts == 0 {
311                    break; // 超过最大重试次数则退出循环
312                }
313                *attempts -= 1;
314            }
315
316            let progress = self.progress();
317            let spinner = progress.create_spinner("Connecting to chip...");
318
319            // 尝试连接
320            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        // 0.0 HCPU Unconditional halt
348        self.debug_halt()?;
349        //  0.1 HPSYS_AON->ISSR->LP_ACTIVE
350        let mut data = self.debug_read_word32(0x4004_0028)?;
351        if data & 0x20 != 0 {
352            data = 0xa05f0003;
353            // LCPU Halt
354            self.debug_write_word32(0x3000_EDF0, data)?;
355        }
356
357        // 1. reset and halt
358        //    1.1. reset_catch_set
359        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        // 1.2. reset_system
365        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()); // MCU已经重启,不一定能收到正确回复
369        std::thread::sleep(std::time::Duration::from_millis(10));
370
371        // 1.3. Re-enter debug mode
372        self.debug_command(SifliUartCommand::Enter)?;
373
374        // 1.4. halt
375        self.debug_halt()?;
376
377        // 1.5. reset_catch_clear
378        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        // 2. Download stub
385        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        // 3. run ram stub
410        // 3.1. set SP and PC
411        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        // 3.2. run
425        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}