Skip to content

Commit

Permalink
Merge pull request #130 from bugadani/xtensa-me
Browse files Browse the repository at this point in the history
Xtensa: Implement instruction execution and memory access
  • Loading branch information
MabezDev authored Dec 5, 2023
2 parents 80a4e98 + 39d91d7 commit fb2d8ac
Show file tree
Hide file tree
Showing 9 changed files with 1,198 additions and 172 deletions.
26 changes: 20 additions & 6 deletions probe-rs/examples/xtensa.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use anyhow::Result;
use probe_rs::config::ScanChainElement;
use probe_rs::Probe;
use probe_rs::{Lister, MemoryInterface, Probe};

fn main() -> Result<()> {
pretty_env_logger::init();

// Get a list of all available debug probes.
let probes = Probe::list_all();
let probe_lister = Lister::new();

let probes = probe_lister.list_all();

// Use the first probe found.
let mut probe: Probe = probes[0].open()?;
let mut probe: Probe = probes[0].open(&probe_lister)?;

probe.set_speed(100)?;
probe.select_protocol(probe_rs::WireProtocol::Jtag)?;
Expand All @@ -25,9 +27,21 @@ fn main() -> Result<()> {
},
])?;
probe.attach_to_unspecified()?;
let _iface = probe
.try_into_xtensa_interface()
.unwrap();
let mut iface = probe.try_into_xtensa_interface().unwrap();

iface.enter_ocd_mode()?;

assert!(iface.is_in_ocd_mode()?);

iface.halt()?;

const SYSTEM_BASE_REGISTER: u32 = 0x600C_0000;
const SYSTEM_DATE_REGISTER: u32 = SYSTEM_BASE_REGISTER | 0x0FFC;
let date = iface.read_word_32(SYSTEM_DATE_REGISTER as u64)?;

iface.leave_ocd_mode()?;

println!("SYSTEM peripheral date: {:08x}", date);

Ok(())
}
3 changes: 3 additions & 0 deletions probe-rs/src/architecture/xtensa/arch/instruction/format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub const fn rsr(opcode: u32, rs: u8, t: u8) -> u32 {
opcode | (rs as u32) << 8 | (t as u32 & 0x0F) << 4
}
39 changes: 39 additions & 0 deletions probe-rs/src/architecture/xtensa/arch/instruction/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use crate::architecture::xtensa::arch::{CpuRegister, SpecialRegister};

pub mod format;

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Instruction {
/// Loads a 32-bit word from the address in `src` into `DDR`
/// Note: this is an illegal instruction when the processor is not in On-Chip Debug Mode
Lddr32P(CpuRegister),

/// Reads `SpecialRegister` into `CpuRegister`
Rsr(SpecialRegister, CpuRegister),

/// Writes `CpuRegister` into `SpecialRegister`
Wsr(SpecialRegister, CpuRegister),

/// Returns the Core to the Running state
Rfdo(u8),
}

/// The architecture supports multi-word instructions. This enum represents the different encodings
// ... but we only support narrow ones for now
pub enum InstructionEncoding {
/// Instruction encoding is narrow enough to fit into DIR0/DIR0EXEC
Narrow(u32),
}

impl Instruction {
pub fn encode(self) -> InstructionEncoding {
let narrow = match self {
Instruction::Lddr32P(src) => 0x0070E0 | (src.address() as u32 & 0x0F) << 8,
Instruction::Rsr(sr, t) => format::rsr(0x030000, sr.address(), t.address()),
Instruction::Wsr(sr, t) => format::rsr(0x130000, sr.address(), t.address()),
Instruction::Rfdo(_) => 0xF1E000,
};

InstructionEncoding::Narrow(narrow)
}
}
139 changes: 139 additions & 0 deletions probe-rs/src/architecture/xtensa/arch/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#![allow(unused)] // TODO remove

pub mod instruction;

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum Register {
Cpu(CpuRegister),
Special(SpecialRegister),
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum CpuRegister {
A0 = 0,
A1 = 1,
A2 = 2,
A3 = 3,
A4 = 4,
A5 = 5,
A6 = 6,
A7 = 7,
A8 = 8,
A9 = 9,
A10 = 10,
A11 = 11,
A12 = 12,
A13 = 13,
A14 = 14,
A15 = 15,
}

impl CpuRegister {
pub const fn scratch() -> Self {
Self::A3
}

pub const fn address(self) -> u8 {
self as u8
}
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum SpecialRegister {
Lbeg = 0,
Lend = 1,
Lcount = 2,
Sar = 3,
Br = 4,
Litbase = 5,
Scompare1 = 12,
AccLo = 16,
AccHi = 17,
M0 = 32,
M1 = 33,
M2 = 34,
M3 = 35,
Windowbase = 72,
Windowstart = 73,
PteVAddr = 83,
RAsid = 90,
// MpuEnB = 90,
ITlbCfg = 91,
DTlbCfg = 92,
// MpuCfg = 92,
ERAccess = 95,
IBreakEnable = 96,
Memctl = 97,
CacheAdrDis = 98,
AtomCtl = 99,
Ddr = 104,
Mepc = 106,
Meps = 107,
Mesave = 108,
Mesr = 109,
Mecr = 110,
MeVAddr = 111,
IBreakA0 = 128,
IBreakA1 = 129,
DBreakA0 = 144,
DBreakA1 = 145,
DBreakC0 = 160,
DBreakC1 = 161,
Epc1 = 177,
Epc2 = 178,
Epc3 = 179,
Epc4 = 180,
Epc5 = 181,
Epc6 = 182,
Epc7 = 183,
IBreakC0 = 192,
IBreakC1 = 193,
// Depc = 192,
Eps2 = 194,
Eps3 = 195,
Eps4 = 196,
Eps5 = 197,
Eps6 = 198,
Eps7 = 199,
ExcSave1 = 209,
ExcSave2 = 210,
ExcSave3 = 211,
ExcSave4 = 212,
ExcSave5 = 213,
ExcSave6 = 214,
ExcSave7 = 215,
CpEnable = 224,
// Interrupt = 226,
IntSet = 226,
IntClear = 227,
IntEnable = 228,
Ps = 230,
VecBase = 231,
ExcCause = 232,
DebugCause = 233,
CCount = 234,
Prid = 235,
ICount = 236,
ICountLevel = 237,
ExcVaddr = 238,
CCompare0 = 240,
CCompare1 = 241,
CCompare2 = 242,
Misc0 = 244,
Misc1 = 245,
Misc2 = 246,
Misc3 = 247,
}

#[allow(non_upper_case_globals)] // Aliasses have same style as other register names
impl SpecialRegister {
// Aliasses
pub const MpuEnB: Self = Self::RAsid;
pub const MpuCfg: Self = Self::DTlbCfg;
pub const Depc: Self = Self::IBreakC0;
pub const Interrupt: Self = Self::IntSet;

pub const fn address(self) -> u8 {
self as u8
}
}
Loading

0 comments on commit fb2d8ac

Please sign in to comment.