1use cfg_if::cfg_if;
10
11use crate::pac::FLASH;
12
13const BANK1_START_ADDR: usize = 0x0800_0000;
17
18cfg_if! {
19 if #[cfg(any(feature = "l5", feature = "g473", feature = "g474", feature = "g483", feature = "g484"))] {
20 const PAGE_SIZE_SINGLE_BANK: usize = 4_096;
21 const PAGE_SIZE_DUAL_BANK: usize = 2_048;
22 const BANK2_START_ADDR: usize = 0x0804_0000;
23 } else if #[cfg(feature = "h7")]{
24 const SECTOR_SIZE: usize = 0x2_0000;
25 const BANK2_START_ADDR: usize = 0x0810_0000;
26 } else {
27 const PAGE_SIZE: usize = 2_048;
28 #[allow(dead_code)] const BANK2_START_ADDR: usize = 0x0804_0000;
30 }
31}
32
33cfg_if! {
34 if #[cfg(any(feature = "l5", feature = "h5"))] {
35 mod trustzone;
36 pub use trustzone::*;
37 } else {
38 mod non_trustzone;
39 pub use non_trustzone::*;
40 }
41}
42
43#[cfg_attr(feature = "defmt", derive(defmt::Format))]
44#[derive(Debug, Clone, Copy, Eq, PartialEq)]
45pub enum FlashError {
47 Busy,
49 Illegal,
51 EccError,
53 PageOutOfRange,
55 Failure,
57}
58
59pub struct Flash {
60 pub regs: FLASH,
61 #[cfg(any(
62 feature = "g473",
63 feature = "g474",
64 feature = "g483",
65 feature = "g484",
66 feature = "l5"
67 ))]
68 pub dual_bank: DualBank,
69}
70
71impl Flash {
75 pub fn new(regs: FLASH) -> Self {
77 cfg_if! {
78 if #[cfg(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484", feature = "l5"))] {
79 Self { regs, dual_bank: DualBank::Dual } } else {
83 Self { regs }
84 }
85 }
86 }
87
88 #[allow(unused_variables)] pub fn read(&self, bank: Bank, page: usize, offset: usize, buf: &mut [u8]) {
91 cfg_if! {
99 if #[cfg(any(
100 feature = "g473",
101 feature = "g474",
102 feature = "g483",
103 feature = "g484",
104 feature = "l5",
105 ))] {
106 let mut addr = page_to_address(self.dual_bank, bank, page) as *mut u32;
107 } else if #[cfg(feature = "h7")]{
108 let mut addr = page_to_address(bank, page) as *mut u32;
109 } else {
110 let mut addr = page_to_address(page) as *mut u32;
111 }
112 }
113
114 unsafe {
115 addr = unsafe { addr.add(offset) };
117 for chunk in buf.chunks_mut(4) {
119 let word = unsafe { core::ptr::read_volatile(addr) };
120 let bytes = word.to_le_bytes();
121
122 let len = chunk.len();
123 if len < 4 {
124 chunk[0..len].copy_from_slice(&bytes[0..len]);
125 } else {
126 chunk[0..4].copy_from_slice(&bytes);
127 };
128
129 unsafe { addr = addr.add(1) };
130 }
131 }
132 }
133}
134
135#[cfg(not(any(
138 feature = "g473",
139 feature = "g474",
140 feature = "g483",
141 feature = "g484",
142 feature = "h5",
143 feature = "l5",
144 feature = "h7"
145)))]
146fn page_to_address(page: usize) -> usize {
147 BANK1_START_ADDR + page * PAGE_SIZE
148}
149
150#[cfg(any(
151 feature = "g473",
152 feature = "g474",
153 feature = "g483",
154 feature = "g484",
155 feature = "h5",
156 feature = "l5",
157))]
158fn page_to_address(dual_bank: DualBank, bank: Bank, page: usize) -> usize {
159 if dual_bank == DualBank::Single {
160 BANK1_START_ADDR + page * PAGE_SIZE_SINGLE_BANK
161 } else {
162 match bank {
163 Bank::B1 => BANK1_START_ADDR + page * PAGE_SIZE_DUAL_BANK,
164 Bank::B2 => BANK2_START_ADDR + page * PAGE_SIZE_DUAL_BANK,
165 }
166 }
167}
168
169#[cfg(feature = "h7")]
170fn page_to_address(bank: Bank, sector: usize) -> usize {
173 let starting_pt = match bank {
175 Bank::B1 => BANK1_START_ADDR,
176 #[cfg(not(any(feature = "h747cm4", feature = "h747cm7")))]
178 Bank::B2 => BANK2_START_ADDR,
179 };
180
181 starting_pt + sector * SECTOR_SIZE
182}