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;
 use core::ptr::write_volatile;
 use core::sync::atomic::{fence, Ordering};
 
+use atomic_polyfill::AtomicBool;
 #[cfg(feature = "nightly")]
 use embassy_sync::waitqueue::AtomicWaker;
 use pac::flash::regs::Sr;
 
-use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
+use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE};
 use crate::flash::Error;
 use crate::pac;
 
@@ -167,6 +168,7 @@ pub use alt_regions::*;
 
 #[cfg(feature = "nightly")]
 static WAKER: AtomicWaker = AtomicWaker::new();
+static DATA_CACHE_WAS_ENABLED: AtomicBool = AtomicBool::new(false);
 
 impl FlashSector {
     const fn snb(&self) -> u8 {
@@ -238,6 +240,7 @@ pub(crate) unsafe fn unlock() {
 #[cfg(feature = "nightly")]
 pub(crate) unsafe fn enable_write() {
     assert_eq!(0, WRITE_SIZE % 4);
+    save_data_cache_state();
 
     pac::FLASH.cr().write(|w| {
         w.set_pg(true);
@@ -254,10 +257,12 @@ pub(crate) unsafe fn disable_write() {
         w.set_eopie(false);
         w.set_errie(false);
     });
+    restore_data_cache_state();
 }
 
 pub(crate) unsafe fn enable_blocking_write() {
     assert_eq!(0, WRITE_SIZE % 4);
+    save_data_cache_state();
 
     pac::FLASH.cr().write(|w| {
         w.set_pg(true);
@@ -267,6 +272,7 @@ pub(crate) unsafe fn enable_blocking_write() {
 
 pub(crate) unsafe fn disable_blocking_write() {
     pac::FLASH.cr().write(|w| w.set_pg(false));
+    restore_data_cache_state();
 }
 
 #[cfg(feature = "nightly")]
@@ -293,6 +299,8 @@ unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) {
 
 #[cfg(feature = "nightly")]
 pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> {
+    save_data_cache_state();
+
     pac::FLASH.cr().modify(|w| {
         w.set_ser(true);
         w.set_snb(sector.snb());
@@ -310,10 +318,13 @@ pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Erro
         w.set_errie(false);
     });
     clear_all_err();
+    restore_data_cache_state();
     ret
 }
 
 pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> {
+    save_data_cache_state();
+
     pac::FLASH.cr().modify(|w| {
         w.set_ser(true);
         w.set_snb(sector.snb())
@@ -325,6 +336,7 @@ pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), E
 
     let ret: Result<(), Error> = wait_ready_blocking();
     clear_all_err();
+    restore_data_cache_state();
     ret
 }
 
@@ -380,6 +392,33 @@ fn get_result(sr: Sr) -> Result<(), Error> {
     }
 }
 
+fn save_data_cache_state() {
+    let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2;
+    if dual_bank {
+        // Disable data cache during write/erase if there are two banks, see errata 2.2.12
+        let dcen = unsafe { pac::FLASH.acr().read().dcen() };
+        DATA_CACHE_WAS_ENABLED.store(dcen, Ordering::Relaxed);
+        if dcen {
+            unsafe { pac::FLASH.acr().modify(|w| w.set_dcen(false)) };
+        }
+    }
+}
+
+fn restore_data_cache_state() {
+    let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2;
+    if dual_bank {
+        // Restore data cache if it was enabled
+        let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed);
+        if dcen {
+            unsafe {
+                // Reset data cache before we enable it again
+                pac::FLASH.acr().modify(|w| w.set_dcrst(true));
+                pac::FLASH.acr().modify(|w| w.set_dcen(true))
+            };
+        }
+    }
+}
+
 pub(crate) fn assert_not_corrupted_read() {
     #[allow(unused)]
     const REVISION_3: u16 = 0x2001;