use std::num::{NonZeroU32, NonZeroU64};
use crate::sidecar::{Alias, Property, SidecarCommand};
pub const BINARY: &str = "rigless-sidecar";
pub const MACHINE: &str = "rigless-armv7m";
pub const PROPERTIES: [(&str, &str); 4] = [
(CLOCK_HZ, "size"),
(INTERRUPT_LINES, "uint32"),
(PRIORITY_BITS, "uint8"),
(REFCLK_DIVIDER, "uint32"),
];
const RESET_VECTOR: u64 = 0;
const CLOCK_HZ: &str = "clock-hz";
const INTERRUPT_LINES: &str = "num-irq";
const PRIORITY_BITS: &str = "num-prio-bits";
const REFCLK_DIVIDER: &str = "refclk-divider";
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Model {
M3,
M4,
M7,
M33,
}
impl Model {
pub const ALL: [Self; 4] = [Self::M3, Self::M4, Self::M7, Self::M33];
#[must_use]
pub const fn name(self) -> &'static str {
match self {
Self::M3 => "cortex-m3",
Self::M4 => "cortex-m4",
Self::M7 => "cortex-m7",
Self::M33 => "cortex-m33",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Core {
pub model: Model,
pub clock_hz: NonZeroU64,
pub interrupt_lines: NonZeroU32,
pub priority_bits: u8,
pub refclk_divider: NonZeroU32,
pub icount_shift: u32,
pub boot: &'static str,
}
impl Core {
#[must_use]
pub fn command(self) -> SidecarCommand {
SidecarCommand {
binary: BINARY,
machine: MACHINE,
cpu: self.model.name(),
properties: vec![
Property::new(CLOCK_HZ, self.clock_hz),
Property::new(INTERRUPT_LINES, self.interrupt_lines),
Property::new(PRIORITY_BITS, self.priority_bits),
Property::new(REFCLK_DIVIDER, self.refclk_divider),
],
icount_shift: self.icount_shift,
aliases: vec![Alias {
region: self.boot,
at: RESET_VECTOR,
}],
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn core() -> Core {
Core {
model: Model::M4,
clock_hz: NonZeroU64::new(168_000_000).unwrap(),
interrupt_lines: NonZeroU32::new(91).unwrap(),
priority_bits: 4,
refclk_divider: NonZeroU32::new(8).unwrap(),
icount_shift: 2,
boot: "flash",
}
}
fn rendered(core: Core) -> Vec<String> {
core.command()
.properties
.iter()
.map(ToString::to_string)
.collect()
}
#[test]
fn the_properties_render_as_the_machine_spells_them() {
assert_eq!(
rendered(core()),
[
"clock-hz=168000000",
"num-irq=91",
"num-prio-bits=4",
"refclk-divider=8"
]
);
let command = core().command();
assert_eq!(command.machine, MACHINE);
assert_eq!(command.cpu, "cortex-m4");
assert_eq!(
command.properties.len(),
PROPERTIES.len(),
"every property the machine declares is set"
);
}
#[test]
fn the_boot_region_is_the_one_the_core_also_finds_at_its_reset_vector() {
assert_eq!(
core().command().aliases,
[Alias {
region: "flash",
at: 0
}]
);
let from_system = Core {
boot: "system",
..core()
};
assert_eq!(
from_system.command().aliases,
[Alias {
region: "system",
at: 0
}],
"the SoC's boot configuration says which region, not the family"
);
}
}