Skip to main content

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::serial_io::is_cancelled_io_error;
12use crate::common::serial_io::{for_tool, sleep_with_cancel};
13use crate::common::sifli_debug::{
14    ChipFrameFormat, RecvError, START_WORD, SifliDebug, SifliUartCommand, SifliUartResponse,
15    common_debug,
16};
17use crate::progress::{
18    EraseFlashStyle, EraseRegionStyle, ProgressOperation, ProgressStatus, StubStage,
19};
20use crate::sf32lb56::ram_command::DownloadStub;
21use crate::{Result, SifliTool, SifliToolBase, SifliToolTrait};
22use serialport::SerialPort;
23use std::io::{BufReader, Read};
24use std::time::Duration;
25
26// Define SF32LB56FrameFormat here to avoid import issues
27pub struct SF32LB56FrameFormat;
28
29impl ChipFrameFormat for SF32LB56FrameFormat {
30    fn create_header(len: u16) -> Vec<u8> {
31        let mut header = vec![];
32        header.extend_from_slice(&START_WORD);
33        // SF32LB56 uses big-endian for data length
34        header.extend_from_slice(&len.to_be_bytes());
35        // SF32LB56 adds 4-byte timestamp (fixed to 0)
36        header.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
37        // Channel number fixed to 0x10
38        header.push(0x10);
39        // CRC fixed to 0x00
40        header.push(0x00);
41        // reserved field (2 bytes, fixed to 0x00)
42        header.extend_from_slice(&[0x00, 0x00]);
43        header
44    }
45
46    fn parse_frame_header<R: Read>(
47        reader: &mut BufReader<R>,
48    ) -> std::result::Result<usize, RecvError> {
49        // 读取长度 (2字节) - SF32LB56 uses big-endian
50        let mut length_bytes = [0; 2];
51        if let Err(e) = reader.read_exact(&mut length_bytes) {
52            if is_cancelled_io_error(&e) {
53                return Err(RecvError::Cancelled);
54            }
55            tracing::error!("Failed to read length bytes: {}", e);
56            return Err(RecvError::InvalidHeaderLength);
57        }
58
59        let payload_size = u16::from_be_bytes(length_bytes) as usize;
60
61        // 读取时间戳 (4字节) - SF32LB56 specific
62        let mut timestamp_bytes = [0; 4];
63        if let Err(e) = reader.read_exact(&mut timestamp_bytes) {
64            if is_cancelled_io_error(&e) {
65                return Err(RecvError::Cancelled);
66            }
67            tracing::error!("Failed to read timestamp bytes: {}", e);
68            return Err(RecvError::InvalidHeaderChannel);
69        }
70
71        // 读取通道和CRC (2字节)
72        let mut channel_crc = [0; 2];
73        if let Err(e) = reader.read_exact(&mut channel_crc) {
74            if is_cancelled_io_error(&e) {
75                return Err(RecvError::Cancelled);
76            }
77            tracing::error!("Failed to read channel and CRC bytes: {}", e);
78            return Err(RecvError::InvalidHeaderChannel);
79        }
80
81        // SF32LB56: Read 2-byte reserved field
82        let mut reserved_bytes = [0; 2];
83        if let Err(e) = reader.read_exact(&mut reserved_bytes) {
84            if is_cancelled_io_error(&e) {
85                return Err(RecvError::Cancelled);
86            }
87            tracing::error!("Failed to read reserved bytes: {}", e);
88            return Err(RecvError::ReadError(e));
89        }
90
91        Ok(payload_size)
92    }
93
94    fn encode_command_data(command: &SifliUartCommand) -> Vec<u8> {
95        let mut send_data = vec![];
96        match command {
97            SifliUartCommand::Enter => {
98                let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x05, 0x21];
99                send_data.extend_from_slice(&temp);
100            }
101            SifliUartCommand::Exit => {
102                let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x18, 0x21];
103                send_data.extend_from_slice(&temp);
104            }
105            SifliUartCommand::MEMRead { addr, len } => {
106                send_data.push(0x40);
107                send_data.push(0x72);
108                // SF32LB56 uses big-endian for address and length
109                send_data.extend_from_slice(&addr.to_be_bytes());
110                send_data.extend_from_slice(&len.to_be_bytes());
111            }
112            SifliUartCommand::MEMWrite { addr, data } => {
113                send_data.push(0x40);
114                send_data.push(0x77);
115                // SF32LB56 uses big-endian for address and data length
116                send_data.extend_from_slice(&addr.to_be_bytes());
117                send_data.extend_from_slice(&(data.len() as u16).to_be_bytes());
118                for d in data.iter() {
119                    send_data.extend_from_slice(&d.to_be_bytes());
120                }
121            }
122        }
123        send_data
124    }
125
126    fn decode_response_data(data: &[u8]) -> u32 {
127        // SF32LB56 uses big-endian
128        u32::from_be_bytes([data[0], data[1], data[2], data[3]])
129    }
130
131    // SF32LB56 specific address mapping function
132    fn map_address(addr: u32) -> u32 {
133        let mut l_addr = addr;
134        if (0xE0000000..0xF0000000).contains(&addr) {
135            l_addr = (addr & 0x0fffffff) | 0xF0000000;
136            // l_addr = addr
137        } else if (0x00400000..=0x0041FFFF).contains(&addr) {
138            // L_RAM
139            l_addr += 0x20000000;
140        } else if (0x20C00000..=0x20C1FFFF).contains(&addr) {
141            // L_RAM
142            l_addr -= 0x00800000;
143        } else if (0x20000000..=0x200C7FFF).contains(&addr) {
144            // H_RAM
145            l_addr += 0x0A000000;
146        } else if (0x20800000..=0x20BFFFFF).contains(&addr) {
147            // H_RAM
148            l_addr -= 0x20800000;
149        } else if (0x10000000..=0x1FFFFFFF).contains(&addr) {
150            // EXT_MEM
151            l_addr += 0x50000000;
152        }
153        l_addr
154    }
155}
156
157pub struct SF32LB56Tool {
158    pub base: SifliToolBase,
159    pub port: Box<dyn SerialPort>,
160}
161
162// 为 SF32LB56Tool 实现 Send 和 Sync
163unsafe impl Send for SF32LB56Tool {}
164unsafe impl Sync for SF32LB56Tool {}
165
166// SifliDebug trait implementation for SF32LB56Tool
167impl SifliDebug for SF32LB56Tool {
168    fn debug_command(&mut self, command: SifliUartCommand) -> Result<SifliUartResponse> {
169        common_debug::debug_command_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, command)
170    }
171
172    fn debug_read_word32(&mut self, addr: u32) -> Result<u32> {
173        common_debug::debug_read_word32_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, addr)
174    }
175
176    fn debug_write_word32(&mut self, addr: u32, data: u32) -> Result<()> {
177        common_debug::debug_write_word32_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, addr, data)
178    }
179
180    fn debug_write_memory(&mut self, addr: u32, data: &[u8]) -> Result<()> {
181        common_debug::debug_write_memory_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self, addr, data)
182    }
183
184    fn debug_write_core_reg(&mut self, reg: u16, data: u32) -> Result<()> {
185        common_debug::debug_write_core_reg_impl::<SF32LB56Tool, SF32LB56FrameFormat>(
186            self, reg, data,
187        )
188    }
189
190    fn debug_step(&mut self) -> Result<()> {
191        common_debug::debug_step_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
192    }
193
194    fn debug_run(&mut self) -> Result<()> {
195        common_debug::debug_run_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
196    }
197
198    fn debug_halt(&mut self) -> Result<()> {
199        common_debug::debug_halt_impl::<SF32LB56Tool, SF32LB56FrameFormat>(self)
200    }
201}
202
203impl SF32LB56Tool {
204    /// 执行全部flash擦除的内部方法
205    pub fn internal_erase_all(&mut self, address: u32) -> Result<()> {
206        use ram_command::{Command, RamCommand};
207
208        let progress = self.progress();
209        let spinner = progress.create_spinner(ProgressOperation::EraseFlash {
210            address,
211            style: EraseFlashStyle::Addressed,
212        });
213
214        // 发送擦除所有命令
215        let _ = self.command(Command::EraseAll { address });
216
217        let mut io = for_tool(self);
218        io.wait_for_pattern(
219            b"OK",
220            Duration::from_millis(30_000),
221            &format!("erasing flash at 0x{:08X}", address),
222        )?;
223
224        spinner.finish(ProgressStatus::Success);
225
226        Ok(())
227    }
228
229    /// 执行区域擦除的内部方法
230    pub fn internal_erase_region(&mut self, address: u32, len: u32) -> Result<()> {
231        use ram_command::{Command, RamCommand};
232
233        let progress = self.progress();
234        let spinner = progress.create_spinner(ProgressOperation::EraseRegion {
235            address,
236            len,
237            style: EraseRegionStyle::HexLength,
238        });
239
240        // 发送擦除区域命令
241        let _ = self.command(Command::Erase { address, len });
242
243        let mut io = for_tool(self);
244        io.wait_for_pattern(
245            b"OK",
246            Duration::from_millis(30_000),
247            &format!("erasing region at 0x{:08X}", address),
248        )?;
249
250        spinner.finish(ProgressStatus::Success);
251
252        Ok(())
253    }
254
255    pub fn attempt_connect(&mut self) -> Result<()> {
256        use crate::common::sifli_debug::{SifliUartCommand, SifliUartResponse};
257
258        let infinite_attempts = self.base.connect_attempts <= 0;
259        let mut remaining_attempts = if infinite_attempts {
260            None
261        } else {
262            Some(self.base.connect_attempts)
263        };
264        loop {
265            if self.base.before.requires_reset() {
266                // 使用RTS引脚复位
267                let mut io = for_tool(self);
268                io.write_request_to_send(true)?;
269                io.sleep(Duration::from_millis(100))?;
270                io.write_request_to_send(false)?;
271                io.sleep(Duration::from_millis(100))?;
272            }
273            let value: Result<()> = match self.debug_command(SifliUartCommand::Enter) {
274                Ok(SifliUartResponse::Enter) => Ok(()),
275                _ => Err(std::io::Error::other("Failed to enter debug mode").into()),
276            };
277            // 如果有限重试,检查是否还有机会
278            if let Some(ref mut attempts) = remaining_attempts {
279                if *attempts == 0 {
280                    break; // 超过最大重试次数则退出循环
281                }
282                *attempts -= 1;
283            }
284
285            let progress = self.progress();
286            let spinner = progress.create_spinner(ProgressOperation::Connect);
287
288            // 尝试连接
289            match value {
290                Ok(_) => {
291                    spinner.finish(ProgressStatus::Success);
292                    return Ok(());
293                }
294                Err(_) => {
295                    spinner.finish(ProgressStatus::Retry);
296                    sleep_with_cancel(&self.base.cancel_token, Duration::from_millis(500))?;
297                }
298            }
299        }
300        Err(std::io::Error::other("Failed to connect to the chip").into())
301    }
302
303    pub fn download_stub_impl(&mut self) -> Result<()> {
304        use crate::common::sifli_debug::SifliUartCommand;
305        use crate::ram_stub::load_stub_file;
306        use probe_rs::MemoryMappedRegister;
307        use probe_rs::architecture::arm::core::armv7m::{Aircr, Demcr};
308        use probe_rs::architecture::arm::core::registers::cortex_m::{PC, SP};
309
310        let progress = self.progress();
311        let spinner = progress.create_spinner(ProgressOperation::DownloadStub {
312            stage: StubStage::Start,
313        });
314
315        // 0.0 HCPU Unconditional halt
316        self.debug_halt()?;
317        //  0.1 HPSYS_AON->ISSR->LP_ACTIVE
318        let mut data = self.debug_read_word32(0x4004_0028)?;
319        if data & 0x20 != 0 {
320            data = 0xa05f0003;
321            // LCPU Halt
322            self.debug_write_word32(0x3000_EDF0, data)?;
323        }
324
325        // 1. reset and halt
326        //    1.1. reset_catch_set
327        let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
328        let mut demcr = Demcr(demcr);
329        demcr.set_vc_corereset(true);
330        self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
331
332        // 1.2. reset_system
333        let mut aircr = Aircr(0);
334        aircr.vectkey();
335        aircr.set_sysresetreq(true);
336        let _ = self.debug_write_word32(Aircr::get_mmio_address() as u32, aircr.into()); // MCU已经重启,不一定能收到正确回复
337        sleep_with_cancel(
338            &self.base.cancel_token,
339            std::time::Duration::from_millis(10),
340        )?;
341
342        // 1.3. Re-enter debug mode
343        self.debug_command(SifliUartCommand::Enter)?;
344
345        // 1.4. halt
346        self.debug_halt()?;
347
348        // 1.5. reset_catch_clear
349        let demcr = self.debug_read_word32(Demcr::get_mmio_address() as u32)?;
350        let mut demcr = Demcr(demcr);
351        demcr.set_vc_corereset(false);
352        self.debug_write_word32(Demcr::get_mmio_address() as u32, demcr.into())?;
353
354        sleep_with_cancel(
355            &self.base.cancel_token,
356            std::time::Duration::from_millis(100),
357        )?;
358        // 2. Download stub - 支持外部 stub 文件
359        let chip_memory_key = format!("sf32lb56_{}", self.base.memory_type);
360        let stub = match load_stub_file(self.base.external_stub_path.as_deref(), &chip_memory_key) {
361            Ok(s) => s,
362            Err(e) => {
363                spinner.finish(ProgressStatus::NotFound);
364                return Err(e.into());
365            }
366        };
367
368        let packet_size = if self.base.compat { 256 } else { 64 * 1024 };
369
370        let mut addr = 0x2006_7000;
371        let mut data = &stub.data[..];
372        while !data.is_empty() {
373            let chunk = &data[..std::cmp::min(data.len(), packet_size)];
374            self.debug_write_memory(addr, chunk)?;
375            addr += chunk.len() as u32;
376            data = &data[chunk.len()..];
377        }
378
379        // 3. run ram stub
380        // 3.1. set SP and PC
381        let sp = u32::from_le_bytes(
382            stub.data[0..4]
383                .try_into()
384                .expect("slice with exactly 4 bytes"),
385        );
386        let pc = u32::from_le_bytes(
387            stub.data[4..8]
388                .try_into()
389                .expect("slice with exactly 4 bytes"),
390        );
391        self.debug_write_core_reg(PC.id.0, pc)?;
392        self.debug_write_core_reg(SP.id.0, sp)?;
393
394        // 3.2. run
395        self.debug_run()?;
396
397        spinner.finish(ProgressStatus::Success);
398
399        Ok(())
400    }
401}
402
403impl SifliTool for SF32LB56Tool {
404    fn create_tool(base: SifliToolBase) -> Box<dyn SifliTool> {
405        let mut port = serialport::new(&base.port_name, 1000000)
406            .timeout(Duration::from_secs(5))
407            .open()
408            .unwrap();
409        port.write_request_to_send(false).unwrap();
410        std::thread::sleep(Duration::from_millis(100));
411
412        let mut tool = Box::new(Self { base, port });
413        if tool.base.before.should_download_stub() {
414            tool.download_stub().expect("Failed to download stub");
415        }
416        tool
417    }
418}
419
420impl SifliToolTrait for SF32LB56Tool {
421    fn port(&mut self) -> &mut Box<dyn SerialPort> {
422        &mut self.port
423    }
424
425    fn base(&self) -> &SifliToolBase {
426        &self.base
427    }
428
429    fn set_speed(&mut self, baud: u32) -> Result<()> {
430        use crate::speed::SpeedTrait;
431        SpeedTrait::set_speed(self, baud)
432    }
433
434    fn soft_reset(&mut self) -> Result<()> {
435        use crate::reset::Reset;
436        Reset::soft_reset(self)
437    }
438}