#[doc(hidden)]
pub(crate) mod mock;
use super::{AccessPort, ApAccess, ApRegister, GenericAp, Register};
use crate::architecture::arm::{communication_interface::RegisterParseError, ApAddress, ArmError};
use enum_primitive_derive::Primitive;
use num_traits::{FromPrimitive, ToPrimitive};
define_ap!(
MemoryAp
);
impl MemoryAp {
pub fn base_address<A>(&self, interface: &mut A) -> Result<u64, ArmError>
where
A: ApAccess,
{
let base_register: BASE = interface.read_ap_register(*self)?;
let mut base_address = if BaseaddrFormat::ADIv5 == base_register.Format {
let base2: BASE2 = interface.read_ap_register(*self)?;
u64::from(base2.BASEADDR) << 32
} else {
0
};
base_address |= u64::from(base_register.BASEADDR << 12);
Ok(base_address)
}
}
impl From<GenericAp> for MemoryAp {
fn from(other: GenericAp) -> Self {
MemoryAp {
address: other.ap_address(),
}
}
}
#[derive(Debug, Primitive, Clone, Copy, PartialEq, Eq)]
pub enum DataSize {
U8 = 0b000,
U16 = 0b001,
U32 = 0b010,
U64 = 0b011,
U128 = 0b100,
U256 = 0b101,
}
impl DataSize {
pub fn from_bytes(bytes: u8) -> Self {
if bytes == 1 {
DataSize::U8
} else if bytes == 2 {
DataSize::U16
} else if bytes == 4 {
DataSize::U32
} else if bytes == 8 {
DataSize::U64
} else if bytes == 16 {
DataSize::U128
} else if bytes == 32 {
DataSize::U256
} else {
DataSize::U32
}
}
}
impl Default for DataSize {
fn default() -> Self {
DataSize::U32
}
}
#[derive(Debug, Primitive, Clone, Copy, PartialEq, Eq)]
pub enum AddressIncrement {
Off = 0b00,
Single = 0b01,
Packed = 0b10,
}
impl Default for AddressIncrement {
fn default() -> Self {
AddressIncrement::Single
}
}
#[derive(Debug, PartialEq, Eq, Primitive, Clone, Copy)]
pub enum BaseaddrFormat {
Legacy = 0,
ADIv5 = 1,
}
impl Default for BaseaddrFormat {
fn default() -> Self {
BaseaddrFormat::Legacy
}
}
#[derive(Debug, Primitive, Clone, Copy, PartialEq, Eq)]
pub enum DebugEntryState {
NotPresent = 0,
Present = 1,
}
impl Default for DebugEntryState {
fn default() -> Self {
DebugEntryState::NotPresent
}
}
define_ap_register!(
type: MemoryAp,
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)
);
define_ap_register!(
type: MemoryAp,
name: BASE2,
address: 0xF0,
fields: [
BASEADDR: u32
],
from: value => Ok(BASE2 { BASEADDR: value }),
to: value => value.BASEADDR
);
define_ap_register!(
type: MemoryAp,
name: BD0,
address: 0x10,
fields: [
data: u32,
],
from: value => Ok(BD0 { data: value }),
to: value => value.data
);
define_ap_register!(
type: MemoryAp,
name: BD1,
address: 0x14,
fields: [
data: u32,
],
from: value => Ok(BD1 { data: value }),
to: value => value.data
);
define_ap_register!(
type: MemoryAp,
name: BD2,
address: 0x18,
fields: [
data: u32,
],
from: value => Ok(BD2 { data: value }),
to: value => value.data
);
define_ap_register!(
type: MemoryAp,
name: BD3,
address: 0x1C,
fields: [
data: u32,
],
from: value => Ok(BD3 { data: value }),
to: value => value.data
);
define_ap_register!(
type: MemoryAp,
name: CFG,
address: 0xF4,
fields: [
LD: u8,
LA: u8,
BE: u8,
],
from: value => Ok(CFG {
LD: ((value >> 2) & 0x01) as u8,
LA: ((value >> 1) & 0x01) as u8,
BE: (value & 0x01) as u8,
}),
to: value => u32::from((value.LD << 2) | (value.LA << 1) | value.BE)
);
define_ap_register!(
type: MemoryAp,
name: CSW,
address: 0x00,
fields: [
DbgSwEnable: u8, HNONSEC: u8, PROT: u8, CACHE: u8, SPIDEN: u8, _RES0: u8, MTE: u8, Type: u8, Mode: u8, TrinProg: u8, DeviceEn: u8, AddrInc: AddressIncrement, _RES1: u8, SIZE: DataSize, ],
from: value => Ok(CSW {
DbgSwEnable: ((value >> 31) & 0x01) as u8,
HNONSEC: ((value >> 30) & 0x01) as u8,
PROT: ((value >> 28) & 0x03) as u8,
CACHE: ((value >> 24) & 0x0F) as u8,
SPIDEN: ((value >> 23) & 0x01) as u8,
_RES0: 0,
MTE: ((value >> 15) & 0x01) as u8,
Type: ((value >> 12) & 0x07) as u8,
Mode: ((value >> 8) & 0x0F) as u8,
TrinProg: ((value >> 7) & 0x01) as u8,
DeviceEn: ((value >> 6) & 0x01) as u8,
AddrInc: AddressIncrement::from_u8(((value >> 4) & 0x03) as u8).ok_or_else(|| RegisterParseError::new("CSW", value))?,
_RES1: 0,
SIZE: DataSize::from_u8((value & 0x07) as u8).ok_or_else(|| RegisterParseError::new("CSW", value))?,
}),
to: value => (u32::from(value.DbgSwEnable) << 31)
| (u32::from(value.HNONSEC ) << 30)
| (u32::from(value.PROT ) << 28)
| (u32::from(value.CACHE ) << 24)
| (u32::from(value.SPIDEN ) << 23)
| (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)
| value.SIZE.to_u32().unwrap()
);
impl CSW {
pub fn new(data_size: DataSize) -> Self {
CSW {
DbgSwEnable: 0b1,
HNONSEC: 0b1,
PROT: 0b110,
CACHE: 0b11,
AddrInc: AddressIncrement::Single,
SIZE: data_size,
..Default::default()
}
}
}
define_ap_register!(
type: MemoryAp,
name: DRW,
address: 0x0C,
fields: [
data: u32,
],
from: value => Ok(DRW { data: value }),
to: value => value.data
);
define_ap_register!(
type: MemoryAp,
name: MBT,
address: 0x20,
fields: [
data: u32,
],
from: value => Ok(MBT { data: value }),
to: value => value.data
);
define_ap_register!(
type: MemoryAp,
name: TAR,
address: 0x04,
fields: [
address: u32,
],
from: value => Ok(TAR { address: value }),
to: value => value.address
);
define_ap_register!(
type: MemoryAp,
name: TAR2,
address: 0x08,
fields: [
address: u32,
],
from: value => Ok(TAR2 { address: value }),
to: value => value.address
);