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

Provides common Nvmc functionality #337

Merged
merged 2 commits into from
Jul 20, 2021
Merged

Provides common Nvmc functionality #337

merged 2 commits into from
Jul 20, 2021

Conversation

huntc
Copy link
Contributor

@huntc huntc commented Jul 13, 2021

The embedded-storage traits are implemented to provide a higher-level abstraction for reading and writing from/to flash storage. In the first instance, support is provided for the nRF52 boards and the nRF9160, but other boards should be relatively easy to support if required in the future.

Sample usage of writing to flash given some 32 bit aligned slice of bytes:

// Erase a page
let _ = nvmc.try_erase(0, 4096);

// Write the 32 bit aligned slice
let _ = nvmc.try_write(0, some_u8_slice_on_32_bit_bounds);

An example of establishing the Nvmc on the nRF9160:

let mut nvmc = Nvmc::new(board.NVMC_NS, unsafe { &mut CONFIG });

...where CONFIG points to flash:

extern "C" {
    #[link_name = "_config"]
    static mut CONFIG: [u32; 1024];
}

...which can be expressed in a memory layout:

MEMORY
{
  /* NOTE 1 K = 1 KiBi = 1024 bytes */
  FLASH : ORIGIN = 0x00040000, LENGTH = 764K
  CONFIG : ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 4K /* 4K is the flash page size */
  RAM : ORIGIN = 0x20020000, LENGTH = 128K
}

_config = ORIGIN(CONFIG);

Testing on the nRF52840 device can be achieved via cargo test --test nvmc from within the nrf52840-hal-tests folder.

Fixes #336

TODO:

  • Implement the ReadNorFlash methods
  • Implement the NorFlash methods
  • Provide an Instance for the nRF52840
  • Provide an Instance for the nRF9160
  • Provide a nvmc module in nrf52840-tests for the new abstraction
  • Write some more tests to test some boundary conditions
  • Go through the code finely and compare it again with the nrfx library
  • Provide an example of reading, writing and erasing from/to storage

@huntc
Copy link
Contributor Author

huntc commented Jul 13, 2021

titanclass/thingy91-lorawan-nbiot@4a9f673 shows the positive impact of this abstraction.

nrf-hal-common/src/nvmc.rs Outdated Show resolved Hide resolved
/// Interface to an NVMC instance.
pub struct Nvmc<'a, T: Instance, const N: usize> {
nvmc: T,
storage: &'a mut [u32; N],
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure how you're planning on using this, but if you plan on offering non-blocking APIs we need to make sure this is mem::forget-safe (presumably by making it 'static)

Also some rationale on why this is const-generic instead of a dynamic slice would be nice, and why this is using u32 instead of u8 as the element type – does the NVMC have alignment requirements?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, writes must be aligned to u32. I agree on the const generics though, a dynamic slice seems simpler.

Also, I'm not sure if there's UB issues with having a &mut to the data while you modify it / erase it through magic register writes...?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure how you're planning on using this, but if you plan on offering non-blocking APIs we need to make sure this is mem::forget-safe (presumably by making it 'static)

Commit 70aad94 makes its 'static.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also some rationale on why this is const-generic instead of a dynamic slice would be nice.

Commit 70aad94 changes this to a dynamic slice. Dunno what I was thinking. :-)

Copy link
Contributor Author

@huntc huntc Jul 14, 2021

Choose a reason for hiding this comment

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

Also, I'm not sure if there's UB issues with having a &mut to the data while you modify it / erase it through magic register writes...?

I may not fully understand the question. However, the data isn't actually modified via registers... the NVMC is put into various modes and then regular memory operations ensue.

}

pub trait Instance {
fn enable_erase();
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if these methods are needed. I'd just do the #[cfg]s in the logic above, which imo is much simpler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Commit c71362c attends to this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Commit 7958ca2 reverts back to the trait methods because there is no common type representing the NVMC configuration. For the 52840, we have the CONFIG type which is a register of a _CONFIG struct. For the 9160 it is CONFIGNS and _CONFIGNS respectively.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, commit e0e4482 figures it out. Deref FTW.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Commit 90b8818 also adds 52840 considerations.

@huntc
Copy link
Contributor Author

huntc commented Jul 16, 2021

@jonas-schievink @Dirbaio We now have tests for the NVMC via nRF52840-hal-tests, and things appear to be working! I want to go through things finely before converting from a draft PR, and write an example. I also want to do some boundary checks via my tests. Your feedback is appreciated!

The embedded-storage traits are implemented to provide a higher level abstraction for reading and writing from/to flash storage. In the first instance, support is provided for the nRF52 series and  the nRF9160, but other boards should be relatively easy to support.
@huntc huntc marked this pull request as ready for review July 17, 2021 02:30
@huntc
Copy link
Contributor Author

huntc commented Jul 17, 2021

This PR is complete and ready for a thorough review.

@jonas-schievink
Copy link
Contributor

bors r+

@bors
Copy link
Contributor

bors bot commented Jul 20, 2021

Build succeeded:

@bors bors bot merged commit 7a0be8a into nrf-rs:master Jul 20, 2021
@huntc huntc deleted the nvmc branch July 21, 2021 00:31
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.

A common HAL NVMC abstraction - needed?
3 participants