1 | use core::ptr::write_volatile; |
2 | use core::sync::atomic::{fence, Ordering}; |
3 | |
4 | use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; |
5 | use crate::flash::Error; |
6 | use crate::pac; |
7 | |
8 | pub(crate) const fn is_default_layout() -> bool { |
9 | true |
10 | } |
11 | |
12 | pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
13 | &FLASH_REGIONS |
14 | } |
15 | |
16 | pub(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 | |
23 | pub(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 | |
36 | pub(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 | |
49 | pub(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 | |
56 | pub(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 | |
69 | pub(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 | |
113 | pub(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 | |
122 | unsafe 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 | |