use std::fmt;
#[derive(Debug, Clone, Copy)]
pub enum ReplSource {
Embedded(&'static str),
ImagePath(&'static str),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CpuInit {
VectorTable,
Board,
}
#[derive(Debug, Clone, Copy)]
pub struct Platform {
pub name: &'static str,
pub repl: ReplSource,
pub init: CpuInit,
pub mips: Option<u32>,
pub can_connector: Option<&'static str>,
pub uart: Option<&'static str>,
pub default_timeout_secs: u32,
}
impl Platform {
#[must_use]
pub const fn rp2040() -> Self {
Self {
name: "rp2040",
repl: ReplSource::Embedded(include_str!("repl/rp2040.repl")),
init: CpuInit::VectorTable,
mips: None,
can_connector: None,
uart: Some("sysbus.uart0"),
default_timeout_secs: 10,
}
}
#[must_use]
pub const fn nrf52840() -> Self {
Self {
name: "nrf52840",
repl: ReplSource::Embedded(include_str!("repl/nrf52840.repl")),
init: CpuInit::VectorTable,
mips: None,
can_connector: None,
uart: None,
default_timeout_secs: 10,
}
}
#[must_use]
pub const fn stm32f4() -> Self {
Self {
name: "stm32f4",
repl: ReplSource::Embedded(include_str!("repl/stm32f4.repl")),
init: CpuInit::VectorTable,
mips: None,
can_connector: None,
uart: None,
default_timeout_secs: 10,
}
}
#[must_use]
pub const fn stm32f3() -> Self {
Self {
name: "stm32f3",
repl: ReplSource::Embedded(include_str!("repl/stm32f3.repl")),
init: CpuInit::VectorTable,
mips: None,
can_connector: None,
uart: None,
default_timeout_secs: 10,
}
}
#[must_use]
pub const fn stm32h7() -> Self {
Self {
name: "stm32h7",
repl: ReplSource::ImagePath("platforms/boards/nucleo_h753zi.repl"),
init: CpuInit::Board,
mips: Some(125),
can_connector: Some("fdcan1"),
uart: Some("sysbus.usart3"),
default_timeout_secs: 15,
}
}
#[must_use]
pub fn repl_content(&self) -> &'static str {
match self.repl {
ReplSource::Embedded(s) | ReplSource::ImagePath(s) => s,
}
}
}
impl fmt::Display for Platform {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builtin_display_names() {
assert_eq!(Platform::rp2040().to_string(), "rp2040");
assert_eq!(Platform::nrf52840().to_string(), "nrf52840");
assert_eq!(Platform::stm32f4().to_string(), "stm32f4");
assert_eq!(Platform::stm32h7().to_string(), "stm32h7");
}
#[test]
fn cortex_m_boards_use_vector_table() {
assert_eq!(Platform::rp2040().init, CpuInit::VectorTable);
assert_eq!(Platform::nrf52840().init, CpuInit::VectorTable);
assert_eq!(Platform::stm32f4().init, CpuInit::VectorTable);
}
#[test]
fn rp2040_repl_is_embedded_cortex_m0() {
assert!(Platform::rp2040().repl_content().contains("cortex-m0+"));
assert!(Platform::rp2040()
.repl_content()
.contains("uart0: UART.PL011"));
assert_eq!(Platform::rp2040().uart, Some("sysbus.uart0"));
}
#[test]
fn stm32h7_is_board_init_with_hub_connector() {
let p = Platform::stm32h7();
assert_eq!(p.init, CpuInit::Board);
assert_eq!(p.mips, Some(125));
assert_eq!(p.can_connector, Some("fdcan1"));
assert!(p.repl_content().contains("nucleo_h753zi"));
}
#[test]
fn custom_platform_via_struct_literal() {
let p = Platform {
name: "myboard",
repl: ReplSource::Embedded("cpu: CPU.CortexM @ sysbus"),
mips: Some(48),
default_timeout_secs: 7,
..Platform::rp2040()
};
assert_eq!(p.to_string(), "myboard");
assert_eq!(p.mips, Some(48));
assert_eq!(p.default_timeout_secs, 7);
}
}