airfrog_core/arm/register.rs
1// Copyright (C) 2025 Piers Finlayson <piers@piers.rocks>
2//
3// MIT License
4
5//! ARM SWD Register Access Traits
6//!
7//! These are used to ensure strongly typed access to reading and writing SWD
8//! registers, using
9//!
10//! * `airfrog_swd::interface::SwdInterface::read_dp_register`
11//! * `airfrog_swd::interface::SwdInterface::read_ap_register`
12//! * `airfrog_swd::interface::SwdInterface::write_dp_register`
13//! * `airfrog_swd::interface::SwdInterface::write_ap_register`
14//!
15//! Unless you are extending the debug/SWD protocol support, it is unlikely
16//! that you will need to use these traits directly.
17
18/// Base trait for all ARM debug register descriptors
19pub trait RegisterDescriptor {
20 const ADDRESS: u8;
21 type Value;
22}
23
24/// Registers that can be read
25pub trait ReadableRegister: RegisterDescriptor {
26 /// Convert raw 32-bit data to register value
27 fn from_raw(data: u32) -> Self::Value
28 where
29 Self::Value: From<u32>,
30 {
31 Self::Value::from(data)
32 }
33}
34
35/// Registers that can be written
36pub trait WritableRegister: RegisterDescriptor {
37 /// Convert register value to raw 32-bit data
38 fn to_raw(value: Self::Value) -> u32
39 where
40 Self::Value: Into<u32>,
41 {
42 value.into()
43 }
44}
45
46/// Debug Port registers (accessed via DP operations)
47pub trait DpRegister: RegisterDescriptor {}
48
49/// Access Port registers (accessed via AP operations)
50pub trait ApRegister: RegisterDescriptor {}
51
52/// Generate a read-only register data type
53#[macro_export]
54macro_rules! register_data_r {
55 ($name:ident) => {
56 // Used to retrieve value
57 impl From<$name> for u32 {
58 fn from(value: $name) -> u32 {
59 value.0
60 }
61 }
62
63 impl From<u32> for $name {
64 fn from(value: u32) -> Self {
65 $name(value)
66 }
67 }
68
69 impl fmt::Display for $name {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 write!(f, "0x{:08X}", self.0)
72 }
73 }
74 };
75}
76
77/// Generate a read-write register data type
78#[macro_export]
79macro_rules! register_data_rw {
80 ($name:ident) => {
81 impl From<$name> for u32 {
82 fn from(value: $name) -> u32 {
83 value.0
84 }
85 }
86
87 impl From<u32> for $name {
88 fn from(value: u32) -> Self {
89 $name(value)
90 }
91 }
92
93 impl fmt::Display for $name {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 write!(f, "0x{:08X}", self.0)
96 }
97 }
98 };
99}
100
101/// Generate a write-only register data type
102#[macro_export]
103macro_rules! register_data_w {
104 ($name:ident) => {
105 impl From<$name> for u32 {
106 fn from(value: $name) -> u32 {
107 value.0
108 }
109 }
110
111 impl fmt::Display for $name {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 write!(f, "0x{:08X}", self.0)
114 }
115 }
116 };
117}