probe_rs/probe/sifliuart/
mod.rs1mod arm;
5
6use crate::Error;
7use crate::architecture::arm::sequences::ArmDebugSequence;
8use crate::architecture::arm::{ArmDebugInterface, ArmError};
9use crate::probe::sifliuart::arm::SifliUartArmDebug;
10use crate::probe::{
11 DebugProbe, DebugProbeError, DebugProbeInfo, DebugProbeSelector, ProbeCreationError,
12 ProbeFactory, WireProtocol,
13};
14use serialport::{SerialPort, SerialPortType, available_ports};
15use std::io::{BufReader, BufWriter, Read, Write};
16use std::sync::Arc;
17use std::time::{Duration, Instant};
18use std::{env, fmt};
19
20const START_WORD: [u8; 2] = [0x7E, 0x79];
21
22const DEFUALT_RECV_TIMEOUT: Duration = Duration::from_secs(3);
23
24const DEFUALT_UART_BAUD: u32 = 1000000;
25
26#[derive(Debug)]
27pub(crate) enum SifliUartCommand<'a> {
28 Enter,
29 Exit,
30 MEMRead { addr: u32, len: u16 },
31 MEMWrite { addr: u32, data: &'a [u32] },
32}
33
34enum SifliUartResponse {
35 Enter,
36 Exit,
37 MEMRead { data: Vec<u8> },
38 MEMWrite,
39}
40
41impl fmt::Display for SifliUartCommand<'_> {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 match self {
44 SifliUartCommand::Enter => write!(f, "Enter"),
45 SifliUartCommand::Exit => write!(f, "Exit"),
46 SifliUartCommand::MEMRead { addr, len } => {
47 write!(f, "MEMRead {{ addr: {addr:#X}, len: {len:#X} }}")
48 }
49 SifliUartCommand::MEMWrite { addr, data } => {
50 write!(f, "MEMWrite {{ addr: {addr:#X}, data: [")?;
51 for (i, d) in data.iter().enumerate() {
52 if i > 0 {
53 write!(f, ", ")?;
54 }
55 write!(f, "{d:#X}")?;
56 }
57 write!(f, "] }}")
58 }
59 }
60 }
61}
62
63impl fmt::Display for SifliUartResponse {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 match self {
66 SifliUartResponse::Enter => write!(f, "Enter"),
67 SifliUartResponse::Exit => write!(f, "Exit"),
68 SifliUartResponse::MEMRead { data } => {
69 write!(f, "MEMRead {{ data: [")?;
70 for (i, byte) in data.iter().enumerate() {
71 if i > 0 {
72 write!(f, ", ")?;
73 }
74 write!(f, "{byte:#04X}")?;
75 }
76 write!(f, "] }}")
77 }
78 SifliUartResponse::MEMWrite => write!(f, "MEMWrite"),
79 }
80 }
81}
82
83#[derive(Debug, thiserror::Error)]
84enum CommandError {
85 ParameterError(std::io::Error),
86 ProbeError(std::io::Error),
89 }
91
92impl fmt::Display for CommandError {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 match self {
95 CommandError::ParameterError(e) => write!(f, "ParameterError({e})"),
96 CommandError::ProbeError(e) => write!(f, "ProbeError({e})"),
99 }
101 }
102}
103
104pub struct SifliUart {
106 reader: BufReader<Box<dyn Read + Send>>,
107 writer: BufWriter<Box<dyn Write + Send>>,
108 _serial_port: Box<dyn SerialPort>,
109 baud: u32,
110}
111
112impl fmt::Debug for SifliUart {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 f.debug_struct("SifliUart")
115 .field("baud", &self.baud)
116 .finish()
117 }
118}
119
120impl fmt::Display for SifliUart {
121 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
122 write!(f, "Sifli UART Debug Probe")
123 }
124}
125
126impl SifliUart {
127 pub fn new(
129 reader: Box<dyn Read + Send>,
130 writer: Box<dyn Write + Send>,
131 port: Box<dyn SerialPort>,
132 ) -> Result<Self, DebugProbeError> {
133 let reader = BufReader::new(reader);
134 let writer = BufWriter::new(writer);
135
136 let probe = SifliUart {
137 reader,
138 writer,
139 baud: DEFUALT_UART_BAUD,
140 _serial_port: port,
141 };
142 Ok(probe)
143 }
144
145 fn create_header(len: u16) -> Vec<u8> {
146 let mut header = vec![];
147 header.extend_from_slice(&START_WORD);
148 header.extend_from_slice(&len.to_le_bytes());
149 header.push(0x10);
150 header.push(0x00);
151 header
152 }
153
154 fn send(
155 writer: &mut BufWriter<Box<dyn Write + Send>>,
156 command: &SifliUartCommand,
157 ) -> Result<(), CommandError> {
158 let mut send_data = vec![];
159 match command {
160 SifliUartCommand::Enter => {
161 let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x05, 0x21];
162 send_data.extend_from_slice(&temp);
163 }
164 SifliUartCommand::Exit => {
165 let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x18, 0x21];
166 send_data.extend_from_slice(&temp);
167 }
168 SifliUartCommand::MEMRead { addr, len } => {
169 send_data.push(0x40);
170 send_data.push(0x72);
171 send_data.extend_from_slice(&addr.to_le_bytes());
172 send_data.extend_from_slice(&len.to_le_bytes());
173 }
174 SifliUartCommand::MEMWrite { addr, data } => {
175 send_data.push(0x40);
176 send_data.push(0x77);
177 send_data.extend_from_slice(&addr.to_le_bytes());
178 send_data.extend_from_slice(&(data.len() as u16).to_le_bytes());
179 for d in data.iter() {
180 send_data.extend_from_slice(&d.to_le_bytes());
181 }
182 }
183 }
184
185 let header = Self::create_header(send_data.len() as u16);
186 writer
187 .write_all(&header)
188 .map_err(CommandError::ProbeError)?;
189 writer
190 .write_all(&send_data)
191 .map_err(CommandError::ProbeError)?;
192 writer.flush().map_err(CommandError::ProbeError)?;
193
194 Ok(())
195 }
196
197 fn recv(
198 reader: &mut BufReader<Box<dyn Read + Send>>,
199 ) -> Result<SifliUartResponse, CommandError> {
200 let start_time = Instant::now();
201 let mut buffer = vec![];
202 let mut recv_data = vec![];
203
204 loop {
205 if start_time.elapsed() >= DEFUALT_RECV_TIMEOUT {
206 return Err(CommandError::ParameterError(std::io::Error::new(
207 std::io::ErrorKind::TimedOut,
208 "Timeout",
209 )));
210 }
211
212 let mut byte = [0; 1];
213 if reader.read_exact(&mut byte).is_err() {
214 continue;
215 }
216
217 if (byte[0] == START_WORD[0]) || (buffer.len() == 1 && byte[0] == START_WORD[1]) {
218 buffer.push(byte[0]);
219 } else {
220 buffer.clear();
221 }
222 tracing::info!("Recv buffer: {:?}", buffer);
223
224 if buffer.ends_with(&START_WORD) {
225 let err = Err(CommandError::ParameterError(std::io::Error::new(
226 std::io::ErrorKind::InvalidData,
227 "Invalid frame size",
228 )));
229 recv_data.clear();
230 let mut temp = [0; 2];
232 if reader.read_exact(&mut temp).is_err() {
233 return err;
234 }
235 let size = u16::from_le_bytes(temp);
236 tracing::info!("Recv size: {}", size);
237
238 if reader.read_exact(&mut temp).is_err() {
240 return err;
241 }
242
243 while recv_data.len() < size as usize {
244 if reader.read_exact(&mut byte).is_err() {
245 return err;
246 }
247 recv_data.push(byte[0]);
248 tracing::info!("Recv data: {:?}", recv_data);
249 }
250 break;
251 } else if buffer.len() == 2 {
252 buffer.clear();
253 }
254 }
255
256 if recv_data[recv_data.len() - 1] != 0x06 {
257 return Err(CommandError::ParameterError(std::io::Error::new(
258 std::io::ErrorKind::InvalidData,
259 "Invalid end of frame",
260 )));
261 }
262
263 match recv_data[0] {
264 0xD1 => Ok(SifliUartResponse::Enter),
265 0xD0 => Ok(SifliUartResponse::Exit),
266 0xD2 => {
267 let data = recv_data[1..recv_data.len() - 1].to_vec();
268 Ok(SifliUartResponse::MEMRead { data })
269 }
270 0xD3 => Ok(SifliUartResponse::MEMWrite),
271 _ => Err(CommandError::ParameterError(std::io::Error::new(
272 std::io::ErrorKind::InvalidData,
273 "Invalid frame type",
274 ))),
275 }
276 }
277
278 fn command(&mut self, command: SifliUartCommand) -> Result<SifliUartResponse, CommandError> {
279 tracing::info!("Command: {}", command);
280 let ret = Self::send(&mut self.writer, &command);
281 if let Err(e) = ret {
282 tracing::error!("Command send error: {:?}", e);
283 return Err(e);
284 }
285
286 match command {
287 SifliUartCommand::Exit => Ok(SifliUartResponse::Exit),
288 _ => Self::recv(&mut self.reader),
289 }
290 }
291}
292
293impl DebugProbe for SifliUart {
294 fn get_name(&self) -> &str {
295 "Sifli UART Debug Probe"
296 }
297
298 fn speed_khz(&self) -> u32 {
299 self.baud / 1000
300 }
301
302 fn set_speed(&mut self, speed_khz: u32) -> Result<u32, DebugProbeError> {
303 self.baud = speed_khz * 1000;
304
305 Ok(speed_khz)
306 }
307
308 fn attach(&mut self) -> Result<(), DebugProbeError> {
309 let ret = self.command(SifliUartCommand::Enter);
310 if let Err(e) = ret {
311 tracing::error!("Enter command error: {:?}", e);
312 return Err(DebugProbeError::NotAttached);
313 }
314 Ok(())
315 }
316
317 fn detach(&mut self) -> Result<(), Error> {
318 let ret = self.command(SifliUartCommand::Exit);
319 if let Err(e) = ret {
320 tracing::error!("Exit command error: {:?}", e);
321 return Err(Error::from(DebugProbeError::Other(
322 "Exit command error".to_string(),
323 )));
324 }
325 Ok(())
326 }
327
328 fn target_reset(&mut self) -> Result<(), DebugProbeError> {
329 todo!()
330 }
331
332 fn target_reset_assert(&mut self) -> Result<(), DebugProbeError> {
333 todo!()
334 }
335
336 fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError> {
337 todo!()
338 }
339
340 fn select_protocol(&mut self, protocol: WireProtocol) -> Result<(), DebugProbeError> {
341 match protocol {
342 WireProtocol::Swd => Ok(()),
343 _ => Err(DebugProbeError::UnsupportedProtocol(protocol)),
344 }
345 }
346
347 fn active_protocol(&self) -> Option<WireProtocol> {
348 Some(WireProtocol::Swd)
349 }
350
351 fn has_arm_interface(&self) -> bool {
352 true
353 }
354
355 fn try_get_arm_debug_interface<'probe>(
356 self: Box<Self>,
357 sequence: Arc<dyn ArmDebugSequence>,
358 ) -> Result<Box<dyn ArmDebugInterface + 'probe>, (Box<dyn DebugProbe>, ArmError)> {
359 Ok(Box::new(SifliUartArmDebug::new(self, sequence)))
360 }
361
362 fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
363 self
364 }
365}
366
367#[derive(Debug)]
369pub struct SifliUartFactory;
370
371impl SifliUartFactory {
372 fn is_sifli_uart(port_type: SerialPortType, port_name: &str) -> Option<DebugProbeInfo> {
373 if cfg!(target_os = "macos") && !port_name.contains("/cu.") {
376 return None;
377 }
378
379 let usb_info = match port_type {
380 SerialPortType::UsbPort(info) => info,
381 _ => return None,
382 };
383
384 if env::var("SIFLI_UART_DEBUG").is_err()
385 && (usb_info.product.is_none()
386 || !usb_info
387 .product
388 .as_ref()
389 .unwrap()
390 .to_lowercase()
391 .contains("sifli"))
392 {
393 return None;
394 }
395
396 let vendor_id = usb_info.vid;
397 let product_id = usb_info.pid;
398 let serial_number = Some(port_name.to_string()); let interface = usb_info.interface;
400 let identifier = "Sifli uart debug probe".to_string();
401
402 Some(DebugProbeInfo {
403 identifier,
404 vendor_id,
405 product_id,
406 serial_number,
407 probe_factory: &SifliUartFactory,
408 interface,
409 is_hid_interface: false,
410 })
411 }
412
413 fn open_port(&self, port_name: &str) -> Result<Box<dyn DebugProbe>, DebugProbeError> {
414 let mut port = serialport::new(port_name, DEFUALT_UART_BAUD)
415 .dtr_on_open(false)
416 .timeout(Duration::from_secs(3))
417 .open()
418 .map_err(|_| {
419 DebugProbeError::ProbeCouldNotBeCreated(ProbeCreationError::CouldNotOpen)
420 })?;
421 port.write_data_terminal_ready(false).map_err(|_| {
422 DebugProbeError::ProbeCouldNotBeCreated(ProbeCreationError::CouldNotOpen)
423 })?;
424 port.write_request_to_send(false).map_err(|_| {
425 DebugProbeError::ProbeCouldNotBeCreated(ProbeCreationError::CouldNotOpen)
426 })?;
427
428 let reader = port.try_clone().map_err(|_| {
429 DebugProbeError::ProbeCouldNotBeCreated(ProbeCreationError::CouldNotOpen)
430 })?;
431 let writer = reader.try_clone().map_err(|_| {
432 DebugProbeError::ProbeCouldNotBeCreated(ProbeCreationError::CouldNotOpen)
433 })?;
434
435 SifliUart::new(Box::new(reader), Box::new(writer), port)
436 .map(|probe| Box::new(probe) as Box<dyn DebugProbe>)
437 }
438}
439
440impl std::fmt::Display for SifliUartFactory {
441 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
442 f.write_str("SifliUart")
443 }
444}
445
446impl ProbeFactory for SifliUartFactory {
447 fn open(&self, selector: &DebugProbeSelector) -> Result<Box<dyn DebugProbe>, DebugProbeError> {
448 let Ok(ports) = available_ports() else {
449 return Err(DebugProbeError::ProbeCouldNotBeCreated(
450 ProbeCreationError::CouldNotOpen,
451 ));
452 };
453
454 if selector.serial_number.is_some() {
455 return self.open_port(selector.serial_number.as_ref().unwrap());
456 }
457
458 for port in ports {
459 let Some(_info) = SifliUartFactory::is_sifli_uart(port.port_type, &port.port_name)
460 else {
461 continue;
462 };
463
464 return self.open_port(&port.port_name);
465 }
466
467 Err(DebugProbeError::ProbeCouldNotBeCreated(
468 ProbeCreationError::NotFound,
469 ))
470 }
471
472 fn list_probes(&self) -> Vec<DebugProbeInfo> {
473 let mut probes = vec![];
474 let Ok(ports) = available_ports() else {
475 return probes;
476 };
477 for port in ports {
478 let Some(info) = SifliUartFactory::is_sifli_uart(port.port_type, &port.port_name)
479 else {
480 continue;
481 };
482 probes.push(info);
483 }
484 probes
485 }
486}