diff options
| author | Rasmus Melchior Jacobsen <[email protected]> | 2023-03-25 16:04:45 +0100 |
|---|---|---|
| committer | Rasmus Melchior Jacobsen <[email protected]> | 2023-03-25 16:04:45 +0100 |
| commit | bc69eb596e2496a5eb0cf1252ada12f2710aaff2 (patch) | |
| tree | d2a4c233d439cba49e2512fce076155b30d20d3c /embassy-stm32/src/flash/f7.rs | |
| parent | 245147634bfbdcd325eea20be19286708bb29c9f (diff) | |
Add is_eraseable_range and split write into consecutive parts
Diffstat (limited to 'embassy-stm32/src/flash/f7.rs')
| -rw-r--r-- | embassy-stm32/src/flash/f7.rs | 70 |
1 files changed, 34 insertions, 36 deletions
diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index 8b8076e0c..16b684580 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs | |||
| @@ -1,17 +1,13 @@ | |||
| 1 | use core::convert::TryInto; | 1 | use core::convert::TryInto; |
| 2 | use core::mem::size_of; | ||
| 3 | use core::ptr::write_volatile; | 2 | use core::ptr::write_volatile; |
| 4 | use core::sync::atomic::{fence, Ordering}; | 3 | use core::sync::atomic::{fence, Ordering}; |
| 5 | 4 | ||
| 6 | use embassy_hal_common::stm32::flash::f7::get_sector; | 5 | use embassy_hal_common::stm32::flash::f7::get_sector; |
| 7 | 6 | ||
| 8 | use super::FlashRegion; | 7 | use super::WRITE_SIZE; |
| 9 | use crate::flash::Error; | 8 | use crate::flash::Error; |
| 10 | use crate::pac; | 9 | use crate::pac; |
| 11 | 10 | ||
| 12 | pub(crate) const MAX_WRITE_SIZE: usize = super::BANK1_REGION3::WRITE_SIZE; | ||
| 13 | pub(crate) const MAX_ERASE_SIZE: usize = super::BANK1_REGION3::ERASE_SIZE; | ||
| 14 | |||
| 15 | pub(crate) unsafe fn lock() { | 11 | pub(crate) unsafe fn lock() { |
| 16 | pac::FLASH.cr().modify(|w| w.set_lock(true)); | 12 | pac::FLASH.cr().modify(|w| w.set_lock(true)); |
| 17 | } | 13 | } |
| @@ -21,49 +17,51 @@ pub(crate) unsafe fn unlock() { | |||
| 21 | pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); | 17 | pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); |
| 22 | } | 18 | } |
| 23 | 19 | ||
| 24 | pub(crate) unsafe fn blocking_write(first_address: u32, buf: &[u8]) -> Result<(), Error> { | 20 | pub(crate) unsafe fn begin_write() { |
| 21 | assert_eq!(0, WRITE_SIZE % 4); | ||
| 22 | |||
| 25 | pac::FLASH.cr().write(|w| { | 23 | pac::FLASH.cr().write(|w| { |
| 26 | w.set_pg(true); | 24 | w.set_pg(true); |
| 27 | w.set_psize(pac::flash::vals::Psize::PSIZE32); | 25 | w.set_psize(pac::flash::vals::Psize::PSIZE32); |
| 28 | }); | 26 | }); |
| 27 | } | ||
| 29 | 28 | ||
| 30 | let ret = { | 29 | pub(crate) unsafe fn end_write() { |
| 31 | let mut ret: Result<(), Error> = Ok(()); | 30 | pac::FLASH.cr().write(|w| w.set_pg(false)); |
| 32 | let mut address = first_address; | 31 | } |
| 33 | for chunk in buf.chunks(MAX_WRITE_SIZE) { | ||
| 34 | let vals = chunk.chunks_exact(size_of::<u32>()); | ||
| 35 | assert!(vals.remainder().is_empty()); | ||
| 36 | for val in vals { | ||
| 37 | write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); | ||
| 38 | address += val.len() as u32; | ||
| 39 | |||
| 40 | // prevents parallelism errors | ||
| 41 | fence(Ordering::SeqCst); | ||
| 42 | } | ||
| 43 | 32 | ||
| 44 | ret = blocking_wait_ready(); | 33 | pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { |
| 45 | if ret.is_err() { | 34 | let mut address = start_address; |
| 46 | break; | 35 | for val in buf.chunks(4) { |
| 47 | } | 36 | write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); |
| 48 | } | 37 | address += val.len() as u32; |
| 49 | ret | ||
| 50 | }; | ||
| 51 | 38 | ||
| 52 | pac::FLASH.cr().write(|w| w.set_pg(false)); | 39 | // prevents parallelism errors |
| 40 | fence(Ordering::SeqCst); | ||
| 41 | } | ||
| 53 | 42 | ||
| 54 | ret | 43 | blocking_wait_ready() |
| 55 | } | 44 | } |
| 56 | 45 | ||
| 57 | pub(crate) unsafe fn blocking_erase(from_address: u32, to_address: u32) -> Result<(), Error> { | 46 | pub(crate) fn is_eraseable_range(start_address: u32, end_address: u32) -> bool { |
| 58 | let start_sector = get_sector(from_address); | 47 | let mut address = start_address; |
| 59 | let end_sector = get_sector(to_address); | 48 | while address < end_address { |
| 60 | for sector in start_sector.index..end_sector.index { | 49 | let sector = get_sector(address); |
| 61 | let ret = erase_sector(sector as u8); | 50 | if sector.start != address { |
| 62 | if ret.is_err() { | 51 | return false; |
| 63 | return ret; | ||
| 64 | } | 52 | } |
| 53 | address += sector.size; | ||
| 65 | } | 54 | } |
| 55 | address == end_address | ||
| 56 | } | ||
| 66 | 57 | ||
| 58 | pub(crate) unsafe fn blocking_erase(start_address: u32, end_address: u32) -> Result<(), Error> { | ||
| 59 | let mut address = start_address; | ||
| 60 | while address < end_address { | ||
| 61 | let sector = get_sector(address); | ||
| 62 | erase_sector(sector.index)?; | ||
| 63 | address += sector.size; | ||
| 64 | } | ||
| 67 | Ok(()) | 65 | Ok(()) |
| 68 | } | 66 | } |
| 69 | 67 | ||
| @@ -106,7 +104,7 @@ pub(crate) unsafe fn clear_all_err() { | |||
| 106 | }); | 104 | }); |
| 107 | } | 105 | } |
| 108 | 106 | ||
| 109 | pub(crate) unsafe fn blocking_wait_ready() -> Result<(), Error> { | 107 | unsafe fn blocking_wait_ready() -> Result<(), Error> { |
| 110 | loop { | 108 | loop { |
| 111 | let sr = pac::FLASH.sr().read(); | 109 | let sr = pac::FLASH.sr().read(); |
| 112 | 110 | ||
