1use core::ptr::write_volatile;
2use core::sync::atomic::{fence, Ordering};
3
4use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
5use crate::flash::Error;
6use crate::pac;
7
8pub(crate) const fn is_default_layout() -> bool {
9 true
10}
11
12pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] {
13 &FLASH_REGIONS
14}
15
16pub(crate) unsafe fn lock() {
17 #[cfg(feature = "trustzone-secure")]
18 pac::FLASH.seccr().modify(|w| w.set_lock(true));
19 #[cfg(not(feature = "trustzone-secure"))]
20 pac::FLASH.nscr().modify(|w: &mut Nscr| w.set_lock(val:true));
21}
22
23pub(crate) unsafe fn unlock() {
24 #[cfg(feature = "trustzone-secure")]
25 if pac::FLASH.seccr().read().lock() {
26 pac::FLASH.seckeyr().write_value(0x4567_0123);
27 pac::FLASH.seckeyr().write_value(0xCDEF_89AB);
28 }
29 #[cfg(not(feature = "trustzone-secure"))]
30 if pac::FLASH.nscr().read().lock() {
31 pac::FLASH.nskeyr().write_value(val:0x4567_0123);
32 pac::FLASH.nskeyr().write_value(val:0xCDEF_89AB);
33 }
34}
35
36pub(crate) unsafe fn enable_blocking_write() {
37 assert_eq!(0, WRITE_SIZE % 4);
38
39 #[cfg(feature = "trustzone-secure")]
40 pac::FLASH.seccr().write(|w| {
41 w.set_pg(pac::flash::vals::SeccrPg::B_0X1);
42 });
43 #[cfg(not(feature = "trustzone-secure"))]
44 pac::FLASH.nscr().write(|w: &mut Nscr| {
45 w.set_pg(val:pac::flash::vals::NscrPg::B_0X1);
46 });
47}
48
49pub(crate) unsafe fn disable_blocking_write() {
50 #[cfg(feature = "trustzone-secure")]
51 pac::FLASH.seccr().write(|w| w.set_pg(pac::flash::vals::SeccrPg::B_0X0));
52 #[cfg(not(feature = "trustzone-secure"))]
53 pac::FLASH.nscr().write(|w: &mut Nscr| w.set_pg(val:pac::flash::vals::NscrPg::B_0X0));
54}
55
56pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> {
57 let mut address: u32 = start_address;
58 for val: &[u8] in buf.chunks(chunk_size:4) {
59 write_volatile(dst:address as *mut u32, src:u32::from_le_bytes(unwrap!(val.try_into())));
60 address += val.len() as u32;
61
62 // prevents parallelism errors
63 fence(order:Ordering::SeqCst);
64 }
65
66 blocking_wait_ready()
67}
68
69pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> {
70 #[cfg(feature = "trustzone-secure")]
71 pac::FLASH.seccr().modify(|w| {
72 w.set_per(pac::flash::vals::SeccrPer::B_0X1);
73 w.set_pnb(sector.index_in_bank);
74 // TODO: add check for bank swap
75 w.set_bker(match sector.bank {
76 FlashBank::Bank1 => pac::flash::vals::SeccrBker::B_0X0,
77 FlashBank::Bank2 => pac::flash::vals::SeccrBker::B_0X1,
78 });
79 });
80 #[cfg(not(feature = "trustzone-secure"))]
81 pac::FLASH.nscr().modify(|w| {
82 w.set_per(pac::flash::vals::NscrPer::B_0X1);
83 w.set_pnb(sector.index_in_bank);
84 // TODO: add check for bank swap
85 w.set_bker(match sector.bank {
86 FlashBank::Bank1 => pac::flash::vals::NscrBker::B_0X0,
87 FlashBank::Bank2 => pac::flash::vals::NscrBker::B_0X1,
88 });
89 });
90
91 #[cfg(feature = "trustzone-secure")]
92 pac::FLASH.seccr().modify(|w| {
93 w.set_strt(true);
94 });
95 #[cfg(not(feature = "trustzone-secure"))]
96 pac::FLASH.nscr().modify(|w| {
97 w.set_strt(true);
98 });
99
100 let ret: Result<(), Error> = blocking_wait_ready();
101 #[cfg(feature = "trustzone-secure")]
102 pac::FLASH
103 .seccr()
104 .modify(|w| w.set_per(pac::flash::vals::SeccrPer::B_0X0));
105 #[cfg(not(feature = "trustzone-secure"))]
106 pac::FLASH
107 .nscr()
108 .modify(|w| w.set_per(pac::flash::vals::NscrPer::B_0X0));
109 clear_all_err();
110 ret
111}
112
113pub(crate) unsafe fn clear_all_err() {
114 // read and write back the same value.
115 // This clears all "write 1 to clear" bits.
116 #[cfg(feature = "trustzone-secure")]
117 pac::FLASH.secsr().modify(|_| {});
118 #[cfg(not(feature = "trustzone-secure"))]
119 pac::FLASH.nssr().modify(|_| {});
120}
121
122unsafe fn blocking_wait_ready() -> Result<(), Error> {
123 loop {
124 #[cfg(feature = "trustzone-secure")]
125 let sr = pac::FLASH.secsr().read();
126 #[cfg(not(feature = "trustzone-secure"))]
127 let sr = pac::FLASH.nssr().read();
128
129 if !sr.bsy() {
130 if sr.pgserr() {
131 return Err(Error::Seq);
132 }
133
134 if sr.sizerr() {
135 return Err(Error::Size);
136 }
137
138 if sr.pgaerr() {
139 return Err(Error::Unaligned);
140 }
141
142 if sr.wrperr() {
143 return Err(Error::Protected);
144 }
145
146 if sr.progerr() {
147 return Err(Error::Prog);
148 }
149
150 return Ok(());
151 }
152 }
153}
154