1use crate::SifliTool;
2use probe_rs::architecture::arm::armv8m::Dcrdr;
3use probe_rs::{MemoryMappedRegister, RegisterId, memory_mapped_bitfield_register};
4use std::cmp::{max, min};
5use std::fmt;
6use std::io::{BufReader, BufWriter, Read, Write};
7use std::time::{Duration, Instant};
8use probe_rs::architecture::arm::ArmError;
9
10const START_WORD: [u8; 2] = [0x7E, 0x79];
11const DEFUALT_RECV_TIMEOUT: Duration = Duration::from_secs(3);
12const DEFUALT_UART_BAUD: u32 = 1000000;
13
14#[derive(Debug)]
15pub(crate) enum SifliUartCommand<'a> {
16 Enter,
17 Exit,
18 MEMRead { addr: u32, len: u16 },
19 MEMWrite { addr: u32, data: &'a [u32] },
20}
21
22#[derive(Debug)]
23pub(crate) enum SifliUartResponse {
24 Enter,
25 Exit,
26 MEMRead { data: Vec<u8> },
27 MEMWrite,
28}
29
30impl fmt::Display for SifliUartCommand<'_> {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 match self {
33 SifliUartCommand::Enter => write!(f, "Enter"),
34 SifliUartCommand::Exit => write!(f, "Exit"),
35 SifliUartCommand::MEMRead { addr, len } => {
36 write!(f, "MEMRead {{ addr: {:#X}, len: {:#X} }}", addr, len)
37 }
38 SifliUartCommand::MEMWrite { addr, data } => {
39 write!(f, "MEMWrite {{ addr: {:#X}, data: [", addr)?;
40 for (i, d) in data.iter().enumerate() {
41 if i > 0 {
42 write!(f, ", ")?;
43 }
44 write!(f, "{:#X}", d)?;
45 }
46 write!(f, "] }}")
47 }
48 }
49 }
50}
51
52impl fmt::Display for SifliUartResponse {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 match self {
55 SifliUartResponse::Enter => write!(f, "Enter"),
56 SifliUartResponse::Exit => write!(f, "Exit"),
57 SifliUartResponse::MEMRead { data } => {
58 write!(f, "MEMRead {{ data: [")?;
59 for (i, byte) in data.iter().enumerate() {
60 if i > 0 {
61 write!(f, ", ")?;
62 }
63 write!(f, "{:#04X}", byte)?;
64 }
65 write!(f, "] }}")
66 }
67 SifliUartResponse::MEMWrite => write!(f, "MEMWrite"),
68 }
69 }
70}
71
72memory_mapped_bitfield_register! {
73 pub struct Dcrsr(u32);
74 0xE000_EDF4, "DCRSR",
75 impl From;
76 pub _, set_regwnr: 16;
77 pub _, set_regsel: 6,0;
79}
80
81memory_mapped_bitfield_register! {
82 pub struct Dhcsr(u32);
83 0xE000_EDF0, "DHCSR",
84 impl From;
85 pub s_reset_st, _: 25;
86 pub s_retire_st, _: 24;
87 pub s_lockup, _: 19;
88 pub s_sleep, _: 18;
89 pub s_halt, _: 17;
90 pub s_regrdy, _: 16;
91 pub c_maskints, set_c_maskints: 3;
92 pub c_step, set_c_step: 2;
93 pub c_halt, set_c_halt: 1;
94 pub c_debugen, set_c_debugen: 0;
95}
96
97impl Dhcsr {
98 pub fn enable_write(&mut self) {
105 self.0 &= !(0xffff << 16);
106 self.0 |= 0xa05f << 16;
107 }
108}
109
110impl SifliTool {
111 fn create_header(len: u16) -> Vec<u8> {
112 let mut header = vec![];
113 header.extend_from_slice(&START_WORD);
114 header.extend_from_slice(&len.to_le_bytes());
115 header.push(0x10);
116 header.push(0x00);
117 header
118 }
119
120 fn send(
121 writer: &mut BufWriter<Box<dyn Write + Send>>,
122 command: &SifliUartCommand,
123 ) -> Result<(), std::io::Error> {
124 let mut send_data = vec![];
125 match command {
126 SifliUartCommand::Enter => {
127 let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x05, 0x21];
128 send_data.extend_from_slice(&temp);
129 }
130 SifliUartCommand::Exit => {
131 let temp = [0x41, 0x54, 0x53, 0x46, 0x33, 0x32, 0x18, 0x21];
132 send_data.extend_from_slice(&temp);
133 }
134 SifliUartCommand::MEMRead { addr, len } => {
135 send_data.push(0x40);
136 send_data.push(0x72);
137 send_data.extend_from_slice(&addr.to_le_bytes());
138 send_data.extend_from_slice(&len.to_le_bytes());
139 }
140 SifliUartCommand::MEMWrite { addr, data } => {
141 send_data.push(0x40);
142 send_data.push(0x77);
143 send_data.extend_from_slice(&addr.to_le_bytes());
144 send_data.extend_from_slice(&(data.len() as u16).to_le_bytes());
145 for d in data.iter() {
146 send_data.extend_from_slice(&d.to_le_bytes());
147 }
148 }
149 }
150
151 let header = Self::create_header(send_data.len() as u16);
152 writer.write_all(&header)?;
153 writer.write_all(&send_data)?;
154 writer.flush()?;
155
156 Ok(())
157 }
158
159 fn recv(
160 reader: &mut BufReader<Box<dyn Read + Send>>,
161 ) -> Result<SifliUartResponse, std::io::Error> {
162 let start_time = Instant::now();
163 let mut buffer = vec![];
164 let mut recv_data = vec![];
165
166 loop {
167 if start_time.elapsed() >= DEFUALT_RECV_TIMEOUT {
168 return Err(std::io::Error::new(std::io::ErrorKind::TimedOut, "Timeout"));
169 }
170
171 let mut byte = [0; 1];
172 if reader.read_exact(&mut byte).is_err() {
173 continue;
174 }
175
176 if (byte[0] == START_WORD[0]) || (buffer.len() == 1 && byte[0] == START_WORD[1]) {
177 buffer.push(byte[0]);
178 } else {
179 buffer.clear();
180 }
181 tracing::info!("Recv buffer: {:?}", buffer);
182
183 if buffer.ends_with(&START_WORD) {
184 let err = Err(std::io::Error::new(
185 std::io::ErrorKind::InvalidData,
186 "Invalid frame start",
187 ));
188 recv_data.clear();
189 let mut temp = [0; 2];
191 if reader.read_exact(&mut temp).is_err() {
192 return err;
193 }
194 let size = u16::from_le_bytes(temp);
195 tracing::info!("Recv size: {}", size);
196
197 if reader.read_exact(&mut temp).is_err() {
199 return err;
200 }
201
202 while recv_data.len() < size as usize {
203 if reader.read_exact(&mut byte).is_err() {
204 return err;
205 }
206 recv_data.push(byte[0]);
207 tracing::info!("Recv data: {:?}", recv_data);
208 }
209 break;
210 } else if buffer.len() == 2 {
211 buffer.clear();
212 }
213 }
214
215 if recv_data[recv_data.len() - 1] != 0x06 {
216 return Err(std::io::Error::new(
217 std::io::ErrorKind::InvalidData,
218 "Invalid frame end",
219 ));
220 }
221
222 match recv_data[0] {
223 0xD1 => Ok(SifliUartResponse::Enter),
224 0xD0 => Ok(SifliUartResponse::Exit),
225 0xD2 => {
226 let data = recv_data[1..recv_data.len() - 1].to_vec();
227 Ok(SifliUartResponse::MEMRead { data })
228 }
229 0xD3 => Ok(SifliUartResponse::MEMWrite),
230 _ => Err(std::io::Error::new(
231 std::io::ErrorKind::InvalidData,
232 "Invalid response",
233 )),
234 }
235 }
236
237 pub(crate) fn debug_command(
238 &mut self,
239 command: SifliUartCommand,
240 ) -> Result<SifliUartResponse, std::io::Error> {
241 tracing::info!("Command: {}", command);
242 let writer: Box<dyn Write + Send> = self.port.try_clone()?;
243 let mut buf_writer = BufWriter::new(writer);
244
245 let reader: Box<dyn Read + Send> = self.port.try_clone()?;
246 let mut buf_reader = BufReader::new(reader);
247
248 let ret = Self::send(&mut buf_writer, &command);
249 if let Err(e) = ret {
250 tracing::error!("Command send error: {:?}", e);
251 return Err(e);
252 }
253
254 match command {
255 SifliUartCommand::Exit => Ok(SifliUartResponse::Exit),
256 _ => Self::recv(&mut buf_reader),
257 }
258 }
259
260 pub(crate) fn debug_read_word32(&mut self, addr: u32) -> Result<u32, std::io::Error> {
261 let command = SifliUartCommand::MEMRead { addr, len: 1 };
262 match self.debug_command(command) {
263 Ok(SifliUartResponse::MEMRead { data }) => {
264 if data.len() != 4 {
265 return Err(std::io::Error::new(
266 std::io::ErrorKind::InvalidData,
267 "Invalid response length",
268 ));
269 }
270 let value = u32::from_le_bytes(data.try_into().unwrap());
271 Ok(value)
272 }
273 Ok(_) => Err(std::io::Error::new(
274 std::io::ErrorKind::InvalidData,
275 "Invalid response",
276 )),
277 Err(e) => Err(e),
278 }
279 }
280
281 pub(crate) fn debug_write_word32(&mut self, addr: u32, data: u32) -> Result<(), std::io::Error> {
282 let command = SifliUartCommand::MEMWrite {
283 addr,
284 data: &[data],
285 };
286 match self.debug_command(command) {
287 Ok(SifliUartResponse::MEMWrite) => Ok(()),
288 Ok(_) => Err(std::io::Error::new(
289 std::io::ErrorKind::InvalidData,
290 "Invalid response",
291 )),
292 Err(e) => Err(e),
293 }
294 }
295
296 pub(crate) fn debug_write_memory(&mut self, address: u32, data: &[u8]) -> Result<(), std::io::Error> {
297 if data.is_empty() {
298 return Ok(());
299 }
300
301 let address = if (address & 0xff000000) == 0x12000000 {
302 (address & 0x00ffffff) | 0x62000000
303 } else {
304 address
305 };
306
307 let addr_usize = address as usize;
308 let start_aligned = addr_usize - (addr_usize % 4);
310 let end_aligned = (addr_usize + data.len()).div_ceil(4) * 4;
311 let total_bytes = end_aligned - start_aligned;
312 let total_words = total_bytes / 4;
313
314 let mut buffer = vec![0u8; total_bytes];
315
316 for i in 0..total_words {
317 let block_addr = start_aligned + i * 4;
318 let block_end = block_addr + 4;
319
320 if block_addr >= addr_usize && block_end <= addr_usize + data.len() {
323 let offset_in_data = block_addr - addr_usize;
324 buffer[i * 4..i * 4 + 4].copy_from_slice(&data[offset_in_data..offset_in_data + 4]);
325 } else {
326 let resp = self.debug_command(SifliUartCommand::MEMRead {
329 addr: block_addr as u32,
330 len: 1,
331 })?;
332 let mut block: [u8; 4] = match resp {
333 SifliUartResponse::MEMRead { data: d } if d.len() == 4 => {
334 [d[0], d[1], d[2], d[3]]
335 }
336 _ => {
337 return Err(std::io::Error::new(
338 std::io::ErrorKind::InvalidData,
339 "Invalid response length",
340 ));
341 }
342 };
343 let overlap_start = max(block_addr, addr_usize);
345 let overlap_end = min(block_end, addr_usize + data.len());
346 if overlap_start < overlap_end {
347 let in_block_offset = overlap_start - block_addr;
348 let in_data_offset = overlap_start - addr_usize;
349 let overlap_len = overlap_end - overlap_start;
350 block[in_block_offset..in_block_offset + overlap_len]
351 .copy_from_slice(&data[in_data_offset..in_data_offset + overlap_len]);
352 }
353 buffer[i * 4..i * 4 + 4].copy_from_slice(&block);
354 }
355 }
356
357 let words: Vec<u32> = buffer
358 .chunks_exact(4)
359 .map(|chunk| u32::from_le_bytes(chunk.try_into().expect("chunk length is 4")))
360 .collect();
361
362 self.debug_command(SifliUartCommand::MEMWrite {
364 addr: start_aligned as u32,
365 data: &words,
366 })?;
367
368 Ok(())
369 }
370
371 fn wait_for_core_register_transfer(
372 &mut self,
373 timeout: Duration
374 ) -> Result<(), std::io::Error> {
375 let start = Instant::now();
378
379 while start.elapsed() < timeout {
380 let dhcsr_val = Dhcsr(self.debug_read_word32(Dhcsr::get_mmio_address() as u32)?);
381
382 if dhcsr_val.s_regrdy() {
383 return Ok(());
384 }
385 }
386 Err(std::io::Error::new(std::io::ErrorKind::TimedOut, "Timeout"))
387 }
388
389 pub(crate) fn debug_write_core_reg(
390 &mut self,
391 addr: RegisterId,
392 value: u32,
393 ) -> Result<(), std::io::Error> {
394 self.debug_write_word32(Dcrdr::get_mmio_address() as u32, value)?;
395
396 let mut dcrsr_val = Dcrsr(0);
397 dcrsr_val.set_regwnr(true); dcrsr_val.set_regsel(addr.into()); self.debug_write_word32(Dcrsr::get_mmio_address() as u32, dcrsr_val.into())?;
401
402 std::thread::sleep(Duration::from_millis(10));
404 Ok(())
405 }
406
407 fn debug_read_core_reg(&mut self, addr: RegisterId) -> Result<u32, std::io::Error> {
408 let mut dcrsr_val = Dcrsr(0);
410 dcrsr_val.set_regwnr(false); dcrsr_val.set_regsel(addr.into()); self.debug_write_word32(Dcrsr::get_mmio_address() as u32, dcrsr_val.into())?;
414
415 self.wait_for_core_register_transfer(Duration::from_millis(100))?;
416
417 let value = self.debug_read_word32(Dcrdr::get_mmio_address() as u32)?;
418
419 Ok(value)
420 }
421
422 fn debug_step(&mut self)-> Result<(), std::io::Error> {
423 let mut value = Dhcsr(0);
425 value.set_c_step(true);
428 value.set_c_halt(false);
429 value.set_c_debugen(true);
430 value.set_c_maskints(true);
431 value.enable_write();
432
433 self.debug_write_word32(Dhcsr::get_mmio_address() as u32, value.into())?;
434
435 std::thread::sleep(Duration::from_millis(10));
436 Ok(())
437 }
438
439 pub(crate) fn debug_run(&mut self) -> Result<(), std::io::Error> {
440 self.debug_step()?;
441 let mut value = Dhcsr(0);
442 value.set_c_halt(false);
443 value.set_c_debugen(true);
444 value.enable_write();
445
446 self.debug_write_word32(Dhcsr::get_mmio_address() as u32, value.into())?;
447
448 std::thread::sleep(Duration::from_millis(10));
449 Ok(())
450 }
451
452 pub fn debug_halt(&mut self) -> Result<(), std::io::Error> {
453 let mut value = Dhcsr(0);
454 value.set_c_halt(true);
455 value.set_c_debugen(true);
456 value.enable_write();
457
458 self.debug_write_word32(Dhcsr::get_mmio_address() as u32, value.into())?;
459 std::thread::sleep(Duration::from_millis(10));
460 Ok(())
461 }
462}