#![no_std]
pub mod arm;
pub mod rp;
pub mod stm;
extern crate alloc;
use core::fmt;
use core::ops::RangeInclusive;
use static_assertions::const_assert;
use crate::arm::ap::Idr;
use crate::arm::dp::IdCode;
#[derive(Debug, Clone, Copy)]
pub enum Mcu {
Stm32(stm::StmDetails),
Rp(rp::RpDetails),
Unknown(IdCode),
}
impl Mcu {
pub fn flash_base(&self) -> Option<u32> {
match self {
Mcu::Stm32(details) => details.flash_base(),
Mcu::Rp(details) => details.flash_base(),
Mcu::Unknown(_) => None,
}
}
pub fn ram_base(&self) -> Option<u32> {
match self {
Mcu::Stm32(details) => details.ram_base(),
Mcu::Rp(details) => details.ram_base(),
Mcu::Unknown(_) => None,
}
}
pub fn flash_size_bytes(&self) -> Option<u32> {
self.flash_size_kb().map(|size| size * 1024)
}
pub fn flash_size_kb(&self) -> Option<u32> {
match self {
Mcu::Stm32(details) => details.flash_size_kb().map(|size| size.raw() as u32),
Mcu::Rp(_) => None,
Mcu::Unknown(_) => None,
}
}
pub fn ram_size_bytes(&self) -> Option<u32> {
self.ram_size_kb().map(|size| size * 1024)
}
pub fn ram_size_kb(&self) -> Option<u32> {
match self {
Mcu::Stm32(details) => details.mcu().line().ram_size_kb(),
Mcu::Rp(details) => details.line().ram_size_kb(),
Mcu::Unknown(_) => None,
}
}
pub fn is_stm32(&self) -> bool {
matches!(self, Mcu::Stm32(_))
}
pub fn is_stm32f4(&self) -> bool {
match self {
Mcu::Stm32(stm) => stm.is_stm32f4(),
Mcu::Rp(_) => false,
Mcu::Unknown(_) => false,
}
}
pub fn is_rp(&self) -> bool {
matches!(self, Mcu::Rp(_))
}
pub fn get_sector_size_bytes(&self, sector: u8) -> Option<u32> {
match self {
Mcu::Stm32(details) => details.get_sector_size_bytes(sector),
Mcu::Rp(_) => None,
Mcu::Unknown(_) => None,
}
}
pub fn get_sector_size_words(&self, sector: u8) -> Option<u32> {
self.get_sector_size_bytes(sector).map(|size| size / 4)
}
pub fn get_sector_size_kb(&self, sector: u8) -> Option<u32> {
self.get_sector_size_bytes(sector).map(|size| size / 1024)
}
pub const MAX_SECTORS: u8 = 12;
pub fn get_sectors_from_word_range(
&self,
range: RangeInclusive<u32>,
sectors: &mut [u8; Self::MAX_SECTORS as usize],
) -> Option<usize> {
const_assert!(Mcu::MAX_SECTORS <= stm::StmDetails::MAX_SECTORS);
match self {
Mcu::Stm32(details) => details.get_sectors_from_word_range(range, sectors),
Mcu::Rp(_) => None,
Mcu::Unknown(_) => None,
}
}
pub fn expected_idr(&self) -> Option<Idr> {
match self {
Mcu::Stm32(details) => details.expected_idr(),
Mcu::Rp(details) => details.expected_idr(),
Mcu::Unknown(_) => None,
}
}
}
impl fmt::Display for Mcu {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Mcu::Stm32(details) => {
if f.alternate() {
write!(f, "STM32 MCU: {details:#}")
} else {
write!(f, "{details}")
}
}
Mcu::Rp(details) => {
if f.alternate() {
write!(f, "RP MCU: {details:#}")
} else {
write!(f, "{details}")
}
}
Mcu::Unknown(idcode) => {
if f.alternate() {
write!(f, "Unknown MCU (IDCODE: {idcode:#})")
} else {
write!(f, "Unknown MCU (IDCODE: {idcode})")
}
}
}
}
}