use crate::architecture::arm::{
ArmError, DapAccess, FullyQualifiedApAddress, RegisterParseError,
ap::{
AccessPortType, AddressIncrement, ApAccess, ApRegAccess, ApRegister, CFG, DataSize,
define_ap_register,
},
};
#[derive(Debug)]
pub struct AmbaApb4Apb5 {
address: FullyQualifiedApAddress,
csw: CSW,
cfg: CFG,
}
impl AmbaApb4Apb5 {
pub fn new<P: DapAccess>(
probe: &mut P,
address: FullyQualifiedApAddress,
) -> Result<Self, ArmError> {
let csw = probe.read_raw_ap_register(&address, CSW::ADDRESS)?;
let cfg = probe.read_raw_ap_register(&address, CFG::ADDRESS)?;
let (csw, cfg) = (csw.try_into()?, cfg.try_into()?);
let me = Self { address, csw, cfg };
let csw = CSW {
DbgSwEnable: true,
AddrInc: AddressIncrement::Single,
..me.csw
};
probe.write_ap_register(&me, csw)?;
Ok(Self { csw, ..me })
}
}
impl super::MemoryApType for AmbaApb4Apb5 {
type CSW = CSW;
fn status<P: ApAccess + ?Sized>(&mut self, probe: &mut P) -> Result<CSW, ArmError> {
const { assert!(crate::architecture::arm::ap::CSW::ADDRESS == CSW::ADDRESS) };
self.csw = probe.read_ap_register(self)?;
Ok(self.csw)
}
fn try_set_datasize<P: ApAccess + ?Sized>(
&mut self,
_probe: &mut P,
data_size: DataSize,
) -> Result<(), ArmError> {
match data_size {
DataSize::U32 => Ok(()),
_ => Err(ArmError::UnsupportedTransferWidth(data_size as usize * 8)),
}
}
fn has_large_address_extension(&self) -> bool {
self.cfg.LA
}
fn has_large_data_extension(&self) -> bool {
self.cfg.LD
}
fn supports_only_32bit_data_size(&self) -> bool {
true
}
}
impl AccessPortType for AmbaApb4Apb5 {
fn ap_address(&self) -> &FullyQualifiedApAddress {
&self.address
}
}
impl ApRegAccess<CSW> for AmbaApb4Apb5 {}
super::attached_regs_to_mem_ap!(memory_ap_regs => AmbaApb4Apb5);
define_ap_register!(
name: CSW,
address: 0x00,
fields: [
DbgSwEnable: bool, NonSecure: bool, Privileged: bool, SPIDEN: bool, TrInProg: bool, DeviceEn: bool, AddrInc: AddressIncrement, Size: DataSize, _reserved_bits: u32, ],
from: value => Ok(CSW {
DbgSwEnable: ((value >> 31) & 0x01) != 0,
NonSecure: ((value >> 29) & 0x01) != 0,
Privileged: ((value >> 28) & 0x01) != 0,
SPIDEN: ((value >> 23) & 0x01) != 0,
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))?,
Size: DataSize::try_from((value & 0x07) as u8).map_err(|_| RegisterParseError::new("CSW", value))?,
_reserved_bits: (value & 0x5F7F_FF08),
}),
to: value => (u32::from(value.DbgSwEnable) << 31)
| (u32::from(value.NonSecure) << 29)
| (u32::from(value.Privileged) << 28)
| (u32::from(value.SPIDEN) << 23)
| (u32::from(value.TrInProg) << 7)
| (u32::from(value.DeviceEn) << 6)
| ((value.AddrInc as u32) << 4)
| (value.Size as u32)
| value._reserved_bits
);