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::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
24// Define SF32LB56FrameFormat here to avoid import issues
25pub 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        // SF32LB56 uses big-endian for data length
32        header.extend_from_slice(&len.to_be_bytes());
33        // SF32LB56 adds 4-byte timestamp (fixed to 0)
34        header.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
35        // Channel number fixed to 0x10
36        header.push(0x10);
37        // CRC fixed to 0x00
38        header.push(0x00);
39        // reserved field (2 bytes, fixed to 0x00)
40        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        // 读取长度 (2字节) - SF32LB56 uses big-endian
48        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        // 读取时间戳 (4字节) - SF32LB56 specific
57        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        // 读取通道和CRC (2字节)
64        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        // SF32LB56: Read 2-byte reserved field
71        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                // SF32LB56 uses big-endian for address and length
95                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                // SF32LB56 uses big-endian for address and data length
102                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        // SF32LB56 uses big-endian
114        u32::from_be_bytes([data[0], data[1], data[2], data[3]])
115    }
116
117    // SF32LB56 specific address mapping function
118    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            // l_addr = addr
123        } else if (0x00400000..=0x0041FFFF).contains(&addr) {
124            // L_RAM
125            l_addr += 0x20000000;
126        } else if (0x20C00000..=0x20C1FFFF).contains(&addr) {
127            // L_RAM
128            l_addr -= 0x00800000;
129        } else if (0x20000000..=0x200C7FFF).contains(&addr) {
130            // H_RAM
131            l_addr += 0x0A000000;
132        } else if (0x20800000..=0x20BFFFFF).contains(&addr) {
133            // H_RAM
134            l_addr -= 0x20800000;
135        } else if (0x10000000..=0x1FFFFFFF).contains(&addr) {
136            // EXT_MEM
137            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
148// 为 SF32LB56Tool 实现 Send 和 Sync
149unsafe impl Send for SF32LB56Tool {}
150unsafe impl Sync for SF32LB56Tool {}
151
152// SifliDebug trait implementation for SF32LB56Tool
153impl 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    /// 执行全部flash擦除的内部方法
191    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        // 发送擦除所有命令
201        let _ = self.command(Command::EraseAll { address });
202
203        let mut buffer = Vec::new();
204        let now = std::time::SystemTime::now();
205
206        // 等待擦除完成
207        loop {
208            let elapsed = now.elapsed().unwrap().as_millis();
209            if elapsed > 30000 {
210                // 擦除可能需要更长时间
211                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            // 检查擦除完成响应
225            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    /// 执行区域擦除的内部方法
236    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        // 发送擦除区域命令
247        let _ = self.command(Command::Erase { address, len });
248
249        let mut buffer = Vec::new();
250        let now = std::time::SystemTime::now();
251
252        // 等待擦除完成
253        loop {
254            let elapsed = now.elapsed().unwrap().as_millis();
255            if elapsed > 30000 {
256                // 擦除可能需要更长时间
257                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            // 检查擦除完成响应
271            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                // 使用RTS引脚复位
293                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            // 如果有限重试,检查是否还有机会
303            if let Some(ref mut attempts) = remaining_attempts {
304                if *attempts == 0 {
305                    break; // 超过最大重试次数则退出循环
306                }
307                *attempts -= 1;
308            }
309
310            let progress = self.progress();
311            let spinner = progress.create_spinner(ProgressOperation::Connect);
312
313            // 尝试连接
314            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        // 0.0 HCPU Unconditional halt
341        self.debug_halt()?;
342        //  0.1 HPSYS_AON->ISSR->LP_ACTIVE
343        let mut data = self.debug_read_word32(0x4004_0028)?;
344        if data & 0x20 != 0 {
345            data = 0xa05f0003;
346            // LCPU Halt
347            self.debug_write_word32(0x3000_EDF0, data)?;
348        }
349
350        // 1. reset and halt
351        //    1.1. reset_catch_set
352        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        // 1.2. reset_system
358        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()); // MCU已经重启,不一定能收到正确回复
362        std::thread::sleep(std::time::Duration::from_millis(10));
363
364        // 1.3. Re-enter debug mode
365        self.debug_command(SifliUartCommand::Enter)?;
366
367        // 1.4. halt
368        self.debug_halt()?;
369
370        // 1.5. reset_catch_clear
371        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        // 2. Download stub - 支持外部 stub 文件
378        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        // 3. run ram stub
399        // 3.1. set SP and PC
400        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        // 3.2. run
414        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}