Skip to main content

airfrog_core/arm/
map.rs

1// Copyright (C) 2025 Piers Finlayson <piers@piers.rocks>
2//
3// MIT License
4
5//! ARM Memory Access Port Registers
6
7use crate::arm::register::{ApRegister, ReadableRegister, RegisterDescriptor, WritableRegister};
8use crate::register_data_rw;
9use alloc::{format, string::String};
10use core::fmt;
11
12/// Control/Status Word Register descriptor (read-write)
13pub struct CswRegister;
14
15impl RegisterDescriptor for CswRegister {
16    const ADDRESS: u8 = 0x00;
17    type Value = Csw;
18}
19
20impl ReadableRegister for CswRegister {}
21impl WritableRegister for CswRegister {}
22impl ApRegister for CswRegister {}
23
24/// Control/Status Word register data
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub struct Csw(u32);
27
28// Standard register data impls
29register_data_rw!(Csw);
30
31impl Csw {
32    // Field masks and shifts
33    const SIZE_MASK: u32 = 0b111;
34    const SIZE_SHIFT: u32 = 0;
35
36    const ADDRINC_MASK: u32 = 0b11;
37    const ADDRINC_SHIFT: u32 = 4;
38
39    const DEVICE_EN: u32 = 1 << 6;
40    const TR_IN_PROG: u32 = 1 << 7;
41
42    const MODE_MASK: u32 = 0b1111;
43    const MODE_SHIFT: u32 = 8;
44
45    const TYPE_MASK: u32 = 0b111;
46    const TYPE_SHIFT: u32 = 12;
47
48    const MTE: u32 = 1 << 15;
49
50    // SPIDEN is read only
51    const SPIDEN: u32 = 1 << 23;
52
53    const PROT_MASK: u32 = 0b1111111;
54    const PROT_SHIFT: u32 = 24;
55
56    const DBG_SW_ENABLE: u32 = 1 << 31;
57
58    const RESERVED_HIGH: u32 = 1 << 24;
59
60    // Size values
61    pub const SIZE_8BIT: u32 = 0b000;
62    pub const SIZE_16BIT: u32 = 0b001;
63    pub const SIZE_32BIT: u32 = 0b010;
64    pub const SIZE_64BIT: u32 = 0b011;
65    pub const SIZE_128BIT: u32 = 0b100;
66    pub const SIZE_256BIT: u32 = 0b101;
67
68    // Address increment values
69    pub const ADDRINC_OFF: u32 = 0b00;
70    pub const ADDRINC_SINGLE: u32 = 0b01;
71    pub const ADDRINC_PACKED: u32 = 0b10;
72
73    // Prot values
74    pub const PROT_MASTER_DEBUG: u32 = 1 << 5;
75    pub const PROT_BIT_1: u32 = 1 << 1;
76
77    /// Get raw register value
78    pub fn value(&self) -> u32 {
79        self.0
80    }
81
82    /// Get size field
83    pub fn size(&self) -> u32 {
84        (self.0 >> Self::SIZE_SHIFT) & Self::SIZE_MASK
85    }
86
87    /// Get address increment field
88    pub fn addrinc(&self) -> u32 {
89        (self.0 >> Self::ADDRINC_SHIFT) & Self::ADDRINC_MASK
90    }
91
92    /// Get device enable flag
93    pub fn device_en(&self) -> bool {
94        self.0 & Self::DEVICE_EN != 0
95    }
96
97    /// Get transfer in progress flag
98    pub fn tr_in_prog(&self) -> bool {
99        self.0 & Self::TR_IN_PROG != 0
100    }
101
102    /// Get mode field
103    pub fn mode(&self) -> u32 {
104        (self.0 >> Self::MODE_SHIFT) & Self::MODE_MASK
105    }
106
107    /// Get type field
108    pub fn type_bits(&self) -> u32 {
109        (self.0 >> Self::TYPE_SHIFT) & Self::TYPE_MASK
110    }
111
112    /// Get MTE flag
113    pub fn mte(&self) -> bool {
114        self.0 & Self::MTE != 0
115    }
116
117    /// Get SPIDEN flag
118    pub fn spiden(&self) -> bool {
119        self.0 & Self::SPIDEN != 0
120    }
121
122    /// Get protection field
123    pub fn prot(&self) -> u32 {
124        (self.0 >> Self::PROT_SHIFT) & Self::PROT_MASK
125    }
126
127    /// Get debug software enable flag
128    pub fn dbg_sw_enable(&self) -> bool {
129        self.0 & Self::DBG_SW_ENABLE != 0
130    }
131
132    // Setters
133    pub fn set_reserved_high(&mut self) {
134        self.0 |= Self::RESERVED_HIGH;
135    }
136
137    /// Set size field
138    pub fn set_size(&mut self, size: u32) {
139        self.0 = (self.0 & !(Self::SIZE_MASK << Self::SIZE_SHIFT))
140            | ((size & Self::SIZE_MASK) << Self::SIZE_SHIFT);
141    }
142
143    /// Set address increment field
144    pub fn set_addrinc(&mut self, addrinc: u32) {
145        self.0 = (self.0 & !(Self::ADDRINC_MASK << Self::ADDRINC_SHIFT))
146            | ((addrinc & Self::ADDRINC_MASK) << Self::ADDRINC_SHIFT);
147    }
148
149    /// Set device enable flag
150    pub fn set_device_en(&mut self, enable: bool) {
151        if enable {
152            self.0 |= Self::DEVICE_EN;
153        } else {
154            self.0 &= !Self::DEVICE_EN;
155        }
156    }
157
158    /// Set mode field
159    pub fn set_mode(&mut self, mode: u32) {
160        self.0 = (self.0 & !(Self::MODE_MASK << Self::MODE_SHIFT))
161            | ((mode & Self::MODE_MASK) << Self::MODE_SHIFT);
162    }
163
164    /// Set type field
165    pub fn set_type(&mut self, type_bits: u32) {
166        self.0 = (self.0 & !(Self::TYPE_MASK << Self::TYPE_SHIFT))
167            | ((type_bits & Self::TYPE_MASK) << Self::TYPE_SHIFT);
168    }
169
170    /// Set MTE flag
171    pub fn set_mte(&mut self, enable: bool) {
172        if enable {
173            self.0 |= Self::MTE;
174        } else {
175            self.0 &= !Self::MTE;
176        }
177    }
178
179    /// Set SPIDEN flag
180    pub fn set_spiden(&mut self, enable: bool) {
181        if enable {
182            self.0 |= Self::SPIDEN;
183        } else {
184            self.0 &= !Self::SPIDEN;
185        }
186    }
187
188    /// Set protection field
189    pub fn set_prot(&mut self, prot: u32) {
190        self.0 = (self.0 & !(Self::PROT_MASK << Self::PROT_SHIFT))
191            | ((prot & Self::PROT_MASK) << Self::PROT_SHIFT);
192    }
193
194    /// Set debug software enable flag
195    pub fn set_dbg_sw_enable(&mut self, enable: bool) {
196        if enable {
197            self.0 |= Self::DBG_SW_ENABLE;
198        } else {
199            self.0 &= !Self::DBG_SW_ENABLE;
200        }
201    }
202
203    /// Get transfer configuration description
204    pub fn transfer_config(&self) -> String {
205        let size = match self.size() {
206            Self::SIZE_8BIT => "8-bit",
207            Self::SIZE_16BIT => "16-bit",
208            Self::SIZE_32BIT => "32-bit",
209            Self::SIZE_64BIT => "64-bit",
210            Self::SIZE_128BIT => "128-bit",
211            Self::SIZE_256BIT => "256-bit",
212            _ => "Reserved",
213        };
214
215        let addrinc = match self.addrinc() {
216            Self::ADDRINC_OFF => "Off",
217            Self::ADDRINC_SINGLE => "Single",
218            Self::ADDRINC_PACKED => "Packed",
219            _ => "Reserved",
220        };
221
222        format!("Size: {size}, AddrInc: {addrinc}")
223    }
224
225    /// Get status flags description
226    pub fn status_flags(&self) -> String {
227        let mut flags = [""; 6];
228        let mut count = 0;
229
230        if self.device_en() {
231            flags[count] = "DEVICE_EN";
232            count += 1;
233        }
234        if self.tr_in_prog() {
235            flags[count] = "TR_IN_PROG";
236            count += 1;
237        }
238        if self.mte() {
239            flags[count] = "MTE";
240            count += 1;
241        }
242        if self.spiden() {
243            flags[count] = "SPIDEN";
244            count += 1;
245        }
246        if self.dbg_sw_enable() {
247            flags[count] = "DBG_SW_ENABLE";
248            count += 1;
249        }
250
251        if count == 0 {
252            "No flags set".into()
253        } else {
254            format!("Flags: {}", flags[..count].join(", "))
255        }
256    }
257
258    /// Get security state description
259    pub fn security_state(&self) -> String {
260        format!(
261            "PROT: 0x{:02x}, SPIDEN: {}, DBG_SW: {}",
262            self.prot(),
263            if self.spiden() { "Y" } else { "N" },
264            if self.dbg_sw_enable() { "Y" } else { "N" }
265        )
266    }
267}
268
269impl Default for Csw {
270    fn default() -> Self {
271        let mut csw = Csw(0);
272        csw.set_reserved_high();
273        csw.set_prot(Self::PROT_MASTER_DEBUG | Self::PROT_BIT_1);
274        csw.set_size(Self::SIZE_32BIT);
275        csw.set_addrinc(Self::ADDRINC_OFF);
276        csw.set_device_en(true);
277
278        csw
279    }
280}
281
282/// Transfer Address Register descriptor (read-write)
283pub struct TarRegister;
284
285impl RegisterDescriptor for TarRegister {
286    const ADDRESS: u8 = 0x04;
287    type Value = Tar;
288}
289
290impl ReadableRegister for TarRegister {}
291impl WritableRegister for TarRegister {}
292impl ApRegister for TarRegister {}
293
294/// Transfer Address Register data
295#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
296pub struct Tar(u32);
297
298// Standard register data impls
299register_data_rw!(Tar);
300
301impl Tar {
302    /// Get raw register value
303    pub fn value(&self) -> u32 {
304        self.0
305    }
306
307    /// Get target address
308    pub fn target_address(&self) -> u32 {
309        self.0
310    }
311
312    /// Set target address
313    pub fn set_target_address(&mut self, address: u32) {
314        self.0 = address;
315    }
316}
317
318/// Data Read/Write Register descriptor (read-write)
319pub struct DrwRegister;
320
321impl RegisterDescriptor for DrwRegister {
322    const ADDRESS: u8 = 0x0C;
323    type Value = Drw;
324}
325
326impl ReadableRegister for DrwRegister {}
327impl WritableRegister for DrwRegister {}
328impl ApRegister for DrwRegister {}
329
330/// Data Read/Write Register data
331#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
332pub struct Drw(u32);
333
334// Standard register data impls
335register_data_rw!(Drw);
336
337impl Drw {
338    /// Get raw register value
339    pub fn value(&self) -> u32 {
340        self.0
341    }
342
343    /// Get data value
344    pub fn data(&self) -> u32 {
345        self.0
346    }
347
348    /// Set data value
349    pub fn set_data(&mut self, data: u32) {
350        self.0 = data;
351    }
352}
353
354/// Banked Data Register 0 descriptor (read-write)
355pub struct Bd0Register;
356
357impl RegisterDescriptor for Bd0Register {
358    const ADDRESS: u8 = 0x10;
359    type Value = BankedData;
360}
361
362impl ReadableRegister for Bd0Register {}
363impl WritableRegister for Bd0Register {}
364impl ApRegister for Bd0Register {}
365
366/// Banked Data Register 1 descriptor (read-write)
367pub struct Bd1Register;
368
369impl RegisterDescriptor for Bd1Register {
370    const ADDRESS: u8 = 0x14;
371    type Value = BankedData;
372}
373
374impl ReadableRegister for Bd1Register {}
375impl WritableRegister for Bd1Register {}
376impl ApRegister for Bd1Register {}
377
378/// Banked Data Register 2 descriptor (read-write)
379pub struct Bd2Register;
380
381impl RegisterDescriptor for Bd2Register {
382    const ADDRESS: u8 = 0x18;
383    type Value = BankedData;
384}
385
386impl ReadableRegister for Bd2Register {}
387impl WritableRegister for Bd2Register {}
388impl ApRegister for Bd2Register {}
389
390/// Banked Data Register 3 descriptor (read-write)
391pub struct Bd3Register;
392
393impl RegisterDescriptor for Bd3Register {
394    const ADDRESS: u8 = 0x1C;
395    type Value = BankedData;
396}
397
398impl ReadableRegister for Bd3Register {}
399impl WritableRegister for Bd3Register {}
400impl ApRegister for Bd3Register {}
401
402/// MEM-AP Banked Data register data
403///
404/// Used as based for [`Bd0Register`], [`Bd1Register`], [`Bd2Register`], and
405/// [`Bd3Register`].
406
407#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
408pub struct BankedData(u32);
409
410// Standard register data impls
411register_data_rw!(BankedData);
412
413impl BankedData {
414    /// Get data value
415    pub fn data(&self) -> u32 {
416        self.0
417    }
418
419    /// Set data value
420    pub fn set_data(&mut self, data: u32) {
421        self.0 = data;
422    }
423}