use crate::coresight::memory::MI;
use crate::probe::{DebugProbeError, MasterProbe};
use crate::target::{
BasicRegisterAddresses, Core, CoreInformation, CoreRegister, CoreRegisterAddress,
};
use bitfield::bitfield;
use std::mem::size_of;
#[derive(Debug, Default, Copy, Clone)]
pub struct M33;
impl M33 {
fn wait_for_core_register_transfer(&self, mi: &mut impl MI) -> Result<(), DebugProbeError> {
for _ in 0..100 {
let dhcsr_val = Dhcsr(mi.read32(Dhcsr::ADDRESS)?);
if dhcsr_val.s_regrdy() {
return Ok(());
}
}
Err(DebugProbeError::Timeout)
}
}
impl Core for M33 {
fn wait_for_core_halted(&self, mi: &mut MasterProbe) -> Result<(), DebugProbeError> {
for _ in 0..100 {
let dhcsr_val = Dhcsr(mi.read32(Dhcsr::ADDRESS)?);
if dhcsr_val.s_halt() {
return Ok(());
}
}
Err(DebugProbeError::Timeout)
}
fn core_halted(&self, mi: &mut MasterProbe) -> Result<bool, DebugProbeError> {
let dhcsr_val = Dhcsr(mi.read32(Dhcsr::ADDRESS)?);
if dhcsr_val.s_halt() {
Ok(true)
} else {
Ok(false)
}
}
fn halt(&self, mi: &mut MasterProbe) -> Result<CoreInformation, DebugProbeError> {
let mut value = Dhcsr(0);
value.set_c_halt(true);
value.set_c_debugen(true);
value.enable_write();
mi.write32(Dhcsr::ADDRESS, value.into())?;
self.wait_for_core_halted(mi)?;
let pc_value = self.read_core_reg(mi, REGISTERS.PC)?;
Ok(CoreInformation { pc: pc_value })
}
fn run(&self, mi: &mut MasterProbe) -> Result<(), DebugProbeError> {
let mut value = Dhcsr(0);
value.set_c_halt(false);
value.set_c_debugen(true);
value.enable_write();
mi.write32(Dhcsr::ADDRESS, value.into()).map_err(Into::into)
}
fn reset(&self, mi: &mut MasterProbe) -> Result<(), DebugProbeError> {
let mut value = Aircr(0);
value.vectkey();
value.set_sysresetreq(true);
mi.write32(Aircr::ADDRESS, value.into())?;
Ok(())
}
fn reset_and_halt(&self, mi: &mut MasterProbe) -> Result<CoreInformation, DebugProbeError> {
let dhcsr_val = Dhcsr(mi.read32(Dhcsr::ADDRESS)?);
if !dhcsr_val.c_debugen() {
let mut dhcsr = Dhcsr(0);
dhcsr.set_c_debugen(true);
dhcsr.enable_write();
mi.write32(Dhcsr::ADDRESS, dhcsr.into())?;
}
let demcr_val = Demcr(mi.read32(Demcr::ADDRESS)?);
if !demcr_val.vc_corereset() {
let mut demcr_enabled = demcr_val;
demcr_enabled.set_vc_corereset(true);
mi.write32(Demcr::ADDRESS, demcr_enabled.into())?;
}
self.reset(mi)?;
self.wait_for_core_halted(mi)?;
const XPSR_THUMB: u32 = 1 << 24;
let xpsr_value = self.read_core_reg(mi, REGISTERS.XPSR)?;
if xpsr_value & XPSR_THUMB == 0 {
self.write_core_reg(mi, REGISTERS.XPSR, xpsr_value | XPSR_THUMB)?;
}
mi.write32(Demcr::ADDRESS, demcr_val.into())?;
let pc_value = self.read_core_reg(mi, REGISTERS.PC)?;
Ok(CoreInformation { pc: pc_value })
}
fn step(&self, mi: &mut MasterProbe) -> Result<CoreInformation, DebugProbeError> {
let mut value = Dhcsr(0);
value.set_c_step(true);
value.set_c_halt(false);
value.set_c_debugen(true);
value.set_c_maskints(true);
value.enable_write();
mi.write32(Dhcsr::ADDRESS, value.into())?;
self.wait_for_core_halted(mi)?;
let pc_value = self.read_core_reg(mi, REGISTERS.PC)?;
Ok(CoreInformation { pc: pc_value })
}
fn read_core_reg(
&self,
mi: &mut MasterProbe,
addr: CoreRegisterAddress,
) -> Result<u32, DebugProbeError> {
let mut dcrsr_val = Dcrsr(0);
dcrsr_val.set_regwnr(false); dcrsr_val.set_regsel(addr.into());
mi.write32(Dcrsr::ADDRESS, dcrsr_val.into())?;
self.wait_for_core_register_transfer(mi)?;
mi.read32(Dcrdr::ADDRESS).map_err(From::from)
}
fn write_core_reg(
&self,
mi: &mut MasterProbe,
addr: CoreRegisterAddress,
value: u32,
) -> Result<(), DebugProbeError> {
let result: Result<(), DebugProbeError> =
mi.write32(Dcrdr::ADDRESS, value).map_err(From::from);
result?;
let mut dcrsr_val = Dcrsr(0);
dcrsr_val.set_regwnr(true); dcrsr_val.set_regsel(addr.into());
mi.write32(Dcrsr::ADDRESS, dcrsr_val.into())?;
self.wait_for_core_register_transfer(mi)
}
fn get_available_breakpoint_units(&self, mi: &mut MasterProbe) -> Result<u32, DebugProbeError> {
let raw_val = mi.read32(FpCtrl::ADDRESS)?;
let reg = FpCtrl::from(raw_val);
Ok(reg.num_code())
}
fn enable_breakpoints(&self, mi: &mut MasterProbe, state: bool) -> Result<(), DebugProbeError> {
let mut val = FpCtrl::from(0);
val.set_key(true);
val.set_enable(state);
mi.write32(FpCtrl::ADDRESS, val.into())?;
Ok(())
}
fn set_breakpoint(
&self,
mi: &mut MasterProbe,
bp_unit_index: usize,
addr: u32,
) -> Result<(), DebugProbeError> {
let mut val = FpCompX::from(0);
let comp_val = addr & 0xff_ff_ff_fe;
val.set_bp_addr(comp_val);
val.set_enable(true);
let reg_addr = FpCompX::ADDRESS + (bp_unit_index * size_of::<u32>()) as u32;
mi.write32(reg_addr, val.into())?;
Ok(())
}
fn read_block8(
&self,
mi: &mut MasterProbe,
address: u32,
data: &mut [u8],
) -> Result<(), DebugProbeError> {
Ok(mi.read_block8(address, data)?)
}
fn registers<'a>(&self) -> &'a BasicRegisterAddresses {
®ISTERS
}
fn clear_breakpoint(
&self,
mi: &mut MasterProbe,
bp_unit_index: usize,
) -> Result<(), DebugProbeError> {
let mut val = FpCompX::from(0);
val.set_enable(false);
val.set_bp_addr(0);
let reg_addr = FpCompX::ADDRESS + (bp_unit_index * size_of::<u32>()) as u32;
mi.write32(reg_addr, val.into())?;
Ok(())
}
}
pub const REGISTERS: BasicRegisterAddresses = BasicRegisterAddresses {
R0: CoreRegisterAddress(0b0_0000),
R1: CoreRegisterAddress(0b0_0001),
R2: CoreRegisterAddress(0b0_0010),
R3: CoreRegisterAddress(0b0_0011),
R4: CoreRegisterAddress(0b0_0100),
R5: CoreRegisterAddress(0b0_0101),
R6: CoreRegisterAddress(0b0_0110),
R7: CoreRegisterAddress(0b0_0111),
R8: CoreRegisterAddress(0b0_1000),
R9: CoreRegisterAddress(0b0_1001),
PC: CoreRegisterAddress(0b0_1111),
SP: CoreRegisterAddress(0b0_1101),
LR: CoreRegisterAddress(0b0_1110),
XPSR: CoreRegisterAddress(0b1_0000),
};
bitfield! {
#[derive(Copy, Clone)]
pub struct Dhcsr(u32);
impl Debug;
pub s_restart_st, _ : 26;
pub s_reset_st, _: 25;
pub s_retire_st, _: 24;
pub s_fpd, _: 23;
pub s_suide, _: 22;
pub s_nsuide, _: 21;
pub s_sde, _: 20;
pub s_lockup, _: 19;
pub s_sleep, _: 18;
pub s_halt, _: 17;
pub s_regrdy, _: 16;
pub c_pmov, set_c_pmov: 6;
pub c_snapstall, set_c_snappstall: 5;
pub c_maskints, set_c_maskints: 3;
pub c_step, set_c_step: 2;
pub c_halt, set_c_halt: 1;
pub c_debugen, set_c_debugen: 0;
}
impl Dhcsr {
fn enable_write(&mut self) {
self.0 &= !(0xffff << 16);
self.0 |= 0xa05f << 16;
}
}
impl From<u32> for Dhcsr {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<Dhcsr> for u32 {
fn from(value: Dhcsr) -> Self {
value.0
}
}
impl CoreRegister for Dhcsr {
const ADDRESS: u32 = 0xE000_EDF0;
const NAME: &'static str = "DHCSR";
}
bitfield! {
#[derive(Copy, Clone)]
pub struct Aircr(u32);
impl Debug;
pub get_vectkeystat, set_vectkey: 31,16;
pub endianness, _: 15;
pub sysresetreqs, set_sysresetreqs: 3;
pub sysresetreq, set_sysresetreq: 2;
pub vectclractive, set_vectclractive: 1;
}
impl From<u32> for Aircr {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<Aircr> for u32 {
fn from(value: Aircr) -> Self {
value.0
}
}
impl Aircr {
pub fn vectkey(&mut self) {
self.set_vectkey(0x05FA);
}
pub fn vectkeystat(&self) -> bool {
self.get_vectkeystat() == 0xFA05
}
}
impl CoreRegister for Aircr {
const ADDRESS: u32 = 0xE000_ED0C;
const NAME: &'static str = "AIRCR";
}
bitfield! {
#[derive(Copy, Clone)]
pub struct Dcrsr(u32);
impl Debug;
pub _, set_regwnr: 16;
pub _, set_regsel: 6,0;
}
impl From<u32> for Dcrsr {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<Dcrsr> for u32 {
fn from(value: Dcrsr) -> Self {
value.0
}
}
impl CoreRegister for Dcrsr {
const ADDRESS: u32 = 0xE000_EDF4;
const NAME: &'static str = "DCRSR";
}
#[derive(Debug, Copy, Clone)]
pub struct Dcrdr(u32);
impl From<u32> for Dcrdr {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<Dcrdr> for u32 {
fn from(value: Dcrdr) -> Self {
value.0
}
}
impl CoreRegister for Dcrdr {
const ADDRESS: u32 = 0xE000_EDF8;
const NAME: &'static str = "DCRDR";
}
bitfield! {
#[derive(Copy, Clone)]
pub struct Demcr(u32);
impl Debug;
pub trcena, set_trcena: 24;
pub monprkey, set_monprkey: 23;
pub umon_en, set_umon_en: 21;
pub sdme, set_sdme: 20;
pub mon_req, set_mon_req: 19;
pub mon_step, set_mon_step: 18;
pub mon_pend, set_mon_pend: 17;
pub mon_en, set_mon_en: 16;
pub vc_sferr, set_vc_sferr: 11;
pub vc_harderr, set_vc_harderr: 10;
pub vc_interr, set_vc_interr: 9;
pub vc_buserr, set_vc_buserr: 8;
pub vc_staterr, set_vc_staterr: 7;
pub vc_chkerr, set_vc_chkerr: 6;
pub vc_nocperr, set_vc_nocperr: 5;
pub vc_mmerr, set_vc_mmerr: 4;
pub vc_corereset, set_vc_corereset: 0;
}
impl From<u32> for Demcr {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<Demcr> for u32 {
fn from(value: Demcr) -> Self {
value.0
}
}
impl CoreRegister for Demcr {
const ADDRESS: u32 = 0xe000_edfc;
const NAME: &'static str = "DEMCR";
}
bitfield! {
#[derive(Copy,Clone)]
pub struct FpCtrl(u32);
impl Debug;
pub rev, _: 31, 28;
num_code_1, _: 14, 12;
pub num_lit, _: 11, 8;
num_code_0, _: 7, 4;
pub _, set_key: 1;
pub enable, set_enable: 0;
}
impl FpCtrl {
pub fn num_code(&self) -> u32 {
(self.num_code_1() << 4) | self.num_code_0()
}
}
impl CoreRegister for FpCtrl {
const ADDRESS: u32 = 0xE000_2008;
const NAME: &'static str = "FP_CTRL";
}
impl From<u32> for FpCtrl {
fn from(value: u32) -> Self {
FpCtrl(value)
}
}
impl From<FpCtrl> for u32 {
fn from(value: FpCtrl) -> Self {
value.0
}
}
bitfield! {
#[derive(Copy,Clone)]
pub struct FpCompX(u32);
impl Debug;
pub bp_addr, set_bp_addr: 31, 1;
pub enable, set_enable: 0;
}
impl CoreRegister for FpCompX {
const ADDRESS: u32 = 0xE000_2000;
const NAME: &'static str = "FP_CTRL";
}
impl From<u32> for FpCompX {
fn from(value: u32) -> Self {
FpCompX(value)
}
}
impl From<FpCompX> for u32 {
fn from(value: FpCompX) -> Self {
value.0
}
}