use crate::arm::register::{ApRegister, ReadableRegister, RegisterDescriptor, WritableRegister};
use crate::register_data_rw;
use alloc::{format, string::String};
use core::fmt;
pub struct CswRegister;
impl RegisterDescriptor for CswRegister {
const ADDRESS: u8 = 0x00;
type Value = Csw;
}
impl ReadableRegister for CswRegister {}
impl WritableRegister for CswRegister {}
impl ApRegister for CswRegister {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Csw(u32);
register_data_rw!(Csw);
impl Csw {
const SIZE_MASK: u32 = 0b111;
const SIZE_SHIFT: u32 = 0;
const ADDRINC_MASK: u32 = 0b11;
const ADDRINC_SHIFT: u32 = 4;
const DEVICE_EN: u32 = 1 << 6;
const TR_IN_PROG: u32 = 1 << 7;
const MODE_MASK: u32 = 0b1111;
const MODE_SHIFT: u32 = 8;
const TYPE_MASK: u32 = 0b111;
const TYPE_SHIFT: u32 = 12;
const MTE: u32 = 1 << 15;
const SPIDEN: u32 = 1 << 23;
const PROT_MASK: u32 = 0b1111111;
const PROT_SHIFT: u32 = 24;
const DBG_SW_ENABLE: u32 = 1 << 31;
const RESERVED_HIGH: u32 = 1 << 24;
pub const SIZE_8BIT: u32 = 0b000;
pub const SIZE_16BIT: u32 = 0b001;
pub const SIZE_32BIT: u32 = 0b010;
pub const SIZE_64BIT: u32 = 0b011;
pub const SIZE_128BIT: u32 = 0b100;
pub const SIZE_256BIT: u32 = 0b101;
pub const ADDRINC_OFF: u32 = 0b00;
pub const ADDRINC_SINGLE: u32 = 0b01;
pub const ADDRINC_PACKED: u32 = 0b10;
pub const PROT_MASTER_DEBUG: u32 = 1 << 5;
pub const PROT_BIT_1: u32 = 1 << 1;
pub fn value(&self) -> u32 {
self.0
}
pub fn size(&self) -> u32 {
(self.0 >> Self::SIZE_SHIFT) & Self::SIZE_MASK
}
pub fn addrinc(&self) -> u32 {
(self.0 >> Self::ADDRINC_SHIFT) & Self::ADDRINC_MASK
}
pub fn device_en(&self) -> bool {
self.0 & Self::DEVICE_EN != 0
}
pub fn tr_in_prog(&self) -> bool {
self.0 & Self::TR_IN_PROG != 0
}
pub fn mode(&self) -> u32 {
(self.0 >> Self::MODE_SHIFT) & Self::MODE_MASK
}
pub fn type_bits(&self) -> u32 {
(self.0 >> Self::TYPE_SHIFT) & Self::TYPE_MASK
}
pub fn mte(&self) -> bool {
self.0 & Self::MTE != 0
}
pub fn spiden(&self) -> bool {
self.0 & Self::SPIDEN != 0
}
pub fn prot(&self) -> u32 {
(self.0 >> Self::PROT_SHIFT) & Self::PROT_MASK
}
pub fn dbg_sw_enable(&self) -> bool {
self.0 & Self::DBG_SW_ENABLE != 0
}
pub fn set_reserved_high(&mut self) {
self.0 |= Self::RESERVED_HIGH;
}
pub fn set_size(&mut self, size: u32) {
self.0 = (self.0 & !(Self::SIZE_MASK << Self::SIZE_SHIFT))
| ((size & Self::SIZE_MASK) << Self::SIZE_SHIFT);
}
pub fn set_addrinc(&mut self, addrinc: u32) {
self.0 = (self.0 & !(Self::ADDRINC_MASK << Self::ADDRINC_SHIFT))
| ((addrinc & Self::ADDRINC_MASK) << Self::ADDRINC_SHIFT);
}
pub fn set_device_en(&mut self, enable: bool) {
if enable {
self.0 |= Self::DEVICE_EN;
} else {
self.0 &= !Self::DEVICE_EN;
}
}
pub fn set_mode(&mut self, mode: u32) {
self.0 = (self.0 & !(Self::MODE_MASK << Self::MODE_SHIFT))
| ((mode & Self::MODE_MASK) << Self::MODE_SHIFT);
}
pub fn set_type(&mut self, type_bits: u32) {
self.0 = (self.0 & !(Self::TYPE_MASK << Self::TYPE_SHIFT))
| ((type_bits & Self::TYPE_MASK) << Self::TYPE_SHIFT);
}
pub fn set_mte(&mut self, enable: bool) {
if enable {
self.0 |= Self::MTE;
} else {
self.0 &= !Self::MTE;
}
}
pub fn set_spiden(&mut self, enable: bool) {
if enable {
self.0 |= Self::SPIDEN;
} else {
self.0 &= !Self::SPIDEN;
}
}
pub fn set_prot(&mut self, prot: u32) {
self.0 = (self.0 & !(Self::PROT_MASK << Self::PROT_SHIFT))
| ((prot & Self::PROT_MASK) << Self::PROT_SHIFT);
}
pub fn set_dbg_sw_enable(&mut self, enable: bool) {
if enable {
self.0 |= Self::DBG_SW_ENABLE;
} else {
self.0 &= !Self::DBG_SW_ENABLE;
}
}
pub fn transfer_config(&self) -> String {
let size = match self.size() {
Self::SIZE_8BIT => "8-bit",
Self::SIZE_16BIT => "16-bit",
Self::SIZE_32BIT => "32-bit",
Self::SIZE_64BIT => "64-bit",
Self::SIZE_128BIT => "128-bit",
Self::SIZE_256BIT => "256-bit",
_ => "Reserved",
};
let addrinc = match self.addrinc() {
Self::ADDRINC_OFF => "Off",
Self::ADDRINC_SINGLE => "Single",
Self::ADDRINC_PACKED => "Packed",
_ => "Reserved",
};
format!("Size: {size}, AddrInc: {addrinc}")
}
pub fn status_flags(&self) -> String {
let mut flags = [""; 6];
let mut count = 0;
if self.device_en() {
flags[count] = "DEVICE_EN";
count += 1;
}
if self.tr_in_prog() {
flags[count] = "TR_IN_PROG";
count += 1;
}
if self.mte() {
flags[count] = "MTE";
count += 1;
}
if self.spiden() {
flags[count] = "SPIDEN";
count += 1;
}
if self.dbg_sw_enable() {
flags[count] = "DBG_SW_ENABLE";
count += 1;
}
if count == 0 {
"No flags set".into()
} else {
format!("Flags: {}", flags[..count].join(", "))
}
}
pub fn security_state(&self) -> String {
format!(
"PROT: 0x{:02x}, SPIDEN: {}, DBG_SW: {}",
self.prot(),
if self.spiden() { "Y" } else { "N" },
if self.dbg_sw_enable() { "Y" } else { "N" }
)
}
}
impl Default for Csw {
fn default() -> Self {
let mut csw = Csw(0);
csw.set_reserved_high();
csw.set_prot(Self::PROT_MASTER_DEBUG | Self::PROT_BIT_1);
csw.set_size(Self::SIZE_32BIT);
csw.set_addrinc(Self::ADDRINC_OFF);
csw.set_device_en(true);
csw
}
}
pub struct TarRegister;
impl RegisterDescriptor for TarRegister {
const ADDRESS: u8 = 0x04;
type Value = Tar;
}
impl ReadableRegister for TarRegister {}
impl WritableRegister for TarRegister {}
impl ApRegister for TarRegister {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Tar(u32);
register_data_rw!(Tar);
impl Tar {
pub fn value(&self) -> u32 {
self.0
}
pub fn target_address(&self) -> u32 {
self.0
}
pub fn set_target_address(&mut self, address: u32) {
self.0 = address;
}
}
pub struct DrwRegister;
impl RegisterDescriptor for DrwRegister {
const ADDRESS: u8 = 0x0C;
type Value = Drw;
}
impl ReadableRegister for DrwRegister {}
impl WritableRegister for DrwRegister {}
impl ApRegister for DrwRegister {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Drw(u32);
register_data_rw!(Drw);
impl Drw {
pub fn value(&self) -> u32 {
self.0
}
pub fn data(&self) -> u32 {
self.0
}
pub fn set_data(&mut self, data: u32) {
self.0 = data;
}
}
pub struct Bd0Register;
impl RegisterDescriptor for Bd0Register {
const ADDRESS: u8 = 0x10;
type Value = BankedData;
}
impl ReadableRegister for Bd0Register {}
impl WritableRegister for Bd0Register {}
impl ApRegister for Bd0Register {}
pub struct Bd1Register;
impl RegisterDescriptor for Bd1Register {
const ADDRESS: u8 = 0x14;
type Value = BankedData;
}
impl ReadableRegister for Bd1Register {}
impl WritableRegister for Bd1Register {}
impl ApRegister for Bd1Register {}
pub struct Bd2Register;
impl RegisterDescriptor for Bd2Register {
const ADDRESS: u8 = 0x18;
type Value = BankedData;
}
impl ReadableRegister for Bd2Register {}
impl WritableRegister for Bd2Register {}
impl ApRegister for Bd2Register {}
pub struct Bd3Register;
impl RegisterDescriptor for Bd3Register {
const ADDRESS: u8 = 0x1C;
type Value = BankedData;
}
impl ReadableRegister for Bd3Register {}
impl WritableRegister for Bd3Register {}
impl ApRegister for Bd3Register {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct BankedData(u32);
register_data_rw!(BankedData);
impl BankedData {
pub fn data(&self) -> u32 {
self.0
}
pub fn set_data(&mut self, data: u32) {
self.0 = data;
}
}