11use core:: ptr:: write_volatile;
22use core:: sync:: atomic:: { Ordering , fence} ;
33
4+ use embassy_sync:: waitqueue:: AtomicWaker ;
5+ use pac:: flash:: regs:: Sr ;
6+
47use super :: { BANK1_REGION , FLASH_REGIONS , FlashSector , WRITE_SIZE } ;
58use crate :: flash:: Error ;
69use crate :: pac;
710
11+ static WAKER : AtomicWaker = AtomicWaker :: new ( ) ;
12+
13+ pub ( crate ) unsafe fn on_interrupt ( ) {
14+ // Clear IRQ flags
15+ pac:: FLASH . bank ( 0 ) . ccr ( ) . write ( |w| {
16+ w. set_clr_eop ( true ) ;
17+ w. set_clr_operr ( true ) ;
18+ } ) ;
19+ if is_dual_bank ( ) {
20+ pac:: FLASH . bank ( 1 ) . ccr ( ) . write ( |w| {
21+ w. set_clr_eop ( true ) ;
22+ w. set_clr_operr ( true ) ;
23+ } ) ;
24+ }
25+
26+ WAKER . wake ( ) ;
27+ }
28+
829const fn is_dual_bank ( ) -> bool {
930 FLASH_REGIONS . len ( ) >= 2
1031}
@@ -29,12 +50,68 @@ pub(crate) unsafe fn unlock() {
2950 }
3051}
3152
53+ pub ( crate ) unsafe fn enable_write ( ) {
54+ enable_blocking_write ( ) ;
55+ }
56+
57+ pub ( crate ) unsafe fn disable_write ( ) {
58+ disable_blocking_write ( ) ;
59+ }
60+
3261pub ( crate ) unsafe fn enable_blocking_write ( ) {
3362 assert_eq ! ( 0 , WRITE_SIZE % 4 ) ;
3463}
3564
3665pub ( crate ) unsafe fn disable_blocking_write ( ) { }
3766
67+ pub ( crate ) async unsafe fn write ( start_address : u32 , buf : & [ u8 ; WRITE_SIZE ] ) -> Result < ( ) , Error > {
68+ // We cannot have the write setup sequence in begin_write as it depends on the address
69+ let bank = if start_address < BANK1_REGION . end ( ) {
70+ pac:: FLASH . bank ( 0 )
71+ } else {
72+ pac:: FLASH . bank ( 1 )
73+ } ;
74+ bank. cr ( ) . write ( |w| {
75+ w. set_pg ( true ) ;
76+ #[ cfg( flash_h7) ]
77+ w. set_psize ( 2 ) ; // 32 bits at once
78+ w. set_eopie ( true ) ;
79+ w. set_operrie ( true ) ;
80+ } ) ;
81+ cortex_m:: asm:: isb ( ) ;
82+ cortex_m:: asm:: dsb ( ) ;
83+ fence ( Ordering :: SeqCst ) ;
84+
85+ let mut res = None ;
86+ let mut address = start_address;
87+ for val in buf. chunks ( 4 ) {
88+ write_volatile ( address as * mut u32 , u32:: from_le_bytes ( unwrap ! ( val. try_into( ) ) ) ) ;
89+ address += val. len ( ) as u32 ;
90+
91+ res = Some ( wait_ready ( bank) . await ) ;
92+ bank. sr ( ) . modify ( |w| {
93+ if w. eop ( ) {
94+ w. set_eop ( true ) ;
95+ }
96+ } ) ;
97+ if unwrap ! ( res) . is_err ( ) {
98+ break ;
99+ }
100+ }
101+
102+ cortex_m:: asm:: isb ( ) ;
103+ cortex_m:: asm:: dsb ( ) ;
104+ fence ( Ordering :: SeqCst ) ;
105+
106+ bank. cr ( ) . write ( |w| {
107+ w. set_pg ( false ) ;
108+ w. set_eopie ( false ) ;
109+ w. set_operrie ( false ) ;
110+ } ) ;
111+
112+ unwrap ! ( res)
113+ }
114+
38115pub ( crate ) unsafe fn blocking_write ( start_address : u32 , buf : & [ u8 ; WRITE_SIZE ] ) -> Result < ( ) , Error > {
39116 // We cannot have the write setup sequence in begin_write as it depends on the address
40117 let bank = if start_address < BANK1_REGION . end ( ) {
@@ -77,6 +154,36 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE])
77154 unwrap ! ( res)
78155}
79156
157+ pub ( crate ) async unsafe fn erase_sector ( sector : & FlashSector ) -> Result < ( ) , Error > {
158+ let bank = pac:: FLASH . bank ( sector. bank as usize ) ;
159+ bank. cr ( ) . modify ( |w| {
160+ w. set_ser ( true ) ;
161+ #[ cfg( flash_h7) ]
162+ w. set_snb ( sector. index_in_bank ) ;
163+ #[ cfg( flash_h7ab) ]
164+ w. set_ssn ( sector. index_in_bank ) ;
165+ w. set_eopie ( true ) ;
166+ w. set_operrie ( true ) ;
167+ } ) ;
168+
169+ bank. cr ( ) . modify ( |w| {
170+ w. set_start ( true ) ;
171+ } ) ;
172+
173+ cortex_m:: asm:: isb ( ) ;
174+ cortex_m:: asm:: dsb ( ) ;
175+ fence ( Ordering :: SeqCst ) ;
176+
177+ let ret: Result < ( ) , Error > = wait_ready ( bank) . await ;
178+ bank. cr ( ) . modify ( |w| {
179+ w. set_ser ( false ) ;
180+ w. set_eopie ( false ) ;
181+ w. set_operrie ( false ) ;
182+ } ) ;
183+ bank_clear_all_err ( bank) ;
184+ ret
185+ }
186+
80187pub ( crate ) unsafe fn blocking_erase_sector ( sector : & FlashSector ) -> Result < ( ) , Error > {
81188 let bank = pac:: FLASH . bank ( sector. bank as usize ) ;
82189 bank. cr ( ) . modify ( |w| {
@@ -112,46 +219,59 @@ unsafe fn bank_clear_all_err(bank: pac::flash::Bank) {
112219 bank. sr ( ) . modify ( |_| { } ) ;
113220}
114221
222+ async fn wait_ready ( bank : pac:: flash:: Bank ) -> Result < ( ) , Error > {
223+ use core:: future:: poll_fn;
224+ use core:: task:: Poll ;
225+
226+ poll_fn ( |cx| {
227+ WAKER . register ( cx. waker ( ) ) ;
228+
229+ let sr = bank. sr ( ) . read ( ) ;
230+ if !sr. bsy ( ) && !sr. qw ( ) {
231+ Poll :: Ready ( get_result ( sr) )
232+ } else {
233+ return Poll :: Pending ;
234+ }
235+ } )
236+ . await
237+ }
238+
115239unsafe fn blocking_wait_ready ( bank : pac:: flash:: Bank ) -> Result < ( ) , Error > {
116240 loop {
117241 let sr = bank. sr ( ) . read ( ) ;
118242
119243 if !sr. bsy ( ) && !sr. qw ( ) {
120- if sr. wrperr ( ) {
121- return Err ( Error :: Protected ) ;
122- }
123- if sr. pgserr ( ) {
124- error ! ( "pgserr" ) ;
125- return Err ( Error :: Seq ) ;
126- }
127- if sr. incerr ( ) {
128- // writing to a different address when programming 256 bit word was not finished
129- error ! ( "incerr" ) ;
130- return Err ( Error :: Seq ) ;
131- }
132- if sr. crcrderr ( ) {
133- error ! ( "crcrderr" ) ;
134- return Err ( Error :: Seq ) ;
135- }
136- if sr. operr ( ) {
137- return Err ( Error :: Prog ) ;
138- }
139- if sr. sneccerr1 ( ) {
140- // single ECC error
141- return Err ( Error :: Prog ) ;
142- }
143- if sr. dbeccerr ( ) {
144- // double ECC error
145- return Err ( Error :: Prog ) ;
146- }
147- if sr. rdperr ( ) {
148- return Err ( Error :: Protected ) ;
149- }
150- if sr. rdserr ( ) {
151- return Err ( Error :: Protected ) ;
152- }
153-
154- return Ok ( ( ) ) ;
244+ return get_result ( sr) ;
155245 }
156246 }
157247}
248+
249+ fn get_result ( sr : Sr ) -> Result < ( ) , Error > {
250+ if sr. wrperr ( ) {
251+ Err ( Error :: Protected )
252+ } else if sr. pgserr ( ) {
253+ error ! ( "pgserr" ) ;
254+ Err ( Error :: Seq )
255+ } else if sr. incerr ( ) {
256+ // writing to a different address when programming 256 bit word was not finished
257+ error ! ( "incerr" ) ;
258+ Err ( Error :: Seq )
259+ } else if sr. crcrderr ( ) {
260+ error ! ( "crcrderr" ) ;
261+ Err ( Error :: Seq )
262+ } else if sr. operr ( ) {
263+ Err ( Error :: Prog )
264+ } else if sr. sneccerr1 ( ) {
265+ // single ECC error
266+ Err ( Error :: Prog )
267+ } else if sr. dbeccerr ( ) {
268+ // double ECC error
269+ Err ( Error :: Prog )
270+ } else if sr. rdperr ( ) {
271+ Err ( Error :: Protected )
272+ } else if sr. rdserr ( ) {
273+ Err ( Error :: Protected )
274+ } else {
275+ Ok ( ( ) )
276+ }
277+ }
0 commit comments