1use crate::arm::register::{DpRegister, ReadableRegister, RegisterDescriptor, WritableRegister};
8use crate::{register_data_r, register_data_rw, register_data_w};
9use alloc::{format, string::String};
10use core::fmt;
11
12pub struct IdCodeRegister;
14
15impl RegisterDescriptor for IdCodeRegister {
16 const ADDRESS: u8 = 0x00;
17 type Value = IdCode;
18}
19
20impl ReadableRegister for IdCodeRegister {}
21impl DpRegister for IdCodeRegister {}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
25pub struct IdCode(u32);
26
27impl IdCode {
28 pub const fn new(value: u32) -> Self {
29 IdCode(value)
30 }
31
32 pub fn data(&self) -> u32 {
33 self.0
34 }
35
36 pub fn revision(&self) -> u8 {
38 ((self.0 >> 28) & 0xF) as u8
39 }
40
41 pub fn part_number(&self) -> u8 {
43 ((self.0 >> 20) & 0xFF) as u8
44 }
45
46 pub fn version(&self) -> u8 {
48 ((self.0 >> 12) & 0xF) as u8
49 }
50
51 pub fn min(&self) -> bool {
53 (self.0 & (1 << 16)) != 0
54 }
55
56 pub fn designer_id(&self) -> u16 {
58 ((self.0 >> 1) & 0x7FF) as u16
59 }
60
61 pub fn is_valid(&self) -> bool {
63 (self.0 & 1) == 1
64 }
65
66 pub fn rao(&self) -> bool {
68 (self.0 & 1) != 0
69 }
70
71 pub fn designer_name(&self) -> &'static str {
73 match self.designer_id() {
74 0x23B => "ARM Ltd",
75 _ => "Unknown",
76 }
77 }
78
79 pub fn part_description(&self) -> &'static str {
81 if self.designer_id() == 0x23B {
82 if self.part_number() == 0xBA {
83 match self.version() {
84 0 => "ARM Debug Port v0",
85 1 => "ARM Debug Port v1",
86 2 => "ARM Debug Port v2",
87 _ => "Unknown ARM Debug Port Version",
88 }
89 } else {
90 "unknown"
91 }
92 } else {
93 "unknown"
94 }
95 }
96
97 pub fn is_arm_debug_port(&self) -> bool {
99 self.designer_id() == 0x23B && self.part_number() == 0xBA
100 }
101
102 pub const fn from_u32(value: u32) -> Self {
103 IdCode(value)
104 }
105}
106
107impl From<u32> for IdCode {
108 fn from(value: u32) -> Self {
109 Self::from_u32(value)
110 }
111}
112
113impl fmt::Display for IdCode {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 if f.alternate() {
116 if !self.is_valid() {
117 return write!(f, "Invalid IDCODE: 0x{:08X} (LSB not set)", self.0);
118 }
119
120 write!(f, "0x{:08X} {}", self.0, self.part_description())
121 } else {
122 write!(f, "0x{:08X}", self.0)
123 }
124 }
125}
126
127impl fmt::LowerHex for IdCode {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 write!(f, "0x{:08x}", self.0)
130 }
131}
132
133impl fmt::UpperHex for IdCode {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 write!(f, "0x{:08X}", self.0)
136 }
137}
138
139pub struct AbortRegister;
141
142impl RegisterDescriptor for AbortRegister {
143 const ADDRESS: u8 = 0x00;
144 type Value = Abort;
145}
146
147impl WritableRegister for AbortRegister {}
148impl DpRegister for AbortRegister {}
149
150#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
152pub struct Abort(u32);
153
154register_data_w!(Abort);
156
157impl Abort {
158 const STKCMPCLR: u32 = 1 << 1;
159 const STKERRCLR: u32 = 1 << 2;
160 const WDERRCLR: u32 = 1 << 3;
161 const ORUNERRCLR: u32 = 1 << 4;
162
163 pub fn set_stkcmpclr(&mut self, enable: bool) {
165 if enable {
166 self.0 |= Self::STKCMPCLR;
167 } else {
168 self.0 &= !Self::STKCMPCLR;
169 }
170 }
171
172 pub fn set_stkerrclr(&mut self, enable: bool) {
174 if enable {
175 self.0 |= Self::STKERRCLR;
176 } else {
177 self.0 &= !Self::STKERRCLR;
178 }
179 }
180
181 pub fn set_wderrclr(&mut self, enable: bool) {
183 if enable {
184 self.0 |= Self::WDERRCLR;
185 } else {
186 self.0 &= !Self::WDERRCLR;
187 }
188 }
189
190 pub fn set_orunerrclr(&mut self, enable: bool) {
192 if enable {
193 self.0 |= Self::ORUNERRCLR;
194 } else {
195 self.0 &= !Self::ORUNERRCLR;
196 }
197 }
198}
199
200pub struct CtrlStatRegister;
202
203impl RegisterDescriptor for CtrlStatRegister {
204 const ADDRESS: u8 = 0x04;
205 type Value = CtrlStat;
206}
207
208impl ReadableRegister for CtrlStatRegister {}
209impl WritableRegister for CtrlStatRegister {}
210impl DpRegister for CtrlStatRegister {}
211
212#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
214pub struct CtrlStat(u32);
215
216register_data_rw!(CtrlStat);
218
219impl CtrlStat {
220 const ORUNDETECT: u32 = 1 << 0;
222 const STICKYORUN: u32 = 1 << 1;
223
224 const TRNMODE_MASK: u32 = 0b11;
225 const TRNMODE_SHIFT: u32 = 2;
226
227 const STICKYCMP: u32 = 1 << 4;
228 const STICKYERR: u32 = 1 << 5;
229 const READOK: u32 = 1 << 6;
230 const WDATAERR: u32 = 1 << 7;
231
232 const MASKLANE_MASK: u32 = 0b1111;
233 const MASKLANE_SHIFT: u32 = 8;
234
235 const TRNCNT_MASK: u32 = 0b111111111111;
236 const TRNCNT_SHIFT: u32 = 12;
237
238 const CDBGRSTREQ: u32 = 1 << 26;
239 const CDBGRSTACK: u32 = 1 << 27;
240 const CDBGPWRUPREQ: u32 = 1 << 28;
241 const CDBGPWRUPACK: u32 = 1 << 29;
242 const CSYSPWRUPREQ: u32 = 1 << 30;
243 const CSYSPWRUPACK: u32 = 1 << 31;
244
245 pub const TRNMODE_NORMAL: u32 = 0b00;
247 pub const TRNMODE_VERIFY: u32 = 0b01;
248 pub const TRNMODE_COMPARE: u32 = 0b10;
249
250 pub fn value(&self) -> u32 {
252 self.0
253 }
254
255 pub fn orundetect(&self) -> bool {
257 self.0 & Self::ORUNDETECT != 0
258 }
259
260 pub fn stickyorun(&self) -> bool {
262 self.0 & Self::STICKYORUN != 0
263 }
264
265 pub fn trnmode(&self) -> u32 {
267 (self.0 >> Self::TRNMODE_SHIFT) & Self::TRNMODE_MASK
268 }
269
270 pub fn stickycmp(&self) -> bool {
272 self.0 & Self::STICKYCMP != 0
273 }
274
275 pub fn stickyerr(&self) -> bool {
277 self.0 & Self::STICKYERR != 0
278 }
279
280 pub fn readok(&self) -> bool {
282 self.0 & Self::READOK != 0
283 }
284
285 pub fn wdataerr(&self) -> bool {
287 self.0 & Self::WDATAERR != 0
288 }
289
290 pub fn masklane(&self) -> u32 {
292 (self.0 >> Self::MASKLANE_SHIFT) & Self::MASKLANE_MASK
293 }
294
295 pub fn trncnt(&self) -> u32 {
297 (self.0 >> Self::TRNCNT_SHIFT) & Self::TRNCNT_MASK
298 }
299
300 pub fn cdbgrstreq(&self) -> bool {
302 self.0 & Self::CDBGRSTREQ != 0
303 }
304
305 pub fn cdbgrstack(&self) -> bool {
307 self.0 & Self::CDBGRSTACK != 0
308 }
309
310 pub fn cdbgpwrupreq(&self) -> bool {
312 self.0 & Self::CDBGPWRUPREQ != 0
313 }
314
315 pub fn cdbgpwrupack(&self) -> bool {
317 self.0 & Self::CDBGPWRUPACK != 0
318 }
319
320 pub fn csyspwrupreq(&self) -> bool {
322 self.0 & Self::CSYSPWRUPREQ != 0
323 }
324
325 pub fn csyspwrupack(&self) -> bool {
327 self.0 & Self::CSYSPWRUPACK != 0
328 }
329
330 pub fn has_errors(&self) -> bool {
331 self.stickyorun()
332 || self.stickycmp()
333 || self.stickyerr()
334 || self.wdataerr()
335 || self.stickyorun()
336 }
337
338 pub fn set_orundetect(&mut self, enable: bool) {
341 if enable {
342 self.0 |= Self::ORUNDETECT;
343 } else {
344 self.0 &= !Self::ORUNDETECT;
345 }
346 }
347
348 pub fn set_stickyorun(&mut self, enable: bool) {
350 if enable {
351 self.0 |= Self::STICKYORUN;
352 } else {
353 self.0 &= !Self::STICKYORUN;
354 }
355 }
356
357 pub fn set_trnmode(&mut self, mode: u32) {
359 self.0 = (self.0 & !(Self::TRNMODE_MASK << Self::TRNMODE_SHIFT))
360 | ((mode & Self::TRNMODE_MASK) << Self::TRNMODE_SHIFT);
361 }
362
363 pub fn set_stickycmp(&mut self, enable: bool) {
365 if enable {
366 self.0 |= Self::STICKYCMP;
367 } else {
368 self.0 &= !Self::STICKYCMP;
369 }
370 }
371
372 pub fn set_stickyerr(&mut self, enable: bool) {
374 if enable {
375 self.0 |= Self::STICKYERR;
376 } else {
377 self.0 &= !Self::STICKYERR;
378 }
379 }
380
381 pub fn set_masklane(&mut self, mask: u32) {
383 self.0 = (self.0 & !(Self::MASKLANE_MASK << Self::MASKLANE_SHIFT))
384 | ((mask & Self::MASKLANE_MASK) << Self::MASKLANE_SHIFT);
385 }
386
387 pub fn set_trncnt(&mut self, count: u32) {
389 self.0 = (self.0 & !(Self::TRNCNT_MASK << Self::TRNCNT_SHIFT))
390 | ((count & Self::TRNCNT_MASK) << Self::TRNCNT_SHIFT);
391 }
392
393 pub fn set_cdbgrstreq(&mut self, enable: bool) {
395 if enable {
396 self.0 |= Self::CDBGRSTREQ;
397 } else {
398 self.0 &= !Self::CDBGRSTREQ;
399 }
400 }
401
402 pub fn set_cdbgpwrupreq(&mut self, enable: bool) {
404 if enable {
405 self.0 |= Self::CDBGPWRUPREQ;
406 } else {
407 self.0 &= !Self::CDBGPWRUPREQ;
408 }
409 }
410
411 pub fn set_csyspwrupreq(&mut self, enable: bool) {
413 if enable {
414 self.0 |= Self::CSYSPWRUPREQ;
415 } else {
416 self.0 &= !Self::CSYSPWRUPREQ;
417 }
418 }
419
420 pub fn error_states(&self) -> String {
423 let mut errors = [""; 5];
424 let mut count = 0;
425
426 if self.stickyorun() {
427 errors[count] = "STICKYORUN";
428 count += 1;
429 }
430 if self.stickycmp() {
431 errors[count] = "STICKYCMP";
432 count += 1;
433 }
434 if self.stickyerr() {
435 errors[count] = "STICKYERR";
436 count += 1;
437 }
438 if self.wdataerr() {
439 errors[count] = "WDATAERR";
440 count += 1;
441 }
442 if self.orundetect() {
443 errors[count] = "ORUNDETECT";
444 count += 1;
445 }
446
447 if count == 0 {
448 format!("No errors{}", if self.readok() { " (READOK)" } else { "" })
449 } else {
450 format!("Errors: {}", errors[..count].join(", "))
451 }
452 }
453
454 pub fn power_states(&self) -> String {
456 format!(
457 "Debug: {}/{}, System: {}/{}",
458 if self.cdbgpwrupreq() { "REQ" } else { "off" },
459 if self.cdbgpwrupack() { "ACK" } else { "nak" },
460 if self.csyspwrupreq() { "REQ" } else { "off" },
461 if self.csyspwrupack() { "ACK" } else { "nak" }
462 )
463 }
464
465 pub fn transaction_state(&self) -> String {
467 let mode = match self.trnmode() {
468 Self::TRNMODE_NORMAL => "Normal",
469 Self::TRNMODE_VERIFY => "Verify",
470 Self::TRNMODE_COMPARE => "Compare",
471 _ => "Reserved",
472 };
473 format!(
474 "Mode: {}, Count: {}, Mask: 0x{:x}",
475 mode,
476 self.trncnt(),
477 self.masklane()
478 )
479 }
480}
481
482pub struct SelectRegister;
484
485impl RegisterDescriptor for SelectRegister {
486 const ADDRESS: u8 = 0x08;
487 type Value = Select;
488}
489
490impl ReadableRegister for SelectRegister {}
491impl WritableRegister for SelectRegister {}
492impl DpRegister for SelectRegister {}
493
494#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
496pub struct Select(u32);
497
498register_data_rw!(Select);
500
501impl Select {
502 const APSEL_MASK: u32 = 0xFF;
504 const APSEL_SHIFT: u32 = 24;
505
506 pub const DPBANKSEL_MASK: u32 = 0xF;
507 pub const DPBANKSEL_SHIFT: u32 = 0;
508
509 pub const APBANKSEL_MASK: u32 = 0xF;
510 pub const APBANKSEL_SHIFT: u32 = 4;
511
512 pub fn value(&self) -> u32 {
514 self.0
515 }
516
517 pub fn apsel(&self) -> u32 {
519 (self.0 >> Self::APSEL_SHIFT) & Self::APSEL_MASK
520 }
521
522 pub fn dpbanksel(&self) -> u32 {
524 (self.0 >> Self::DPBANKSEL_SHIFT) & Self::DPBANKSEL_MASK
525 }
526
527 pub fn apbanksel(&self) -> u32 {
529 (self.0 >> Self::APBANKSEL_SHIFT) & Self::APBANKSEL_MASK
530 }
531
532 pub fn set_apsel(&mut self, apsel: u32) {
534 self.0 = (self.0 & !(Self::APSEL_MASK << Self::APSEL_SHIFT))
535 | ((apsel & Self::APSEL_MASK) << Self::APSEL_SHIFT);
536 }
537
538 pub fn set_dpbanksel(&mut self, banksel: u8) {
540 let banksel = banksel as u32;
541 self.0 = (self.0 & !(Self::DPBANKSEL_MASK << Self::DPBANKSEL_SHIFT))
542 | ((banksel & Self::DPBANKSEL_MASK) << Self::DPBANKSEL_SHIFT);
543 }
544
545 pub fn set_apbanksel(&mut self, banksel: u8) {
547 let banksel = banksel as u32;
548 self.0 = (self.0 & !(Self::APBANKSEL_MASK << Self::APBANKSEL_SHIFT))
549 | ((banksel & Self::APBANKSEL_MASK) << Self::APBANKSEL_SHIFT);
550 }
551
552 pub fn set_dpbanksel_from_addr(&mut self, addr: u8) {
554 let banksel = (addr >> 4) & 0xF;
555 self.set_dpbanksel(banksel);
556 }
557
558 pub fn set_apbanksel_from_addr(&mut self, addr: u8) {
560 let banksel = (addr >> 4) & 0xF;
561 self.set_apbanksel(banksel);
562 }
563
564 pub fn selection_info(&self) -> String {
566 format!(
567 "AP: {}, DP Bank: {}, AP Bank: {}",
568 self.apsel(),
569 self.dpbanksel(),
570 self.apbanksel()
571 )
572 }
573}
574
575pub struct RdBuffRegister;
577
578impl RegisterDescriptor for RdBuffRegister {
579 const ADDRESS: u8 = 0x0C;
580 type Value = RdBuff;
581}
582
583impl ReadableRegister for RdBuffRegister {}
584impl DpRegister for RdBuffRegister {}
585
586#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
588pub struct RdBuff(u32);
589
590register_data_r!(RdBuff);
592
593impl RdBuff {
594 pub fn data(&self) -> u32 {
596 self.0
597 }
598}
599
600pub struct TargetSelRegister;
602
603impl RegisterDescriptor for TargetSelRegister {
604 const ADDRESS: u8 = 0x0C;
605 type Value = TargetSel;
606}
607
608impl WritableRegister for TargetSelRegister {}
609impl DpRegister for TargetSelRegister {}
610
611#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
613pub struct TargetSel(u32);
614
615register_data_w!(TargetSel);
616
617impl TargetSel {
618 pub const fn new(value: u32) -> Self {
619 TargetSel(value)
620 }
621
622 pub fn data(&self) -> u32 {
624 self.0
625 }
626}
627
628impl From<IdCode> for TargetSel {
629 fn from(id: IdCode) -> Self {
630 TargetSel(id.data())
631 }
632}
633
634pub const TARGET_SEL_RP2040_BASE: u32 = 0x01002927;
636pub const TARGET_SEL_RP2040_CORE0: TargetSel = TargetSel(TARGET_SEL_RP2040_BASE);
637pub const TARGET_SEL_RP2040_CORE1: TargetSel = TargetSel(0x1 << 28 | TARGET_SEL_RP2040_BASE);
638pub const TARGET_SEL_RP2040_RESCUE_DP: TargetSel = TargetSel(0xF << 28 | TARGET_SEL_RP2040_BASE);
639
640pub const TARGET_SEL_RP2040_ALL: [TargetSel; 3] = [
641 TARGET_SEL_RP2040_CORE0,
642 TARGET_SEL_RP2040_CORE1,
643 TARGET_SEL_RP2040_RESCUE_DP,
644];