use crate::{
CoreInterface, MemoryInterface,
architecture::{riscv::Riscv32, xtensa::Xtensa},
semihosting::{
SemihostingCommand, UnknownCommandDetails, WriteConsoleRequest, ZeroTerminatedString,
},
};
pub(super) struct EspBreakpointHandler {}
impl EspBreakpointHandler {
pub fn handle_riscv_idf_semihosting(
arch: &mut Riscv32,
details: UnknownCommandDetails,
) -> Result<Option<SemihostingCommand>, crate::Error> {
match details.operation {
0x103 => {
let set_breakpoint = arch.read_word_32(details.parameter as u64)?;
if set_breakpoint != 0 {
let mut breakpoint_data = [0; 2];
arch.read_32(details.parameter as u64 + 4, &mut breakpoint_data)?;
let [breakpoint_number, address] = breakpoint_data;
arch.set_hw_breakpoint(breakpoint_number as usize, address as u64)?;
} else {
let breakpoint_number = arch.read_word_32(details.parameter as u64 + 4)?;
arch.clear_hw_breakpoint(breakpoint_number as usize)?;
}
Ok(None)
}
0x116 => Self::read_panic_reason(arch, details.parameter),
_ => Ok(Some(SemihostingCommand::Unknown(details))),
}
}
pub fn handle_xtensa_idf_semihosting(
arch: &mut Xtensa,
details: UnknownCommandDetails,
) -> Result<Option<SemihostingCommand>, crate::Error> {
match details.operation {
0x116 => Self::read_panic_reason(arch, details.parameter),
_ => Ok(Some(SemihostingCommand::Unknown(details))),
}
}
fn read_panic_reason(
arch: &mut dyn CoreInterface,
parameter: u32,
) -> Result<Option<SemihostingCommand>, crate::Error> {
let mut buffer = [0; 2];
arch.read_32(parameter as u64, &mut buffer)?;
let [address, length] = buffer;
Ok(Some(SemihostingCommand::WriteConsole(WriteConsoleRequest(
ZeroTerminatedString {
address,
length: Some(length),
},
))))
}
}