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#[derive(Debug, Clone, Copy, Eq, PartialEq, defmt::Format)]
44pub enum FlashError {
46 Busy,
48 Illegal,
50 EccError,
52 PageOutOfRange,
54 Failure,
56}
57
58pub struct Flash {
59 pub regs: FLASH,
60 #[cfg(any(
61 feature = "g473",
62 feature = "g474",
63 feature = "g483",
64 feature = "g484",
65 feature = "l5"
66 ))]
67 pub dual_bank: DualBank,
68}
69
70impl Flash {
74 pub fn new(regs: FLASH) -> Self {
76 cfg_if! {
77 if #[cfg(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484", feature = "l5"))] {
78 Self { regs, dual_bank: DualBank::Dual } } else {
82 Self { regs }
83 }
84 }
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}