From f3700b4e42fbb0e0e4876307ba5533b7b215f5e3 Mon Sep 17 00:00:00 2001 From: Matous Hybl Date: Mon, 2 May 2022 15:36:02 +0200 Subject: [PATCH] Refactor flash handling to different modules for different families --- embassy-stm32/src/flash/f3.rs | 104 ++++++++++++++ embassy-stm32/src/flash/l.rs | 185 +++++++++++++++++++++++++ embassy-stm32/src/flash/mod.rs | 244 ++------------------------------- 3 files changed, 298 insertions(+), 235 deletions(-) create mode 100644 embassy-stm32/src/flash/f3.rs create mode 100644 embassy-stm32/src/flash/l.rs diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs new file mode 100644 index 00000000..a5dc8dd0 --- /dev/null +++ b/embassy-stm32/src/flash/f3.rs @@ -0,0 +1,104 @@ +use core::convert::TryInto; +use core::ptr::write_volatile; + +use crate::flash::Error; +use crate::pac; + +pub(crate) unsafe fn lock() { + pac::FLASH.cr().modify(|w| w.set_lock(true)); +} + +pub(crate) unsafe fn unlock() { + pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123)); + pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); +} + +pub(crate) unsafe fn blocking_write(offset: u32, buf: &[u8]) -> Result<(), Error> { + pac::FLASH.cr().write(|w| w.set_pg(true)); + + let ret = { + let mut ret: Result<(), Error> = Ok(()); + let mut offset = offset; + for chunk in buf.chunks(2) { + write_volatile( + offset as *mut u16, + u16::from_le_bytes(chunk[0..2].try_into().unwrap()), + ); + offset += chunk.len() as u32; + + ret = blocking_wait_ready(); + if ret.is_err() { + break; + } + } + ret + }; + + pac::FLASH.cr().write(|w| w.set_pg(false)); + + ret +} + +pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> { + for page in (from..to).step_by(super::ERASE_SIZE) { + pac::FLASH.cr().modify(|w| { + w.set_per(true); + }); + + pac::FLASH.ar().write(|w| w.set_far(page)); + + pac::FLASH.cr().modify(|w| { + w.set_strt(true); + }); + + let mut ret: Result<(), Error> = blocking_wait_ready(); + + if !pac::FLASH.sr().read().eop() { + trace!("FLASH: EOP not set"); + ret = Err(Error::Prog); + } else { + pac::FLASH.sr().write(|w| w.set_eop(true)); + } + + pac::FLASH.cr().modify(|w| w.set_per(false)); + + clear_all_err(); + if ret.is_err() { + return ret; + } + } + + Ok(()) +} + +pub(crate) unsafe fn clear_all_err() { + pac::FLASH.sr().modify(|w| { + if w.pgerr() { + w.set_pgerr(true); + } + if w.wrprterr() { + w.set_wrprterr(true); + } + if w.eop() { + w.set_eop(true); + } + }); +} + +pub(crate) unsafe fn blocking_wait_ready() -> Result<(), Error> { + loop { + let sr = pac::FLASH.sr().read(); + + if !sr.bsy() { + if sr.wrprterr() { + return Err(Error::Protected); + } + + if sr.pgerr() { + return Err(Error::Seq); + } + + return Ok(()); + } + } +} diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs new file mode 100644 index 00000000..6ec4796a --- /dev/null +++ b/embassy-stm32/src/flash/l.rs @@ -0,0 +1,185 @@ +use core::convert::TryInto; +use core::ptr::write_volatile; + +use crate::flash::Error; +use crate::pac; + +pub(crate) unsafe fn lock() { + #[cfg(any(flash_wl, flash_wb, flash_l4))] + pac::FLASH.cr().modify(|w| w.set_lock(true)); + + #[cfg(any(flash_l0))] + pac::FLASH.pecr().modify(|w| { + w.set_optlock(true); + w.set_prglock(true); + w.set_pelock(true); + }); +} + +pub(crate) unsafe fn unlock() { + #[cfg(any(flash_wl, flash_wb, flash_l4))] + { + pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123)); + pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB)); + } + + #[cfg(any(flash_l0, flash_l1))] + { + pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x89ABCDEF)); + pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x02030405)); + + pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x8C9DAEBF)); + pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x13141516)); + } +} + +pub(crate) unsafe fn blocking_write(offset: u32, buf: &[u8]) -> Result<(), Error> { + #[cfg(any(flash_wl, flash_wb, flash_l4))] + pac::FLASH.cr().write(|w| w.set_pg(true)); + + let ret = { + let mut ret: Result<(), Error> = Ok(()); + let mut offset = offset; + for chunk in buf.chunks(super::WRITE_SIZE) { + for val in chunk.chunks(4) { + write_volatile( + offset as *mut u32, + u32::from_le_bytes(val[0..4].try_into().unwrap()), + ); + offset += val.len() as u32; + } + + ret = blocking_wait_ready(); + if ret.is_err() { + break; + } + } + ret + }; + + #[cfg(any(flash_wl, flash_wb, flash_l4))] + pac::FLASH.cr().write(|w| w.set_pg(false)); + + ret +} + +pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> { + for page in (from..to).step_by(super::ERASE_SIZE) { + #[cfg(any(flash_l0, flash_l1))] + { + pac::FLASH.pecr().modify(|w| { + w.set_erase(true); + w.set_prog(true); + }); + + write_volatile(page as *mut u32, 0xFFFFFFFF); + } + + #[cfg(any(flash_wl, flash_wb, flash_l4))] + { + let idx = page / super::ERASE_SIZE as u32; + + pac::FLASH.cr().modify(|w| { + w.set_per(true); + w.set_pnb(idx as u8); + #[cfg(any(flash_wl, flash_wb))] + w.set_strt(true); + #[cfg(any(flash_l4))] + w.set_start(true); + }); + } + + let ret: Result<(), Error> = blocking_wait_ready(); + + #[cfg(any(flash_wl, flash_wb, flash_l4))] + pac::FLASH.cr().modify(|w| w.set_per(false)); + + #[cfg(any(flash_l0, flash_l1))] + pac::FLASH.pecr().modify(|w| { + w.set_erase(false); + w.set_prog(false); + }); + + clear_all_err(); + if ret.is_err() { + return ret; + } + } + + Ok(()) +} + +pub(crate) unsafe fn clear_all_err() { + pac::FLASH.sr().modify(|w| { + #[cfg(any(flash_wl, flash_wb, flash_l4, flash_l0))] + if w.rderr() { + w.set_rderr(true); + } + #[cfg(any(flash_wl, flash_wb, flash_l4))] + if w.fasterr() { + w.set_fasterr(true); + } + #[cfg(any(flash_wl, flash_wb, flash_l4))] + if w.miserr() { + w.set_miserr(true); + } + #[cfg(any(flash_wl, flash_wb, flash_l4))] + if w.pgserr() { + w.set_pgserr(true); + } + if w.sizerr() { + w.set_sizerr(true); + } + if w.pgaerr() { + w.set_pgaerr(true); + } + if w.wrperr() { + w.set_wrperr(true); + } + #[cfg(any(flash_wl, flash_wb, flash_l4))] + if w.progerr() { + w.set_progerr(true); + } + #[cfg(any(flash_wl, flash_wb, flash_l4))] + if w.operr() { + w.set_operr(true); + } + }); +} + +pub(crate) unsafe fn blocking_wait_ready() -> Result<(), Error> { + loop { + let sr = pac::FLASH.sr().read(); + + if !sr.bsy() { + #[cfg(any(flash_wl, flash_wb, flash_l4))] + if sr.progerr() { + return Err(Error::Prog); + } + + if sr.wrperr() { + return Err(Error::Protected); + } + + if sr.pgaerr() { + return Err(Error::Unaligned); + } + + if sr.sizerr() { + return Err(Error::Size); + } + + #[cfg(any(flash_wl, flash_wb, flash_l4))] + if sr.miserr() { + return Err(Error::Miss); + } + + #[cfg(any(flash_wl, flash_wb, flash_l4))] + if sr.pgserr() { + return Err(Error::Seq); + } + + return Ok(()); + } + } +} diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 0ce74a5e..8b2a7711 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -1,8 +1,5 @@ -use crate::pac; use crate::peripherals::FLASH; -use core::convert::TryInto; use core::marker::PhantomData; -use core::ptr::write_volatile; use embassy::util::Unborrow; use embassy_hal_common::unborrow; @@ -17,6 +14,10 @@ pub use crate::pac::FLASH_SIZE; pub use crate::pac::WRITE_SIZE; const FLASH_END: usize = FLASH_BASE + FLASH_SIZE; +#[cfg_attr(any(flash_wl, flash_wb, flash_l0, flash_l1, flash_l4), path = "l.rs")] +#[cfg_attr(flash_f3, path = "f3.rs")] +mod family; + pub struct Flash<'d> { _inner: FLASH, _phantom: PhantomData<&'d mut FLASH>, @@ -33,37 +34,13 @@ impl<'d> Flash<'d> { pub fn unlock(p: impl Unborrow) -> Self { let flash = Self::new(p); - #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))] - unsafe { - pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123)); - pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB)); - } - #[cfg(any(flash_l0, flash_l1))] - unsafe { - pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x89ABCDEF)); - pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x02030405)); - - pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x8C9DAEBF)); - pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x13141516)); - } + unsafe { family::unlock() }; flash } pub fn lock(&mut self) { - #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))] - unsafe { - pac::FLASH.cr().modify(|w| w.set_lock(true)); - } - - #[cfg(any(flash_l0))] - unsafe { - pac::FLASH.pecr().modify(|w| { - w.set_optlock(true); - w.set_prglock(true); - w.set_pelock(true); - }); - } + unsafe { family::lock() }; } pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { @@ -89,61 +66,7 @@ impl<'d> Flash<'d> { self.clear_all_err(); - #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))] - unsafe { - pac::FLASH.cr().write(|w| w.set_pg(true)) - } - - #[cfg(not(flash_f3))] - let ret = { - let mut ret: Result<(), Error> = Ok(()); - let mut offset = offset; - for chunk in buf.chunks(WRITE_SIZE) { - for val in chunk.chunks(4) { - unsafe { - write_volatile( - offset as *mut u32, - u32::from_le_bytes(val[0..4].try_into().unwrap()), - ); - } - offset += val.len() as u32; - } - - ret = self.blocking_wait_ready(); - if ret.is_err() { - break; - } - } - ret - }; - - #[cfg(flash_f3)] - let ret = { - let mut ret: Result<(), Error> = Ok(()); - let mut offset = offset; - for chunk in buf.chunks(2) { - unsafe { - write_volatile( - offset as *mut u16, - u16::from_le_bytes(chunk[0..2].try_into().unwrap()), - ); - } - offset += chunk.len() as u32; - - ret = self.blocking_wait_ready(); - if ret.is_err() { - break; - } - } - ret - }; - - #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))] - unsafe { - pac::FLASH.cr().write(|w| w.set_pg(false)) - } - - ret + unsafe { family::blocking_write(offset, buf) } } pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { @@ -158,160 +81,11 @@ impl<'d> Flash<'d> { self.clear_all_err(); - for page in (from..to).step_by(ERASE_SIZE) { - #[cfg(any(flash_l0, flash_l1))] - unsafe { - pac::FLASH.pecr().modify(|w| { - w.set_erase(true); - w.set_prog(true); - }); - - write_volatile(page as *mut u32, 0xFFFFFFFF); - } - - #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))] - unsafe { - #[cfg(not(flash_f3))] - let idx = page / ERASE_SIZE as u32; - - pac::FLASH.cr().modify(|w| { - w.set_per(true); - #[cfg(not(flash_f3))] - w.set_pnb(idx as u8); - #[cfg(any(flash_wl, flash_wb))] - w.set_strt(true); - #[cfg(any(flash_l4))] - w.set_start(true); - }); - - #[cfg(flash_f3)] - pac::FLASH.ar().write(|w| w.set_far(page)); - - #[cfg(flash_f3)] - pac::FLASH.cr().modify(|w| { - w.set_strt(true); - }); - } - - let ret: Result<(), Error> = self.blocking_wait_ready(); - - unsafe { - if pac::FLASH.sr().read().eop() { - pac::FLASH.sr().modify(|w| w.set_eop(true)); - } else { - panic!("wtf") - } - } - - #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))] - unsafe { - pac::FLASH.cr().modify(|w| w.set_per(false)); - } - - #[cfg(any(flash_l0, flash_l1))] - unsafe { - pac::FLASH.pecr().modify(|w| { - w.set_erase(false); - w.set_prog(false); - }); - } - - self.clear_all_err(); - if ret.is_err() { - return ret; - } - } - - Ok(()) - } - - fn blocking_wait_ready(&self) -> Result<(), Error> { - loop { - let sr = unsafe { pac::FLASH.sr().read() }; - - if !sr.bsy() { - #[cfg(any(flash_wl, flash_wb, flash_l4))] - if sr.progerr() { - return Err(Error::Prog); - } - - if sr.wrperr() { - return Err(Error::Protected); - } - - #[cfg(not(flash_f3))] - if sr.pgaerr() { - return Err(Error::Unaligned); - } - - #[cfg(not(flash_f3))] - if sr.sizerr() { - return Err(Error::Size); - } - - #[cfg(any(flash_wl, flash_wb, flash_l4))] - if sr.miserr() { - return Err(Error::Miss); - } - - #[cfg(any(flash_wl, flash_wb, flash_l4))] - if sr.pgserr() { - return Err(Error::Seq); - } - - #[cfg(flash_f3)] - if sr.pgerr() { - return Err(Error::Seq); - } - return Ok(()); - } - } + unsafe { family::blocking_erase(from, to) } } fn clear_all_err(&mut self) { - unsafe { - pac::FLASH.sr().modify(|w| { - #[cfg(any(flash_wl, flash_wb, flash_l4, flash_l0))] - if w.rderr() { - w.set_rderr(true); - } - #[cfg(any(flash_wl, flash_wb, flash_l4))] - if w.fasterr() { - w.set_fasterr(true); - } - #[cfg(any(flash_wl, flash_wb, flash_l4))] - if w.miserr() { - w.set_miserr(true); - } - #[cfg(any(flash_wl, flash_wb, flash_l4))] - if w.pgserr() { - w.set_pgserr(true); - } - #[cfg(flash_f3)] - if w.pgerr() { - w.set_pgerr(true); - } - #[cfg(not(flash_f3))] - if w.sizerr() { - w.set_sizerr(true); - } - #[cfg(not(flash_f3))] - if w.pgaerr() { - w.set_pgaerr(true); - } - if w.wrperr() { - w.set_wrperr(true); - } - #[cfg(any(flash_wl, flash_wb, flash_l4))] - if w.progerr() { - w.set_progerr(true); - } - #[cfg(any(flash_wl, flash_wb, flash_l4))] - if w.operr() { - w.set_operr(true); - } - }); - } + unsafe { family::clear_all_err() }; } }