aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorRasmus Melchior Jacobsen <[email protected]>2023-05-25 21:14:35 +0200
committerRasmus Melchior Jacobsen <[email protected]>2023-05-25 21:14:35 +0200
commit18d14dff48d1fd49cfd43fb94304bf932a74a6ca (patch)
tree8d870c031b0b444d324ff3665be676411df23c2f /embassy-stm32
parentb412784a7aea102ef53744fbb11d473fa3c0c984 (diff)
Handle errata 2.2.12
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/flash/f4.rs41
1 files changed, 40 insertions, 1 deletions
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
index 488584212..d67e6d0a1 100644
--- a/embassy-stm32/src/flash/f4.rs
+++ b/embassy-stm32/src/flash/f4.rs
@@ -2,11 +2,12 @@ use core::convert::TryInto;
2use core::ptr::write_volatile; 2use core::ptr::write_volatile;
3use core::sync::atomic::{fence, Ordering}; 3use core::sync::atomic::{fence, Ordering};
4 4
5use atomic_polyfill::AtomicBool;
5#[cfg(feature = "nightly")] 6#[cfg(feature = "nightly")]
6use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
7use pac::flash::regs::Sr; 8use pac::flash::regs::Sr;
8 9
9use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; 10use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
10use crate::flash::Error; 11use crate::flash::Error;
11use crate::pac; 12use crate::pac;
12 13
@@ -167,6 +168,7 @@ pub use alt_regions::*;
167 168
168#[cfg(feature = "nightly")] 169#[cfg(feature = "nightly")]
169static WAKER: AtomicWaker = AtomicWaker::new(); 170static WAKER: AtomicWaker = AtomicWaker::new();
171static DATA_CACHE_WAS_ENABLED: AtomicBool = AtomicBool::new(false);
170 172
171impl FlashSector { 173impl FlashSector {
172 const fn snb(&self) -> u8 { 174 const fn snb(&self) -> u8 {
@@ -238,6 +240,7 @@ pub(crate) unsafe fn unlock() {
238#[cfg(feature = "nightly")] 240#[cfg(feature = "nightly")]
239pub(crate) unsafe fn enable_write() { 241pub(crate) unsafe fn enable_write() {
240 assert_eq!(0, WRITE_SIZE % 4); 242 assert_eq!(0, WRITE_SIZE % 4);
243 save_data_cache_state();
241 244
242 pac::FLASH.cr().write(|w| { 245 pac::FLASH.cr().write(|w| {
243 w.set_pg(true); 246 w.set_pg(true);
@@ -254,10 +257,12 @@ pub(crate) unsafe fn disable_write() {
254 w.set_eopie(false); 257 w.set_eopie(false);
255 w.set_errie(false); 258 w.set_errie(false);
256 }); 259 });
260 restore_data_cache_state();
257} 261}
258 262
259pub(crate) unsafe fn enable_blocking_write() { 263pub(crate) unsafe fn enable_blocking_write() {
260 assert_eq!(0, WRITE_SIZE % 4); 264 assert_eq!(0, WRITE_SIZE % 4);
265 save_data_cache_state();
261 266
262 pac::FLASH.cr().write(|w| { 267 pac::FLASH.cr().write(|w| {
263 w.set_pg(true); 268 w.set_pg(true);
@@ -267,6 +272,7 @@ pub(crate) unsafe fn enable_blocking_write() {
267 272
268pub(crate) unsafe fn disable_blocking_write() { 273pub(crate) unsafe fn disable_blocking_write() {
269 pac::FLASH.cr().write(|w| w.set_pg(false)); 274 pac::FLASH.cr().write(|w| w.set_pg(false));
275 restore_data_cache_state();
270} 276}
271 277
272#[cfg(feature = "nightly")] 278#[cfg(feature = "nightly")]
@@ -293,6 +299,8 @@ unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) {
293 299
294#[cfg(feature = "nightly")] 300#[cfg(feature = "nightly")]
295pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> { 301pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> {
302 save_data_cache_state();
303
296 pac::FLASH.cr().modify(|w| { 304 pac::FLASH.cr().modify(|w| {
297 w.set_ser(true); 305 w.set_ser(true);
298 w.set_snb(sector.snb()); 306 w.set_snb(sector.snb());
@@ -310,10 +318,13 @@ pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Erro
310 w.set_errie(false); 318 w.set_errie(false);
311 }); 319 });
312 clear_all_err(); 320 clear_all_err();
321 restore_data_cache_state();
313 ret 322 ret
314} 323}
315 324
316pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { 325pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> {
326 save_data_cache_state();
327
317 pac::FLASH.cr().modify(|w| { 328 pac::FLASH.cr().modify(|w| {
318 w.set_ser(true); 329 w.set_ser(true);
319 w.set_snb(sector.snb()) 330 w.set_snb(sector.snb())
@@ -325,6 +336,7 @@ pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), E
325 336
326 let ret: Result<(), Error> = wait_ready_blocking(); 337 let ret: Result<(), Error> = wait_ready_blocking();
327 clear_all_err(); 338 clear_all_err();
339 restore_data_cache_state();
328 ret 340 ret
329} 341}
330 342
@@ -380,6 +392,33 @@ fn get_result(sr: Sr) -> Result<(), Error> {
380 } 392 }
381} 393}
382 394
395fn save_data_cache_state() {
396 let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2;
397 if dual_bank {
398 // Disable data cache during write/erase if there are two banks, see errata 2.2.12
399 let dcen = unsafe { pac::FLASH.acr().read().dcen() };
400 DATA_CACHE_WAS_ENABLED.store(dcen, Ordering::Relaxed);
401 if dcen {
402 unsafe { pac::FLASH.acr().modify(|w| w.set_dcen(false)) };
403 }
404 }
405}
406
407fn restore_data_cache_state() {
408 let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2;
409 if dual_bank {
410 // Restore data cache if it was enabled
411 let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed);
412 if dcen {
413 unsafe {
414 // Reset data cache before we enable it again
415 pac::FLASH.acr().modify(|w| w.set_dcrst(true));
416 pac::FLASH.acr().modify(|w| w.set_dcen(true))
417 };
418 }
419 }
420}
421
383pub(crate) fn assert_not_corrupted_read() { 422pub(crate) fn assert_not_corrupted_read() {
384 #[allow(unused)] 423 #[allow(unused)]
385 const REVISION_3: u16 = 0x2001; 424 const REVISION_3: u16 = 0x2001;