use alloc::{format, string::String};
use core::fmt;
use core::ops::RangeInclusive;
use crate::arm::Cortex;
use crate::arm::ap::Idr;
use crate::arm::ap::{IDR_AHB_AP_CORTEX_M3, IDR_AHB_AP_CORTEX_M4};
use crate::arm::dp::IdCode;
const STM32F1_FLASH_BASE: u32 = 0x0800_0000;
const STM32F4_FLASH_BASE: u32 = 0x0800_0000;
const STM32F4_RAM_BASE: u32 = 0x2000_0000;
const STM32F1_RAM_BASE: u32 = 0x2000_0000;
const GPIOX_MODER_OFFSET: u32 = 0x00;
const GPIOX_OTYPER_OFFSET: u32 = 0x04;
const GPIOX_OSPEEDR_OFFSET: u32 = 0x08;
const GPIOX_PUPDR_OFFSET: u32 = 0x0C;
const GPIOX_IDR_OFFSET: u32 = 0x10;
const GPIOX_ODR_OFFSET: u32 = 0x14;
const GPIOX_BSRR_OFFSET: u32 = 0x18;
const GPIOX_LCKR_OFFSET: u32 = 0x1C;
const GPIOX_AFRL_OFFSET: u32 = 0x20;
const GPIOX_AFRH_OFFSET: u32 = 0x24;
const STM32F4_GPIOA_REG_BASE: u32 = 0x4002_0000;
pub const STM32F4_GPIOA_MODER: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_MODER_OFFSET;
pub const STM32F4_GPIOA_OTYPER: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_OTYPER_OFFSET;
pub const STM32F4_GPIOA_OSPEEDR: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_OSPEEDR_OFFSET;
pub const STM32F4_GPIOA_PUPDR: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_PUPDR_OFFSET;
pub const STM32F4_GPIOA_IDR: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_IDR_OFFSET;
pub const STM32F4_GPIOA_ODR: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_ODR_OFFSET;
pub const STM32F4_GPIOA_BSRR: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_BSRR_OFFSET;
pub const STM32F4_GPIOA_LCKR: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_LCKR_OFFSET;
pub const STM32F4_GPIOA_AFRL: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_AFRL_OFFSET;
pub const STM32F4_GPIOA_AFRH: u32 = STM32F4_GPIOA_REG_BASE + GPIOX_AFRH_OFFSET;
const STM32F4_GPIOB_REG_BASE: u32 = 0x4002_0400;
pub const STM32F4_GPIOB_MODER: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_MODER_OFFSET;
pub const STM32F4_GPIOB_OTYPER: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_OTYPER_OFFSET;
pub const STM32F4_GPIOB_OSPEEDR: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_OSPEEDR_OFFSET;
pub const STM32F4_GPIOB_PUPDR: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_PUPDR_OFFSET;
pub const STM32F4_GPIOB_IDR: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_IDR_OFFSET;
pub const STM32F4_GPIOB_ODR: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_ODR_OFFSET;
pub const STM32F4_GPIOB_BSRR: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_BSRR_OFFSET;
pub const STM32F4_GPIOB_LCKR: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_LCKR_OFFSET;
pub const STM32F4_GPIOB_AFRL: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_AFRL_OFFSET;
pub const STM32F4_GPIOB_AFRH: u32 = STM32F4_GPIOB_REG_BASE + GPIOX_AFRH_OFFSET;
const STM32F4_GPIOC_REG_BASE: u32 = 0x4002_0800;
pub const STM32F4_GPIOC_MODER: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_MODER_OFFSET;
pub const STM32F4_GPIOC_OTYPER: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_OTYPER_OFFSET;
pub const STM32F4_GPIOC_OSPEEDR: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_OSPEEDR_OFFSET;
pub const STM32F4_GPIOC_PUPDR: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_PUPDR_OFFSET;
pub const STM32F4_GPIOC_IDR: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_IDR_OFFSET;
pub const STM32F4_GPIOC_ODR: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_ODR_OFFSET;
pub const STM32F4_GPIOC_BSRR: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_BSRR_OFFSET;
pub const STM32F4_GPIOC_LCKR: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_LCKR_OFFSET;
pub const STM32F4_GPIOC_AFRL: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_AFRL_OFFSET;
pub const STM32F4_GPIOC_AFRH: u32 = STM32F4_GPIOC_REG_BASE + GPIOX_AFRH_OFFSET;
const STM32F4_GPIOD_REG_BASE: u32 = 0x4002_0C00;
pub const STM32F4_GPIOD_MODER: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_MODER_OFFSET;
pub const STM32F4_GPIOD_OTYPER: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_OTYPER_OFFSET;
pub const STM32F4_GPIOD_OSPEEDR: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_OSPEEDR_OFFSET;
pub const STM32F4_GPIOD_PUPDR: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_PUPDR_OFFSET;
pub const STM32F4_GPIOD_IDR: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_IDR_OFFSET;
pub const STM32F4_GPIOD_ODR: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_ODR_OFFSET;
pub const STM32F4_GPIOD_BSRR: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_BSRR_OFFSET;
pub const STM32F4_GPIOD_LCKR: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_LCKR_OFFSET;
pub const STM32F4_GPIOD_AFRL: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_AFRL_OFFSET;
pub const STM32F4_GPIOD_AFRH: u32 = STM32F4_GPIOD_REG_BASE + GPIOX_AFRH_OFFSET;
const STM32F4_GPIOE_REG_BASE: u32 = 0x4002_1000;
pub const STM32F4_GPIOE_MODER: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_MODER_OFFSET;
pub const STM32F4_GPIOE_OTYPER: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_OTYPER_OFFSET;
pub const STM32F4_GPIOE_OSPEEDR: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_OSPEEDR_OFFSET;
pub const STM32F4_GPIOE_PUPDR: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_PUPDR_OFFSET;
pub const STM32F4_GPIOE_IDR: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_IDR_OFFSET;
pub const STM32F4_GPIOE_ODR: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_ODR_OFFSET;
pub const STM32F4_GPIOE_BSRR: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_BSRR_OFFSET;
pub const STM32F4_GPIOE_LCKR: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_LCKR_OFFSET;
pub const STM32F4_GPIOE_AFRL: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_AFRL_OFFSET;
pub const STM32F4_GPIOE_AFRH: u32 = STM32F4_GPIOE_REG_BASE + GPIOX_AFRH_OFFSET;
pub const STM32F4_MODER_OUTPUT: u32 = 0b01;
pub const STM32F4_MODER_INPUT: u32 = 0b00;
pub const STM32F4_MODER_AF: u32 = 0b10;
pub const STM32F4_MODER_ANALOG: u32 = 0b11;
pub const STM32F4_MODER_MASK: u32 = 0b11;
pub const STM32F4_PUPDR_NONE: u32 = 0b00;
pub const STM32F4_PUPDR_PU: u32 = 0b01;
pub const STM32F4_PUPDR_PD: u32 = 0b10;
pub const STM32F4_PUPDR_MASK: u32 = 0b11;
const STM32F4_FLASH_REG_BASE: u32 = 0x4002_3C00;
pub struct Stm32F4FlashCr;
impl Stm32F4FlashCr {
pub const ADDRESS: u32 = STM32F4_FLASH_REG_BASE + 0x10;
pub const LOCK_BIT: u32 = 31;
pub const ERRIE_BIT: u32 = 25;
pub const EOPIE_BIT: u32 = 24;
pub const STRT_BIT: u32 = 16;
pub const MER_BIT: u32 = 2;
pub const SER_BIT: u32 = 1;
pub const PG_BIT: u32 = 0;
pub const SNB_SHIFT: u32 = 3;
pub const PSIZE_SHIFT: u32 = 8;
pub const SNB_MASK: u32 = 0b1111;
pub const PSIZE_MASK: u32 = 0b11;
pub const PSIZE_X8: u32 = 0b00;
pub const PSIZE_X16: u32 = 0b01;
pub const PSIZE_X32: u32 = 0b10;
pub const PSIZE_X64: u32 = 0b11;
}
pub struct Stm32F4FlashSr(u32);
impl Stm32F4FlashSr {
pub const ADDRESS: u32 = STM32F4_FLASH_REG_BASE + 0x0C;
pub const EOP_BIT: u32 = 0;
pub const OPERR_BIT: u32 = 1;
pub const WRPERR_BIT: u32 = 4;
pub const PGAERR_BIT: u32 = 5;
pub const PGPERR_BIT: u32 = 6;
pub const PGSERR_BIT: u32 = 7;
pub const RDERR_BIT: u32 = 8;
pub const BSY_BIT: u32 = 16;
pub fn busy(&self) -> bool {
(self.0 >> Self::BSY_BIT) & 1 != 0
}
pub fn errors(&self) -> bool {
let error_mask = (1 << Self::OPERR_BIT)
| (1 << Self::WRPERR_BIT)
| (1 << Self::PGAERR_BIT)
| (1 << Self::PGPERR_BIT)
| (1 << Self::PGSERR_BIT)
| (1 << Self::RDERR_BIT);
self.0 & error_mask != 0
}
}
impl From<u32> for Stm32F4FlashSr {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<Stm32F4FlashSr> for u32 {
fn from(sr: Stm32F4FlashSr) -> Self {
sr.0
}
}
impl fmt::Display for Stm32F4FlashSr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x{:08X}", self.0)
}
}
pub struct Stm32F4FlashKeyr;
impl Stm32F4FlashKeyr {
pub const ADDRESS: u32 = STM32F4_FLASH_REG_BASE + 0x04;
pub const KEY1: u32 = 0x45670123;
pub const KEY2: u32 = 0xCDEF89AB;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StmFamily {
F4,
F1,
Unknown,
}
impl StmFamily {
pub fn known(&self) -> bool {
!matches!(self, StmFamily::Unknown)
}
}
impl fmt::Display for StmFamily {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
StmFamily::F4 => write!(f, "STM32F4"),
StmFamily::F1 => write!(f, "STM32F1"),
StmFamily::Unknown => write!(f, "Unknown"),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StmLine {
F401BC,
F401DE,
F411,
F427_F437,
F413_F423,
F4x5,
F446,
F103,
Unknown,
}
impl StmLine {
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 {
StmLine::F401BC => Some(96),
StmLine::F401DE => Some(96),
StmLine::F411 => Some(128),
StmLine::F427_F437 => Some(192),
StmLine::F413_F423 => Some(256),
StmLine::F4x5 => Some(128),
StmLine::F446 => Some(128),
StmLine::F103 => Some(20),
StmLine::Unknown => None,
}
}
pub fn ccm_ram_size_bytes(&self) -> Option<u32> {
self.ccm_ram_size_kb().map(|size| size * 1024)
}
pub fn ccm_ram_size_kb(&self) -> Option<u32> {
match self {
StmLine::F401BC => None,
StmLine::F401DE => None,
StmLine::F411 => None,
StmLine::F427_F437 => None,
StmLine::F413_F423 => None,
StmLine::F4x5 => Some(64),
StmLine::F446 => None,
StmLine::F103 => None,
StmLine::Unknown => None,
}
}
}
impl fmt::Display for StmLine {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
StmLine::F401BC => write!(f, "STM32F401B/C"),
StmLine::F401DE => write!(f, "STM32F401D/E"),
StmLine::F4x5 => write!(f, "STM32F405/415/07/17"),
StmLine::F411 => write!(f, "STM32F411"),
StmLine::F413_F423 => write!(f, "STM32F413/423"),
StmLine::F427_F437 => write!(f, "STM32F427/437"),
StmLine::F446 => write!(f, "STM32F446"),
StmLine::F103 => write!(f, "STM32F103"),
StmLine::Unknown => write!(f, "Unknown STM32"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StmDeviceId {
raw: u32,
}
impl StmDeviceId {
pub const ADDRESS: u32 = 0xE004_2000;
pub fn new(raw: u32) -> Self {
Self { raw }
}
pub fn raw(&self) -> u32 {
self.raw
}
pub fn revision(&self) -> u16 {
((self.raw >> 16) & 0xFFFF) as u16
}
pub fn device_id(&self) -> u16 {
(self.raw & 0xFFF) as u16
}
pub fn family(&self) -> StmFamily {
match self.device_id() {
0x423 | 0x433 | 0x431 | 0x413 | 0x419 | 0x463 | 0x421 => StmFamily::F4,
0x412 | 0x410 | 0x414 | 0x430 | 0x418 => StmFamily::F1,
_ => StmFamily::Unknown,
}
}
pub fn line(&self) -> StmLine {
match self.device_id() {
0x423 => StmLine::F401BC,
0x433 => StmLine::F401DE,
0x431 => StmLine::F411,
0x413 => StmLine::F4x5,
0x419 => StmLine::F427_F437,
0x463 => StmLine::F413_F423,
0x421 => StmLine::F446,
0x410 => StmLine::F103,
_ => StmLine::Unknown,
}
}
pub fn revision_str(&self) -> &'static str {
match self.line() {
StmLine::F401BC | StmLine::F401DE => match self.revision() {
0x1000 => "A",
0x1001 => "1/Z",
_ => "unknown",
},
StmLine::F411 => match self.revision() {
0x1000 => "A/1/Z",
_ => "unknown",
},
StmLine::F4x5 => match self.revision() {
0x1000 => "A",
0x1001 => "Z",
0x1003 => "1",
0x1007 => "2",
0x100F => "Y/4",
0x101F => "5/6",
_ => "unknown",
},
StmLine::F427_F437 => match self.revision() {
0x1000 => "A",
0x1003 => "Y",
0x2001 => "3",
0x2003 => "4/5/B",
_ => "unknown",
},
StmLine::F413_F423 => match self.revision() {
0x1000 => "A/1",
_ => "unknown",
},
StmLine::F446 => match self.revision() {
0x1000 => "A/1",
_ => "unknown",
},
StmLine::F103 => match self.revision() {
0x0000 => "A",
0x2000 => "B",
0x2001 => "Z",
0x2003 => "1/2/3/X/Y",
_ => "unknown",
},
StmLine::Unknown => "unknown",
}
}
pub fn is_known_device(&self) -> bool {
!matches!(self.line(), StmLine::Unknown)
}
}
impl From<u32> for StmDeviceId {
fn from(raw: u32) -> Self {
Self::new(raw)
}
}
impl fmt::Display for StmDeviceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(
f,
"STM32 Device ID: 0x{:08X} ({} {})",
self.raw(),
self.line(),
self.revision_str()
)
} else {
write!(f, "{}", self.line())
}
}
}
impl fmt::LowerHex for StmDeviceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x{:08x}", self.raw)
}
}
impl fmt::UpperHex for StmDeviceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x{:08X}", self.raw)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StmUniqueId {
uid: [u32; 3],
}
impl StmUniqueId {
pub const STM32F4_INITIAL_ADDRESS: u32 = 0x1FFF_7A10;
pub const STM32F1_INITIAL_ADDRESS: u32 = 0x1FFF_F7E8;
pub fn addr_from_family(family: StmFamily) -> Option<u32> {
match family {
StmFamily::F4 => Some(Self::STM32F4_INITIAL_ADDRESS),
StmFamily::F1 => Some(Self::STM32F1_INITIAL_ADDRESS),
StmFamily::Unknown => None,
}
}
pub fn new(uid: [u32; 3]) -> Self {
Self { uid }
}
pub fn x_y(&self) -> u32 {
self.uid[0]
}
pub fn x(&self) -> u16 {
(self.x_y() & 0xFFFF) as u16
}
pub fn y(&self) -> u16 {
((self.x_y() >> 16) & 0xFFFF) as u16
}
pub fn wafer(&self) -> u8 {
(self.uid[1] & 0xFF) as u8
}
pub fn lot(&self) -> [u8; 7] {
let uid1_bytes = self.uid[1].to_le_bytes();
let uid2_bytes = self.uid[2].to_le_bytes();
[
uid2_bytes[3], uid2_bytes[2], uid2_bytes[1], uid2_bytes[0], uid1_bytes[3], uid1_bytes[2], uid1_bytes[1], ]
}
pub fn wafer_str(&self) -> String {
let byte = self.wafer();
format!("0x{byte:02X}")
}
pub fn lot_str(&self) -> String {
let bytes = self.lot();
let mut result = String::new();
for &byte in &bytes {
if byte.is_ascii_graphic() {
result.push(byte as char);
} else {
result.push('.')
}
}
result
}
pub fn raw(&self) -> [u32; 3] {
self.uid
}
}
impl fmt::Display for StmUniqueId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"UID[95:0]: 0x{:08X}{:08X}{:08X} Lot: {} Wafer: {} X/Y: {}/{}",
self.raw()[2],
self.raw()[1],
self.raw()[0],
self.lot_str(),
self.wafer_str(),
self.x(),
self.y(),
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StmFlashSize {
raw: u16,
}
impl StmFlashSize {
pub const STM32F4_ADDRESS_OF_U16: u32 = 0x1FFF_7A20;
pub const STM32F1_ADDRESS_OF_U16: u32 = 0x1FFF_F7E0;
pub fn addr_from_family(family: StmFamily) -> Option<u32> {
match family {
StmFamily::F4 => Some(Self::STM32F4_ADDRESS_OF_U16),
StmFamily::F1 => Some(Self::STM32F1_ADDRESS_OF_U16),
StmFamily::Unknown => None,
}
}
pub fn new(raw: u16) -> Self {
Self { raw }
}
pub fn raw(&self) -> u16 {
self.raw
}
pub fn size_bytes(&self) -> u32 {
(self.raw as u32) * 1024
}
pub fn size_kb(&self) -> u32 {
self.raw as u32
}
}
impl fmt::Display for StmFlashSize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Flash Size: {} KB", self.size_kb())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StmDetails {
mcu: StmDeviceId,
idcode: IdCode,
uid: Option<StmUniqueId>,
flash_size: Option<StmFlashSize>,
}
impl StmDetails {
pub fn new(
mcu: StmDeviceId,
idcode: IdCode,
uid: Option<StmUniqueId>,
flash_size: Option<StmFlashSize>,
) -> Self {
Self {
mcu,
idcode,
uid,
flash_size,
}
}
pub fn idcode(&self) -> &IdCode {
&self.idcode
}
pub fn get_cortex(&self) -> Option<Cortex> {
Cortex::from_idcode(self.idcode)
}
pub fn mcu(&self) -> &StmDeviceId {
&self.mcu
}
pub fn uid(&self) -> Option<StmUniqueId> {
self.uid
}
pub fn flash_size_bytes(&self) -> Option<u32> {
self.flash_size.map(|size| size.size_bytes())
}
pub fn flash_size_kb(&self) -> Option<StmFlashSize> {
self.flash_size
}
pub fn flash_base(&self) -> Option<u32> {
match self.mcu.family() {
StmFamily::F4 => Some(STM32F4_FLASH_BASE),
StmFamily::F1 => Some(STM32F1_FLASH_BASE),
StmFamily::Unknown => None,
}
}
pub fn ram_base(&self) -> Option<u32> {
match self.mcu.family() {
StmFamily::F4 => Some(STM32F4_RAM_BASE),
StmFamily::F1 => Some(STM32F1_RAM_BASE),
StmFamily::Unknown => None,
}
}
pub fn is_stm32f4(&self) -> bool {
matches!(self.mcu.family(), StmFamily::F4)
}
pub fn is_stm32f1(&self) -> bool {
matches!(self.mcu.family(), StmFamily::F1)
}
pub const MAX_SECTORS: u8 = 12;
const SECTOR_SIZES_BYTES: [u32; Self::MAX_SECTORS as usize] = [
16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024, 128 * 1024, 128 * 1024, 128 * 1024, 128 * 1024, 128 * 1024, 128 * 1024, 128 * 1024, 128 * 1024, ];
pub fn get_sector_size_bytes(&self, sector: u8) -> Option<u32> {
if !self.is_stm32f4() {
return None;
}
let value = if sector < Self::SECTOR_SIZES_BYTES.len() as u8 {
Self::SECTOR_SIZES_BYTES[sector as usize]
} else {
return None;
};
let flash_size = self.flash_size_bytes()? as usize;
let mut total_size: usize = 0;
for size in Self::SECTOR_SIZES_BYTES.iter().take(sector as usize + 1) {
total_size += *size as usize;
if total_size > flash_size {
return None; }
}
Some(value)
}
pub fn get_sector_size_kb(&self, sector: u8) -> Option<u32> {
self.get_sector_size_bytes(sector).map(|size| size / 1024)
}
pub fn get_sectors_from_word_range(
&self,
range: RangeInclusive<u32>,
sectors: &mut [u8; Self::MAX_SECTORS as usize],
) -> Option<usize> {
if !self.is_stm32f4() {
return None;
}
let start_word = *range.start();
let start_bytes = start_word * 4;
let end_word = *range.end();
let end_bytes = end_word * 4;
if start_word > end_word {
return None; }
let flash_size = self.flash_size_bytes()?;
if end_bytes + 4 > flash_size {
return None; }
let mut sector_count = 0;
let mut current_address = 0u32;
let range_end_bytes = end_bytes + 3;
for (sector_num, §or_size) in Self::SECTOR_SIZES_BYTES.iter().enumerate() {
let sector_start = current_address;
let sector_end = current_address + sector_size - 1;
if start_bytes <= sector_end && range_end_bytes >= sector_start {
sectors[sector_count] = sector_num as u8;
sector_count += 1;
}
current_address += sector_size;
if current_address > range_end_bytes {
break;
}
}
Some(sector_count)
}
pub fn expected_idr(&self) -> Option<Idr> {
if self.is_stm32f4() {
Some(IDR_AHB_AP_CORTEX_M4)
} else if self.is_stm32f1() {
Some(IDR_AHB_AP_CORTEX_M3)
} else {
None
}
}
}
impl fmt::Display for StmDetails {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(f, "{:#}", self.mcu)?;
if let Some(flash_size) = self.flash_size {
write!(f, " {} KB", flash_size.size_kb())?;
} else {
write!(f, " Flash Size: unknown ")?;
};
if let Some(uid) = &self.uid {
write!(f, " {uid}")
} else {
write!(f, " UID: unknown ")
}
} else {
write!(f, "{}", self.mcu)
}
}
}