use std::sync::{Arc, Mutex};
use crate::architecture::riscv::communication_interface::{
MemoryAccessMethod, RiscvBusAccess, RiscvCommunicationInterface,
};
use crate::architecture::riscv::sequences::RiscvDebugSequence;
use crate::memory::MemoryInterface;
const NUSPI_BASE: u64 = 0x1001_4000;
const NUSPI_FCTRL: u64 = 0x60;
const FCTRL_EN: u32 = 1;
#[derive(Debug)]
pub struct NucleiSequence {
saved_fctrl: Mutex<Option<u32>>,
}
impl NucleiSequence {
pub fn create() -> Arc<dyn RiscvDebugSequence> {
Arc::new(Self {
saved_fctrl: Mutex::new(None),
})
}
}
impl RiscvDebugSequence for NucleiSequence {
fn on_connect(&self, interface: &mut RiscvCommunicationInterface) -> Result<(), crate::Error> {
let config = interface.memory_access_config();
for width in [
RiscvBusAccess::A8,
RiscvBusAccess::A16,
RiscvBusAccess::A32,
RiscvBusAccess::A64,
RiscvBusAccess::A128,
] {
config.set_default_method(width, MemoryAccessMethod::ProgramBuffer);
}
tracing::debug!("NucleiSequence: enabling force_machine_mode_progbuf");
interface.set_force_machine_mode_progbuf(true);
if let Ok(misa) = interface.read_csr_progbuf_64(0x301) {
let mxl = misa >> 62;
if mxl == 2 {
tracing::info!(
"NucleiSequence: detected RV64 (MISA={:#018x}), setting xlen_64",
misa
);
interface.set_xlen_64(true);
} else {
tracing::debug!("NucleiSequence: MISA={:#018x}, MXL={}", misa, mxl);
}
}
if let Ok(milmb) = interface.read_csr_progbuf_64(0x7C0) {
let ilm_base = milmb & !1u64;
tracing::info!("NucleiSequence: ILM base (milmb) = {:#010x}", ilm_base);
}
if let Ok(mdlmb) = interface.read_csr_progbuf_64(0x7C1) {
let dlm_base = mdlmb & !1u64;
tracing::info!("NucleiSequence: DLM base (mdlmb) = {:#010x}", dlm_base);
}
let fctrl_addr = NUSPI_BASE + NUSPI_FCTRL;
let current_fctrl = interface.read_word_32(fctrl_addr)?;
tracing::debug!(
"NucleiSequence: NUSPI fctrl @ {:#010x} = {:#010x}",
fctrl_addr,
current_fctrl
);
if let Ok(mut saved) = self.saved_fctrl.lock() {
*saved = Some(current_fctrl);
}
if current_fctrl & FCTRL_EN == 0 {
tracing::info!(
"NucleiSequence: NUSPI XIP disabled (fctrl={:#010x}), enabling XIP for flash backup",
current_fctrl
);
interface.write_word_32(fctrl_addr, current_fctrl | FCTRL_EN)?;
} else {
tracing::debug!("NucleiSequence: NUSPI XIP already enabled");
}
Ok(())
}
}