Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement FLC #6

Merged
merged 6 commits into from
Jan 29, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: remove flashprog linkage by default
WhiteHoodHacker committed Jan 29, 2025
commit 8302dca7ee3118330571a1c817213f26670fa46b
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -26,5 +26,7 @@ rand_core = { version = "0.6.4", default-features = false, optional = true }

[features]
default = ["rand", "rt"]
# Enabling this adds the `.flashprog` section header to critical flash programming functions for custom linkage
flashprog-linkage = []
rand = ["dep:rand", "dep:rand_core"]
rt = ["max78000-pac/critical-section", "max78000-pac/rt"]
47 changes: 8 additions & 39 deletions src/flc.rs
Original file line number Diff line number Diff line change
@@ -52,37 +52,6 @@ pub enum FlashError {
/// let new_data: u32 = flc.read_32(0x1006_0004).unwrap();
/// assert_eq!(new_data, 0x7856_3412);
/// ```
///
/// ## Flash Programming Linkage
/// Executing from flash memory while writing to flash memory can result
/// in a crash or undefined behavior. All critical flash programming functions
/// are marked with the `.flashprog` section and are set to never be inlined.
/// This allows the user to place these functions either in a "safe" flash page
/// or in executable RAM. The user can modify their `memory.x` file (or
/// `link.x`, or a custom linker script) to specify where the `.flashprog`
/// section is placed. This is recommended if you are experiencing crashes
/// while writing to flash memory.
///
/// The below example will collect all `.flashprog` functions into a new
/// section, which will be placed in flash memory (`AT>FLASH`) after the `.data`
/// section (`INSERT AFTER .data;`), then loaded into RAM and executed from RAM
/// at runtime (`> RAM`).
///
/// ```
/// /* linker script */
/// SECTIONS {
/// .flash_code :
/// {
/// . = ALIGN(4);
/// *(.flashprog*)
/// . = ALIGN(4);
/// } > RAM AT>FLASH
/// }
/// INSERT AFTER .data;
/// ```
///
/// Note that you likely do not need to do this if you are not experiencing
/// crashes while writing to flash memory.
pub struct Flc {
flc: crate::pac::Flc,
sys_clk: Clock<SystemClock>,
@@ -159,27 +128,27 @@ impl Flc {
}

/// Commit a write operation.
#[link_section = ".flashprog"]
#[cfg_attr(feature = "flashprog-linkage", link_section = ".flashprog")]
#[inline]
fn commit_write(&self) {
self.flc.ctrl().modify(|_, w| w.wr().set_bit());
while self.flc.ctrl().read().wr().bit_is_set() {}
self.flc.ctrl().modify(|_, w| w.wr().start());
while !self.flc.ctrl().read().wr().is_complete() {}
while self.is_busy() {}
}

/// Commit a page erase operation.
#[link_section = ".flashprog"]
#[cfg_attr(feature = "flashprog-linkage", link_section = ".flashprog")]
#[inline]
fn commit_erase(&self) {
self.flc.ctrl().modify(|_, w| w.pge().set_bit());
while self.flc.ctrl().read().pge().bit_is_set() {}
self.flc.ctrl().modify(|_, w| w.pge().start());
while !self.flc.ctrl().read().pge().is_complete() {}
while self.is_busy() {}
}

/// Write a 128-bit word to flash memory. This is an internal function to
/// be used by all other write functions.
#[doc(hidden)]
#[link_section = ".flashprog"]
#[cfg_attr(feature = "flashprog-linkage", link_section = ".flashprog")]
#[inline(never)]
fn _write_128(&self, address: u32, data: &[u32; 4]) -> Result<(), FlashError> {
// Target address must be 128-bit aligned
@@ -219,7 +188,7 @@ impl Flc {

/// Erases a page in flash memory.
#[doc(hidden)]
#[link_section = ".flashprog"]
#[cfg_attr(feature = "flashprog-linkage", link_section = ".flashprog")]
#[inline(never)]
fn _erase_page(&self, address: u32) -> Result<(), FlashError> {
while self.is_busy() {}