use crate::architecture::arm::communication_interface::RegisterParseError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum DataSize {
U8 = 0b000,
U16 = 0b001,
#[default]
U32 = 0b010,
U64 = 0b011,
U128 = 0b100,
U256 = 0b101,
}
impl DataSize {
pub fn to_byte_count(self) -> usize {
match self {
DataSize::U8 => 1,
DataSize::U16 => 2,
DataSize::U32 => 4,
DataSize::U64 => 8,
DataSize::U128 => 16,
DataSize::U256 => 32,
}
}
}
pub struct InvalidDataSizeError;
impl TryFrom<u8> for DataSize {
type Error = InvalidDataSizeError;
fn try_from(value: u8) -> Result<Self, InvalidDataSizeError> {
match value {
0b000 => Ok(DataSize::U8),
0b001 => Ok(DataSize::U16),
0b010 => Ok(DataSize::U32),
0b011 => Ok(DataSize::U64),
0b100 => Ok(DataSize::U128),
0b101 => Ok(DataSize::U256),
_ => Err(InvalidDataSizeError),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AddressIncrement {
Off = 0b00,
#[default]
Single = 0b01,
Packed = 0b10,
}
impl AddressIncrement {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0b00 => Some(AddressIncrement::Off),
0b01 => Some(AddressIncrement::Single),
0b10 => Some(AddressIncrement::Packed),
_ => None,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
pub enum BaseAddrFormat {
#[default]
Legacy = 0,
ADIv5 = 1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[allow(dead_code)] pub enum DebugEntryState {
#[default]
NotPresent = 0,
Present = 1,
}
define_ap_register!(
name: CSW,
address: 0x00,
fields: [
DbgSwEnable: bool, Prot: u8, SPIDEN: bool, _RES0: u8, MTE: bool, Type: u8, Mode: u8, TrInProg: bool, DeviceEn: bool, AddrInc: AddressIncrement, _RES1: u8, SIZE: DataSize, ],
from: value => Ok(CSW {
DbgSwEnable: ((value >> 31) & 0x01) != 0,
Prot: ((value >> 24) & 0x7F) as u8,
SPIDEN: ((value >> 23) & 0x01) != 0,
_RES0: ((value >> 16) & 0x7F) as u8,
MTE: ((value >> 15) & 0x01) != 0,
Type: ((value >> 12) & 0x07) as u8,
Mode: ((value >> 8) & 0x0F) as u8,
TrInProg: ((value >> 7) & 0x01) != 0,
DeviceEn: ((value >> 6) & 0x01) != 0,
AddrInc: AddressIncrement::from_u8(((value >> 4) & 0x03) as u8).ok_or_else(|| RegisterParseError::new("CSW", value))?,
_RES1: ((value >> 3) & 1) as u8,
SIZE: DataSize::try_from((value & 0x07) as u8).map_err(|_| RegisterParseError::new("CSW", value))?,
}),
to: value => (u32::from(value.DbgSwEnable) << 31)
| (u32::from(value.Prot ) << 24)
| (u32::from(value.SPIDEN ) << 23)
| (u32::from(value._RES0 ) << 16)
| (u32::from(value.MTE ) << 15)
| (u32::from(value.Type ) << 12)
| (u32::from(value.Mode ) << 8)
| (u32::from(value.TrInProg ) << 7)
| (u32::from(value.DeviceEn ) << 6)
| (u32::from(value.AddrInc as u8) << 4)
| (u32::from(value._RES1 ) << 1)
| (value.SIZE as u32)
);
define_ap_register!(
name: TAR,
address: 0x04,
fields: [
address: u32,
],
from: value => Ok(TAR { address: value }),
to: value => value.address
);
define_ap_register!(
name: TAR2,
address: 0x08,
fields: [
address: u32,
],
from: value => Ok(TAR2 { address: value }),
to: value => value.address
);
define_ap_register!(
name: DRW,
address: 0x0C,
fields: [
data: u32,
],
from: value => Ok(DRW { data: value }),
to: value => value.data
);
define_ap_register!(
name: BD0,
address: 0x10,
fields: [
data: u32,
],
from: value => Ok(BD0 { data: value }),
to: value => value.data
);
define_ap_register!(
name: BD1,
address: 0x14,
fields: [
data: u32,
],
from: value => Ok(BD1 { data: value }),
to: value => value.data
);
define_ap_register!(
name: BD2,
address: 0x18,
fields: [
data: u32,
],
from: value => Ok(BD2 { data: value }),
to: value => value.data
);
define_ap_register!(
name: BD3,
address: 0x1C,
fields: [
data: u32,
],
from: value => Ok(BD3 { data: value }),
to: value => value.data
);
define_ap_register!(
name: MBT,
address: 0x20,
fields: [
data: u32,
],
from: value => Ok(MBT { data: value }),
to: value => value.data
);
define_ap_register!(
name: BASE2,
address: 0xF0,
fields: [
BASEADDR: u32
],
from: value => Ok(BASE2 { BASEADDR: value }),
to: value => value.BASEADDR
);
define_ap_register!(
name: CFG,
address: 0xF4,
fields: [
LD: bool,
LA: bool,
BE: bool,
],
from: value => Ok(CFG {
LD: ((value >> 2) & 0x01) != 0,
LA: ((value >> 1) & 0x01) != 0,
BE: (value & 0x01) != 0,
}),
to: value => ((value.LD as u32) << 2) | ((value.LA as u32) << 1) | (value.BE as u32)
);
define_ap_register!(
name: BASE,
address: 0xF8,
fields: [
BASEADDR: u32,
_RES0: u8,
Format: BaseAddrFormat,
present: bool,
],
from: value => Ok(BASE {
BASEADDR: (value & 0xFFFF_F000) >> 12,
_RES0: 0,
Format: match ((value >> 1) & 0x01) as u8 {
0 => BaseAddrFormat::Legacy,
1 => BaseAddrFormat::ADIv5,
_ => panic!("This is a bug. Please report it."),
},
present: match (value & 0x01) as u8 {
0 => false,
1 => true,
_ => panic!("This is a bug. Please report it."),
},
}),
to: value =>
(value.BASEADDR << 12)
| (u32::from(value.Format as u8) << 1)
| u32::from(value.present)
);