|
| 1 | +use crate::architecture::arm::{ |
| 2 | + ap::{AccessPortType, ApAccess, ApRegAccess}, |
| 3 | + communication_interface::RegisterParseError, |
| 4 | + ArmError, DapAccess, FullyQualifiedApAddress, Register, |
| 5 | +}; |
| 6 | + |
| 7 | +use super::{AddressIncrement, DataSize}; |
| 8 | + |
| 9 | +/// Memory AP |
| 10 | +/// |
| 11 | +/// The memory AP can be used to access a memory-mapped |
| 12 | +/// set of debug resources of the attached system. |
| 13 | +#[derive(Debug)] |
| 14 | +pub struct AmbaAhb3 { |
| 15 | + address: FullyQualifiedApAddress, |
| 16 | + csw: CSW, |
| 17 | + cfg: super::registers::CFG, |
| 18 | +} |
| 19 | + |
| 20 | +impl AmbaAhb3 { |
| 21 | + /// Creates a new AmbaAhb3 with `address` as base address. |
| 22 | + pub fn new<P: DapAccess>( |
| 23 | + probe: &mut P, |
| 24 | + address: FullyQualifiedApAddress, |
| 25 | + ) -> Result<Self, ArmError> { |
| 26 | + use crate::architecture::arm::Register; |
| 27 | + let csw = probe.read_raw_ap_register(&address, CSW::ADDRESS)?; |
| 28 | + let cfg = probe.read_raw_ap_register(&address, super::registers::CFG::ADDRESS)?; |
| 29 | + let (csw, cfg) = (csw.try_into()?, cfg.try_into()?); |
| 30 | + |
| 31 | + let me = Self { address, csw, cfg }; |
| 32 | + let csw = CSW { |
| 33 | + AddrInc: AddressIncrement::Single, |
| 34 | + ..me.csw |
| 35 | + }; |
| 36 | + probe.write_ap_register(&me, csw)?; |
| 37 | + Ok(Self { csw, ..me }) |
| 38 | + } |
| 39 | +} |
| 40 | + |
| 41 | +impl super::MemoryApType for AmbaAhb3 { |
| 42 | + type CSW = CSW; |
| 43 | + |
| 44 | + fn status<P: ApAccess + ?Sized>(&mut self, probe: &mut P) -> Result<Self::CSW, ArmError> { |
| 45 | + assert_eq!(super::registers::CSW::ADDRESS, CSW::ADDRESS); |
| 46 | + self.csw = probe.read_ap_register(self)?; |
| 47 | + Ok(self.csw) |
| 48 | + } |
| 49 | + |
| 50 | + fn try_set_datasize<P: ApAccess + ?Sized>( |
| 51 | + &mut self, |
| 52 | + probe: &mut P, |
| 53 | + data_size: DataSize, |
| 54 | + ) -> Result<(), ArmError> { |
| 55 | + match data_size { |
| 56 | + DataSize::U8 | DataSize::U16 | DataSize::U32 if data_size != self.csw.Size => { |
| 57 | + let csw = CSW { |
| 58 | + Size: data_size, |
| 59 | + ..self.csw |
| 60 | + }; |
| 61 | + probe.write_ap_register(self, csw)?; |
| 62 | + self.csw = csw; |
| 63 | + } |
| 64 | + DataSize::U64 | DataSize::U128 | DataSize::U256 => { |
| 65 | + return Err(ArmError::UnsupportedTransferWidth( |
| 66 | + data_size.to_byte_count() * 8, |
| 67 | + )) |
| 68 | + } |
| 69 | + _ => {} |
| 70 | + } |
| 71 | + Ok(()) |
| 72 | + } |
| 73 | + |
| 74 | + fn has_large_address_extension(&self) -> bool { |
| 75 | + self.cfg.LA |
| 76 | + } |
| 77 | + |
| 78 | + fn has_large_data_extension(&self) -> bool { |
| 79 | + self.cfg.LD |
| 80 | + } |
| 81 | + |
| 82 | + fn supports_only_32bit_data_size(&self) -> bool { |
| 83 | + // Amba AHB3 must support word, half-word and byte size transfers. |
| 84 | + false |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +impl AccessPortType for AmbaAhb3 { |
| 89 | + fn ap_address(&self) -> &FullyQualifiedApAddress { |
| 90 | + &self.address |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +impl ApRegAccess<CSW> for AmbaAhb3 {} |
| 95 | + |
| 96 | +crate::attached_regs_to_mem_ap!(memory_ap_regs => AmbaAhb3); |
| 97 | + |
| 98 | +define_ap_register!( |
| 99 | + /// Control and Status Word register |
| 100 | + /// |
| 101 | + /// The control and status word register (CSW) is used |
| 102 | + /// to configure memory access through the memory AP. |
| 103 | + name: CSW, |
| 104 | + address: 0x00, |
| 105 | + fields: [ |
| 106 | + /// Is debug software access enabled. |
| 107 | + DbgSwEnable: bool, // [31] |
| 108 | + /// HNONSEC |
| 109 | + /// |
| 110 | + /// Not formally defined. |
| 111 | + /// If implemented should be 1 at reset. |
| 112 | + /// If not implemented, should be 1 and writing 0 leads to unpredictable AHB-AP behavior. |
| 113 | + HNONSEC: bool, // [30] |
| 114 | + /// Defines which Requester ID is used on `HMASTER[3:0]` signals. |
| 115 | + /// |
| 116 | + /// Support of this function is implementation defined. |
| 117 | + MasterType: bool, // [29] |
| 118 | + /// Drives `HPROT[4]`, Allocate. |
| 119 | + /// |
| 120 | + /// `HPROT[4]` is an Armv5 extension to AHB. For more information, see the Arm1136JF-S™ and |
| 121 | + /// Arm1136J-S ™ Technical Reference Manual. |
| 122 | + Allocate: bool, // [28] |
| 123 | + /// `HPROT[3]` |
| 124 | + Cacheable: bool, // [27] |
| 125 | + /// `HPROT[2]` |
| 126 | + Bufferable: bool, // [26] |
| 127 | + /// `HPROT[1]` |
| 128 | + Privileged: bool, // [25] |
| 129 | + /// `HPROT[0]` |
| 130 | + Data: bool, // [24] |
| 131 | + /// Secure Debug Enabled. |
| 132 | + /// |
| 133 | + /// This field has one of the following values: |
| 134 | + /// - `0b0` Secure access is disabled. |
| 135 | + /// - `0b1` Secure access is enabled. |
| 136 | + /// This field is optional, and read-only. If not implemented, the bit is RES0. |
| 137 | + /// If CSW.DeviceEn is 0b0, SPIDEN is ignored and the effective value of SPIDEN is 0b1. |
| 138 | + /// For more information, see `Enabling access to the connected debug device or memory system` |
| 139 | + /// on page C2-154. |
| 140 | + /// |
| 141 | + /// Note: |
| 142 | + /// In ADIv5 and older versions of the architecture, the CSW.SPIDEN field is in the same bit |
| 143 | + /// position as CSW.SDeviceEn, and has the same meaning. From ADIv6, the name SDeviceEn is |
| 144 | + /// used to avoid confusion between this field and the SPIDEN signal on the authentication |
| 145 | + /// interface. |
| 146 | + SPIDEN: bool, // [23] |
| 147 | + /// A transfer is in progress. |
| 148 | + /// Can be used to poll whether an aborted transaction has completed. |
| 149 | + /// Read only. |
| 150 | + TrInProg: bool, // [7] |
| 151 | + /// `1` if transactions can be issued through this access port at the moment. |
| 152 | + /// Read only. |
| 153 | + DeviceEn: bool, // [6] |
| 154 | + /// The address increment on DRW access. |
| 155 | + AddrInc: AddressIncrement, // [5:4] |
| 156 | + /// The access size of this memory AP. |
| 157 | + Size: DataSize, // [2:0] |
| 158 | + /// Reserved bit, kept to preserve IMPLEMENTATION DEFINED statuses. |
| 159 | + _reserved_bits: u32 // mask |
| 160 | + ], |
| 161 | + from: value => Ok(CSW { |
| 162 | + DbgSwEnable: ((value >> 31) & 0x01) != 0, |
| 163 | + HNONSEC: ((value >> 30) & 0x01) != 0, |
| 164 | + MasterType: ((value >> 29) & 0x01) != 0, |
| 165 | + Allocate: ((value >> 28) & 0x01) != 0, |
| 166 | + Cacheable: ((value >> 27) & 0x01) != 0, |
| 167 | + Bufferable: ((value >> 26) & 0x01) != 0, |
| 168 | + Privileged: ((value >> 25) & 0x01) != 0, |
| 169 | + Data: ((value >> 24) & 0x01) != 0, |
| 170 | + SPIDEN: ((value >> 23) & 0x01) != 0, |
| 171 | + TrInProg: ((value >> 7) & 0x01) != 0, |
| 172 | + DeviceEn: ((value >> 6) & 0x01) != 0, |
| 173 | + AddrInc: AddressIncrement::from_u8(((value >> 4) & 0x03) as u8).ok_or_else(|| RegisterParseError::new("CSW", value))?, |
| 174 | + Size: DataSize::try_from((value & 0x07) as u8).map_err(|_| RegisterParseError::new("CSW", value))?, |
| 175 | + _reserved_bits: value & 0x007F_FF08, |
| 176 | + }), |
| 177 | + to: value => (u32::from(value.DbgSwEnable) << 31) |
| 178 | + | (u32::from(value.HNONSEC ) << 30) |
| 179 | + | (u32::from(value.MasterType ) << 29) |
| 180 | + | (u32::from(value.Allocate ) << 28) |
| 181 | + | (u32::from(value.Cacheable ) << 27) |
| 182 | + | (u32::from(value.Bufferable ) << 26) |
| 183 | + | (u32::from(value.Privileged ) << 25) |
| 184 | + | (u32::from(value.Data ) << 24) |
| 185 | + | (u32::from(value.SPIDEN ) << 23) |
| 186 | + | (u32::from(value.TrInProg ) << 7) |
| 187 | + | (u32::from(value.DeviceEn ) << 6) |
| 188 | + | (u32::from(value.AddrInc as u8) << 4) |
| 189 | + | (value.Size as u32) |
| 190 | + | value._reserved_bits |
| 191 | +); |
0 commit comments