opentitanlib/test_utils/
crashdump.rs1use anyhow::{Result, bail};
6
7use crate::app::TransportWrapper;
8use crate::dif::rstmgr::{
9 DifRstmgrResetInfo, RstmgrAlertInfoCtrl, RstmgrCpuInfoCtrl, RstmgrCpuRegwen, RstmgrReg,
10};
11use crate::io::jtag::{JtagParams, JtagTap};
12
13use top_earlgrey::top_earlgrey;
14
15pub fn read_cpu_crashdump_data(
19 transport: &TransportWrapper,
20 jtag_params: &JtagParams,
21) -> Result<()> {
22 transport.pin_strapping("PINMUX_TAP_RISCV")?.apply()?;
23 let mut jtag = jtag_params.create(transport)?.connect(JtagTap::RiscvTap)?;
24
25 let mut buf = [0u32];
27
28 jtag.read_memory32(
30 top_earlgrey::RSTMGR_AON_BASE_ADDR as u32 + RstmgrReg::CpuRegwen as u32,
31 &mut buf,
32 )?;
33 if buf[0] & RstmgrCpuRegwen::EN == 0 {
34 bail!("CPU_REGWEN.EN is 0, cannot read CPU crash dump.");
35 }
36
37 let mut cpu_crashdump_info = [0u32; 16];
38 jtag.read_memory32(
39 top_earlgrey::RSTMGR_AON_BASE_ADDR as u32 + RstmgrReg::CpuInfoAttr as u32,
40 &mut buf,
41 )?;
42 let len = buf[0];
43 log::info!("CPU Crash Dump Info ({:?} words):", len);
44 for i in 0..len {
45 jtag.write_memory32(
46 top_earlgrey::RSTMGR_AON_BASE_ADDR as u32 + RstmgrReg::CpuInfoCtrl as u32,
47 &[RstmgrCpuInfoCtrl::INDEX.emplace(i) | RstmgrCpuInfoCtrl::EN],
48 )?;
49 jtag.read_memory32(
50 top_earlgrey::RSTMGR_AON_BASE_ADDR as u32 + RstmgrReg::CpuInfo as u32,
51 &mut buf,
52 )?;
53 cpu_crashdump_info[i as usize] = buf[0];
54 }
55 log::info!(" Current MTVAL = 0x{:x?}", cpu_crashdump_info[0]);
56 log::info!(" Current MPEC = 0x{:x?}", cpu_crashdump_info[1]);
57 log::info!(" Last Data Access Addr = 0x{:x?}", cpu_crashdump_info[2]);
58 log::info!(" Next PC = 0x{:x?}", cpu_crashdump_info[3]);
59 log::info!(" PC = 0x{:x?}", cpu_crashdump_info[4]);
60 log::info!(" Previous MTVAL = 0x{:x?}", cpu_crashdump_info[5]);
61 log::info!(" Previous MPEC = 0x{:x?}", cpu_crashdump_info[6]);
62 log::info!(" Double Fault = 0x{:x?}", cpu_crashdump_info[7]);
63
64 transport.pin_strapping("PINMUX_TAP_RISCV")?.remove()?;
65 jtag.disconnect()?;
66
67 Ok(())
68}
69
70pub fn read_alert_crashdump_data(
74 transport: &TransportWrapper,
75 jtag_params: &JtagParams,
76) -> Result<()> {
77 transport.pin_strapping("PINMUX_TAP_RISCV")?.apply()?;
78 let mut jtag = jtag_params.create(transport)?.connect(JtagTap::RiscvTap)?;
79
80 let mut buf = [0u32];
81 jtag.read_memory32(
82 top_earlgrey::RSTMGR_AON_BASE_ADDR as u32 + RstmgrReg::AlertInfoAttr as u32,
83 &mut buf,
84 )?;
85 let len = buf[0];
86 log::info!("Alert Crash Dump Info ({:?} words):", len);
87 for i in 0..len {
88 jtag.write_memory32(
89 top_earlgrey::RSTMGR_AON_BASE_ADDR as u32 + RstmgrReg::AlertInfoCtrl as u32,
90 &[RstmgrAlertInfoCtrl::INDEX.emplace(i) | RstmgrAlertInfoCtrl::EN],
91 )?;
92 jtag.read_memory32(
93 top_earlgrey::RSTMGR_AON_BASE_ADDR as u32 + RstmgrReg::AlertInfo as u32,
94 &mut buf,
95 )?;
96 log::info!(" Word {:?} = 0x{:x?}", i, buf[0]);
97 }
98
99 transport.pin_strapping("PINMUX_TAP_RISCV")?.remove()?;
100 jtag.disconnect()?;
101
102 Ok(())
103}
104
105pub fn read_reset_reason(transport: &TransportWrapper, jtag_params: &JtagParams) -> Result<()> {
109 transport.pin_strapping("PINMUX_TAP_RISCV")?.apply()?;
110 let mut jtag = jtag_params.create(transport)?.connect(JtagTap::RiscvTap)?;
111
112 let mut buf = [0u32];
113 jtag.read_memory32(
114 top_earlgrey::RSTMGR_AON_BASE_ADDR as u32 + RstmgrReg::ResetInfo as u32,
115 &mut buf,
116 )?;
117 let reset_reason = buf[0];
118
119 log::info!("Reset Reasons:");
120 log::info!(
121 " PoR = {:?}",
122 (reset_reason & u32::from(DifRstmgrResetInfo::Por)) != 0
123 );
124 log::info!(
125 " LowPowerExit = {:?}",
126 (reset_reason & u32::from(DifRstmgrResetInfo::LowPowerExit)) != 0
127 );
128 log::info!(
129 " Sw = {:?}",
130 (reset_reason & u32::from(DifRstmgrResetInfo::Sw)) != 0
131 );
132 log::info!(
133 " HwReq = {:?}",
134 (reset_reason & u32::from(DifRstmgrResetInfo::HwReq)) != 0
135 );
136 log::info!(
137 " SysRstCtrl = {:?}",
138 (reset_reason & u32::from(DifRstmgrResetInfo::SysRstCtrl)) != 0
139 );
140 log::info!(
141 " Watchdog = {:?}",
142 (reset_reason & u32::from(DifRstmgrResetInfo::Watchdog)) != 0
143 );
144 log::info!(
145 " PowerUnstable = {:?}",
146 (reset_reason & u32::from(DifRstmgrResetInfo::PowerUnstable)) != 0
147 );
148 log::info!(
149 " Escalation = {:?}",
150 (reset_reason & u32::from(DifRstmgrResetInfo::Escalation)) != 0
151 );
152 log::info!(
153 " Ndm = {:?}",
154 (reset_reason & u32::from(DifRstmgrResetInfo::Ndm)) != 0
155 );
156
157 transport.pin_strapping("PINMUX_TAP_RISCV")?.remove()?;
158 jtag.disconnect()?;
159
160 Ok(())
161}