diff --git a/src/flash/low_level.rs b/src/flash/low_level.rs index 4ae903f..5c042be 100644 --- a/src/flash/low_level.rs +++ b/src/flash/low_level.rs @@ -2,6 +2,7 @@ use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; use crate::pac; +use crate::pac::rcc::vals::HsiFs; use super::{Error, FlashUnit}; use super::values::*; @@ -17,35 +18,6 @@ pub(crate) unsafe fn unlock() { } } -// unsafe fn timing_sequence_config() { -// let hsifs = pac::RCC.icscr().read().hsi_fs(); - -// let timing = get_timing_sequence(hsifs); - -// pac::FLASH.ts0().write(|w| w.set_ts0(timing.ts0)); -// pac::FLASH.ts1().write(|w| w.set_ts1(timing.ts1)); -// pac::FLASH.ts3().write(|w| w.set_ts3(timing.ts3)); -// pac::FLASH.ts2p().write(|w| w.set_ts2p(timing.ts2p)); -// pac::FLASH.tps3().write(|w| w.set_tps3(timing.tps3)); -// pac::FLASH.pertpe().write(|w| w.set_pertpe(timing.pertpe)); -// pac::FLASH.smertpe().write(|w| w.set_smertpe(timing.smertpe)); -// pac::FLASH.prgtpe().write(|w| w.set_prgtpe(timing.prgtpe)); -// pac::FLASH.pretpe().write(|w| w.set_pretpe(timing.pretpe)); - -// } - -struct Timing { - ts0: u8, - ts1: u16, - ts3: u8, - ts2p: u8, - tps3: u16, - pertpe: u32, - smertpe: u32, - prgtpe: u16, - pretpe: u16, -} - pub(crate) unsafe fn enable_blocking_write() { pac::FLASH.cr().modify(|w| w.set_pg(true)); pac::FLASH.cr().modify(|w| w.set_eopie(true)); @@ -147,4 +119,22 @@ pub(crate) unsafe fn clear_all_err() { // read and write back the same value. // This clears all "write 1 to clear" bits. pac::FLASH.sr().modify(|_| {}); +} + +pub(crate) unsafe fn timing_sequence_config(configured: Option) { + let hsifs = pac::RCC.icscr().read().hsi_fs(); + + if Some(hsifs) != configured { + let eppara = pac::CONFIGBYTES.eppara(hsifs as usize); + + pac::FLASH.ts0().write(|w| w.set_ts0(eppara.eppara0().read().ts0())); + pac::FLASH.ts1().write(|w| w.set_ts1(eppara.eppara0().read().ts1())); + pac::FLASH.ts3().write(|w| w.set_ts3(eppara.eppara0().read().ts3())); + pac::FLASH.ts2p().write(|w| w.set_ts2p(eppara.eppara1().read().ts2p())); + pac::FLASH.tps3().write(|w| w.set_tps3(eppara.eppara1().read().tps3())); + pac::FLASH.pertpe().write(|w| w.set_pertpe(eppara.eppara2().read().pertpe())); + pac::FLASH.smertpe().write(|w| w.set_smertpe(eppara.eppara3().read().smertpe())); + pac::FLASH.pretpe().write(|w| w.set_pretpe(eppara.eppara4().read().pretpe())); + pac::FLASH.prgtpe().write(|w| w.set_prgtpe(eppara.eppara4().read().prgtpe())); + } } \ No newline at end of file diff --git a/src/flash/mod.rs b/src/flash/mod.rs index 5e94e30..ced111d 100644 --- a/src/flash/mod.rs +++ b/src/flash/mod.rs @@ -4,6 +4,7 @@ use core::sync::atomic::{fence, Ordering}; use embassy_hal_internal::drop::OnDrop; use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; +use crate::pac::rcc::vals::HsiFs; use crate::mode::{Async, Blocking}; use crate::peripherals::FLASH; @@ -47,8 +48,11 @@ pub enum FlashUnit { /// Internal flash memory driver. pub struct Flash<'d, MODE = Async> { - pub(crate) inner: PeripheralRef<'d, FLASH>, + pub(crate) _inner: PeripheralRef<'d, FLASH>, pub(crate) _mode: PhantomData, + // size_of::>() == 1 byte + // TODO: PY32F072 timing regs reset value is 24mhz. Should we use that? + pub(crate) timing_configured: Option, } impl<'d> Flash<'d, Blocking> { @@ -56,9 +60,14 @@ impl<'d> Flash<'d, Blocking> { pub fn new_blocking(p: impl Peripheral

+ 'd) -> Self { into_ref!(p); + // unsafe { low_level::timing_sequence_config() }; + // let ts1 = crate::pac::FLASH.ts1().read().ts1(); + // info!("FLASH TS1: 0x{:x}", ts1 as u16); + Self { - inner: p, + _inner: p, _mode: PhantomData, + timing_configured: None, } } } @@ -95,7 +104,7 @@ impl<'d, MODE> Flash<'d, MODE> { let mut address = FLASH_BASE + offset; trace!("Writing {} bytes at 0x{:x}", bytes.len(), address); for chunk in bytes.chunks(WRITE_SIZE) { - unsafe { write_chunk_with_critical_section(address, chunk) }?; + unsafe { write_chunk_with_critical_section(address, chunk, self.timing_configured) }?; address += WRITE_SIZE as u32; } Ok(()) @@ -124,12 +133,12 @@ impl<'d, MODE> Flash<'d, MODE> { if use_sector { let sector = get_sector(address); trace!("Erasing sector: {:?}", sector); - unsafe { erase_unit_unlocked(&FlashUnit::Sector(sector)) }?; + unsafe { erase_unit_with_critical_section(&FlashUnit::Sector(sector), self.timing_configured) }?; address += SECTOR_SIZE; } else { let page = get_page(address); trace!("Erasing page: {:?}", page); - unsafe { erase_unit_unlocked(&FlashUnit::Page(page)) }?; + unsafe { erase_unit_with_critical_section(&FlashUnit::Page(page), self.timing_configured) }?; address += PAGE_SIZE; } } @@ -137,7 +146,7 @@ impl<'d, MODE> Flash<'d, MODE> { } } -#[cfg(py32f072)] +// #[cfg(py32f072)] pub mod values { pub const WRITE_SIZE: usize = 0x100; pub const READ_SIZE: usize = 1; @@ -152,11 +161,13 @@ pub mod values { } use values::*; -pub(super) unsafe fn write_chunk_unlocked(address: u32, chunk: &[u8]) -> Result<(), Error> { +pub(super) unsafe fn write_chunk_unlocked(address: u32, chunk: &[u8], timing_configured: Option) -> Result<(), Error> { low_level::clear_all_err(); fence(Ordering::SeqCst); low_level::unlock(); fence(Ordering::SeqCst); + low_level::timing_sequence_config(timing_configured); + fence(Ordering::SeqCst); low_level::enable_blocking_write(); fence(Ordering::SeqCst); @@ -169,23 +180,25 @@ pub(super) unsafe fn write_chunk_unlocked(address: u32, chunk: &[u8]) -> Result< low_level::blocking_write(address, unwrap!(chunk.try_into())) } -pub(super) unsafe fn write_chunk_with_critical_section(address: u32, chunk: &[u8]) -> Result<(), Error> { - critical_section::with(|_| write_chunk_unlocked(address, chunk)) +pub(super) unsafe fn write_chunk_with_critical_section(address: u32, chunk: &[u8], timing_configured: Option) -> Result<(), Error> { + critical_section::with(|_| write_chunk_unlocked(address, chunk, timing_configured)) } -pub(super) unsafe fn erase_unit_unlocked(unit: &FlashUnit) -> Result<(), Error> { +pub(super) unsafe fn erase_unit_unlocked(unit: &FlashUnit, timing_configured: Option) -> Result<(), Error> { low_level::clear_all_err(); fence(Ordering::SeqCst); low_level::unlock(); fence(Ordering::SeqCst); + low_level::timing_sequence_config(timing_configured); + fence(Ordering::SeqCst); let _on_drop = OnDrop::new(|| low_level::lock()); low_level::blocking_erase_unit(unit) } -pub(super) unsafe fn erase_unit_with_critical_section(unit: &FlashUnit) -> Result<(), Error> { - critical_section::with(|_| erase_unit_unlocked(unit)) +pub(super) unsafe fn erase_unit_with_critical_section(unit: &FlashUnit, timing_configured: Option) -> Result<(), Error> { + critical_section::with(|_| erase_unit_unlocked(unit, timing_configured)) } pub(super) fn get_sector(address: u32) -> FlashSector {