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 #[cfg(not(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484", feature = "l5")))]
76 pub fn new(regs: FLASH) -> Self {
78 Self { regs }
79 }
80
81 #[cfg(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484", feature = "l5"))]
82 pub fn new(regs: FLASH, dual_bank: DualBank) -> Self {
83 Self { regs, dual_bank }
85 }
86
87 #[allow(unused_variables)] pub fn read(&self, bank: Bank, page: usize, offset: usize, buf: &mut [u8]) {
90 cfg_if! {
98 if #[cfg(any(
99 feature = "g473",
100 feature = "g474",
101 feature = "g483",
102 feature = "g484",
103 feature = "l5",
104 ))] {
105 let mut addr = page_to_address(self.dual_bank, bank, page) as *mut u32;
106 } else if #[cfg(feature = "h7")]{
107 let mut addr = page_to_address(bank, page) as *mut u32;
108 } else {
109 let mut addr = page_to_address(page) as *mut u32;
110 }
111 }
112
113 unsafe {
114 addr = unsafe { addr.add(offset) };
116 for chunk in buf.chunks_mut(4) {
118 let word = unsafe { core::ptr::read_volatile(addr) };
119 let bytes = word.to_le_bytes();
120
121 let len = chunk.len();
122 if len < 4 {
123 chunk[0..len].copy_from_slice(&bytes[0..len]);
124 } else {
125 chunk[0..4].copy_from_slice(&bytes);
126 };
127
128 unsafe { addr = addr.add(1) };
129 }
130 }
131 }
132}
133
134#[cfg(not(any(
137 feature = "g473",
138 feature = "g474",
139 feature = "g483",
140 feature = "g484",
141 feature = "h5",
142 feature = "l5",
143 feature = "h7"
144)))]
145fn page_to_address(page: usize) -> usize {
146 BANK1_START_ADDR + page * PAGE_SIZE
147}
148
149#[cfg(any(
150 feature = "g473",
151 feature = "g474",
152 feature = "g483",
153 feature = "g484",
154 feature = "h5",
155 feature = "l5",
156))]
157fn page_to_address(dual_bank: DualBank, bank: Bank, page: usize) -> usize {
158 if dual_bank == DualBank::Single {
159 BANK1_START_ADDR + page * PAGE_SIZE_SINGLE_BANK
160 } else {
161 match bank {
162 Bank::B1 => BANK1_START_ADDR + page * PAGE_SIZE_DUAL_BANK,
163 Bank::B2 => BANK2_START_ADDR + page * PAGE_SIZE_DUAL_BANK,
164 }
165 }
166}
167
168#[cfg(feature = "h7")]
169fn page_to_address(bank: Bank, sector: usize) -> usize {
172 let starting_pt = match bank {
174 Bank::B1 => BANK1_START_ADDR,
175 #[cfg(not(any(feature = "h747cm4", feature = "h747cm7")))]
177 Bank::B2 => BANK2_START_ADDR,
178 };
179
180 starting_pt + sector * SECTOR_SIZE
181}