use cfg_if::cfg_if;
use crate::pac::FLASH;
const BANK1_START_ADDR: usize = 0x0800_0000;
cfg_if! {
if #[cfg(any(feature = "l5", feature = "g473", feature = "g474", feature = "g483", feature = "g484"))] {
const PAGE_SIZE_SINGLE_BANK: usize = 4_096;
const PAGE_SIZE_DUAL_BANK: usize = 2_048;
const BANK2_START_ADDR: usize = 0x0804_0000;
} else if #[cfg(feature = "h7")]{
const SECTOR_SIZE: usize = 0x2_0000;
const BANK2_START_ADDR: usize = 0x0810_0000;
} else {
const PAGE_SIZE: usize = 2_048;
#[allow(dead_code)] const BANK2_START_ADDR: usize = 0x0804_0000;
}
}
cfg_if! {
if #[cfg(any(feature = "l5", feature = "h5"))] {
mod trustzone;
pub use trustzone::*;
} else {
mod non_trustzone;
pub use non_trustzone::*;
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum FlashError {
Busy,
Illegal,
EccError,
PageOutOfRange,
Failure,
}
pub struct Flash {
pub regs: FLASH,
#[cfg(any(
feature = "g473",
feature = "g474",
feature = "g483",
feature = "g484",
feature = "l5"
))]
pub dual_bank: DualBank,
}
impl Flash {
#[cfg(not(any(
feature = "g473",
feature = "g474",
feature = "g483",
feature = "g484",
feature = "l5"
)))]
pub fn new(regs: FLASH) -> Self {
Self { regs }
}
#[cfg(any(
feature = "g473",
feature = "g474",
feature = "g483",
feature = "g484",
feature = "l5"
))]
pub fn new(regs: FLASH, dual_bank: DualBank) -> Self {
Self { regs, dual_bank }
}
#[allow(unused_variables)] pub fn read(&self, bank: Bank, page: usize, offset: usize, buf: &mut [u8]) {
cfg_if! {
if #[cfg(any(
feature = "g473",
feature = "g474",
feature = "g483",
feature = "g484",
feature = "l5",
))] {
let mut addr = page_to_address(self.dual_bank, bank, page) as *mut u32;
} else if #[cfg(feature = "h7")]{
let mut addr = page_to_address(bank, page) as *mut u32;
} else {
let mut addr = page_to_address(page) as *mut u32;
}
}
unsafe {
addr = unsafe { addr.add(offset) };
for chunk in buf.chunks_mut(4) {
let word = unsafe { core::ptr::read_volatile(addr) };
let bytes = word.to_le_bytes();
let len = chunk.len();
if len < 4 {
chunk[0..len].copy_from_slice(&bytes[0..len]);
} else {
chunk[0..4].copy_from_slice(&bytes);
};
unsafe { addr = addr.add(1) };
}
}
}
}
#[cfg(not(any(
feature = "g473",
feature = "g474",
feature = "g483",
feature = "g484",
feature = "h5",
feature = "l5",
feature = "h7"
)))]
fn page_to_address(page: usize) -> usize {
BANK1_START_ADDR + page * PAGE_SIZE
}
#[cfg(any(
feature = "g473",
feature = "g474",
feature = "g483",
feature = "g484",
feature = "h5",
feature = "l5",
))]
fn page_to_address(dual_bank: DualBank, bank: Bank, page: usize) -> usize {
if dual_bank == DualBank::Single {
BANK1_START_ADDR + page * PAGE_SIZE_SINGLE_BANK
} else {
match bank {
Bank::B1 => BANK1_START_ADDR + page * PAGE_SIZE_DUAL_BANK,
Bank::B2 => BANK2_START_ADDR + page * PAGE_SIZE_DUAL_BANK,
}
}
}
#[cfg(feature = "h7")]
fn page_to_address(bank: Bank, sector: usize) -> usize {
let starting_pt = match bank {
Bank::B1 => BANK1_START_ADDR,
#[cfg(not(any(feature = "h747cm4", feature = "h747cm7")))]
Bank::B2 => BANK2_START_ADDR,
};
starting_pt + sector * SECTOR_SIZE
}