Skip to content

Conversation

@pdobbins23
Copy link
Contributor

@pdobbins23 pdobbins23 commented Feb 23, 2025

Main Changes:

  • Added a new write_guard function which takes a closure to guarantee proper FLC pre/post write operations
  • Fix some code duplication to help reduce bugs (busy wait loop, clear interrupts)
  • Update tests to include both semihosting and UART

@pdobbins23 pdobbins23 changed the title Add write guard, fix some code duplication FLC Rework Feb 23, 2025
@MelonShooter MelonShooter self-requested a review February 23, 2025 09:35
Copy link
Contributor

@MelonShooter MelonShooter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved - I would like to see those test outputs on UART and semihosting, and potential verification that this doesn't mess with other pieces of flash memory

Copy link
Contributor

@suaviloquence suaviloquence left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, did we audit the actual logic in the big write and read functions that splits it into atomic read/write128s?

/// - Lock write protection
/// - Flush ICC
/// - Enable icc0
fn write_guard<F: Fn()>(&self, sys_clk: &SystemClock, operation: F) -> Result<(), FlashErr> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn write_guard<F: Fn()>(&self, sys_clk: &SystemClock, operation: F) -> Result<(), FlashErr> {
fn write_guard<F: FnOnce()>(&self, sys_clk: &SystemClock, operation: F) -> Result<(), FlashErr> {

/// [`flash_write_full_partially_outbound_end`].
pub fn run_flc_tests(
stdout: &mut hio::HostStream,
pub fn run_flc_tests<T: Write>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to add a test that does two writes in a row, irrespective of output, to prevent this issue from showing up again.

/// Behavior is undefined if any of the following conditions are violated:
/// * `address` must be in a valid flash page
pub unsafe fn page_erase(&self, address: u32, sys_clk: &SystemClock) -> Result<(), FlashErr> {
self.check_address_bounds(address..address)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this have size 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well the address is the address of the page, check_address_bounds does a contains check on the given range. Essentially this is just checking that address is within the bounds of flash.

Unless I am mistaken about what range syntax is doing here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn check_address_bounds(&self, address_range: core::ops::Range<u32>) -> Result<(), FlashErr> {
if (FLASH_MEM_BASE..(FLASH_MEM_BASE + FLASH_MEM_SIZE)).contains(&address_range.start)
&& (FLASH_MEM_BASE..(FLASH_MEM_BASE + FLASH_MEM_SIZE)).contains(&address_range.end)

You're totally right here - we are just treating a range x..y as a tuple (x, y)

(although i think the checking code is subtly wrong - it's treating the range as inclusive when it should be a <= x < b) 😭

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically this is a false positive where end = FLASH_START + FLASH_SIZE

@suaviloquence
Copy link
Contributor

contained in #83

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants