Skip to content

Storage Traits for on and off board storage #241

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

Closed
wants to merge 14 commits into from

Conversation

tl8roy
Copy link

@tl8roy tl8roy commented Aug 1, 2020

Closes #28
These are a set of traits that can be used for on and off board storage.

Each function is split into its own trait to deal with the different types of memory (Particularly Read Only vs Read/Write)

MCU Flash impl:
https://github.com/tl8roy/alt-stm32f30x-hal/blob/master/src/storage.rs

I2C EEPROM impl:
https://github.com/tl8roy/eeprom24x-rs/blob/master/src/eeprom24x.rs

SPI PSRAM implementation:
https://github.com/tl8roy/esp_psram
This is a completely new implementation using SPI.

Feedback has come from #28, diondokter/device-driver#1 and twitter https://twitter.com/tl8roy/status/1287254634512310272

@rust-highfive
Copy link

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @eldruin (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added S-waiting-on-review Review is incomplete T-hal labels Aug 1, 2020
@ryankurte
Copy link
Contributor

hey thanks for the PR, this looks like a super useful abstraction! (and i needed it this week 😂)

i am not completely sure whether this is the right level to include in the embedded-hal or not, though it would be great to have a standard flash API for HAL implementations which is a serious point in favour. as it is a reasonably complex abstraction i suspect that there remains some room for experimentation (and some changes may occur during this), so i think my preference at this time would be to create a flash-hal crate to build out and evaluate this api prior to either adopting it into the WG or merging it into embedded-hal.

@rust-embedded/hal how do y'all feel like this, and is it worth a discussion at the next meeting about formalising the experimental-crate approach a bit more?

a few miscellaneous thoughts:

  • is there an advantage to an API for page / flash sizes rather than associated constants? i guess flash size might be runtime detected but page size is probably not?
  • how would you implement multiple erase methods (often devices support chip, page, half-page, and sector erase)?
  • is it important to communicate the erase state? in the comments you mention setting the memory to 0, however, this depends on the underlying technology and may impact the api consumer
  • is it expected that the flash-hal will fail when writing across some boundaries and thus this must be handled by the application, or that the driver will manage this? it is worth noting that this may not be a page boundary (many chips i have used can only write 255 bytes at a time as well as the standard page boundary limit). it seems to me the latter would be a neater abstraction for consumers?
  • is it worth having a mechanism for locking/unlocking memory as is required for writing to most internal flash or is that outside the scope of this abstraction? (and is it important to signal that writing to internal flash is going to stop the processor doing anything or is that a hal implementation concern).

@tl8roy
Copy link
Author

tl8roy commented Aug 1, 2020

hey thanks for the PR, this looks like a super useful abstraction! (and i needed it this week 😂)

i am not completely sure whether this is the right level to include in the embedded-hal or not, though it would be great to have a standard flash API for HAL implementations which is a serious point in favour. as it is a reasonably complex abstraction i suspect that there remains some room for experimentation (and some changes may occur during this), so i think my preference at this time would be to create a flash-hal crate to build out and evaluate this api prior to either adopting it into the WG or merging it into embedded-hal.

While the inspiration is that issue, the goal is absolutely a generic storage traits that aren't flash specific.

Copy link
Member

@eldruin eldruin left a comment

Choose a reason for hiding this comment

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

Thank you for this PR.
I agree with @ryankurte. I would really like this merged but I also think it still needs a couple iterations. Whether that needs to be done in a separate crate I do not really care.
More thoughts:

  1. Non-blocking
    All methods offer a non-blocking interface. While that makes sense since storage devices take a while to complete, both implementations presented above are actually blocking.
    It would be interesting to see how real non-blocking implementations look like.
  2. Paging
    The eeprom24x implementation just writes one byte at a time. It would be interesting to see how a more advanced implementation would look like, where actual arrays are written and how to deal with page boundaries, specially in the face of a non-blocking operation.
  3. Storage size
    I am also wondering if stateful fallible methods are necessary here or if this can be determined at compile time and associated constants would do just as well.
    Anyway example implementations are necessary here.
  4. Example implementation for eeprom24x
    This is simple: I think it would be better to implement the storage traits in a separate file. I think this would be easier for other people to understand what the addition is without having to look at the diff.

src/storage.rs Outdated
/// Allows for Read Only Memory as well as Read and Write Memory
use nb;

/// Address represents an unsigned int. This allows for devices that have bigger or smaller address spaces than the host.
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: I would rather refer to an "unsigned integer" (also below)

src/storage.rs Outdated
type Error;

/// Erase the page of memory
/// For flash devices, this sets the whole page to 0xFF
Copy link
Member

Choose a reason for hiding this comment

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

I also think the reset value is probably better left to implementations. Anything written in the documentation of the trait would be part of a contract. (also below)

src/storage.rs Outdated
type Error;

/// Returns the start address and the maximum size that can be stored by the device
fn try_total_size(&mut self) -> nb::Result<(Address<U>, AddressOffset<U>), Self::Error>;
Copy link
Member

Choose a reason for hiding this comment

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

I think two different methods may be better, since it would be fairly easy to make a mistake.

use core::ops::Add;

/// Implement add for the Address and AddressOffset Types.
impl<'a, 'b, U> Add<&'b AddressOffset<U>> for &'a Address<U>
Copy link
Member

Choose a reason for hiding this comment

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

Subtraction of an offset from an address is probably also interesting. And if we already at it, maybe addition and subtraction of address offsets. However I start wondering where to stop :) and then if it makes sense to include these implementations at all since the user already needs to deal with the inner values.

src/storage.rs Outdated
}

/// Page represents an unsigned int that is a Page ID in the device memory space.
pub struct Page<U>(U);
Copy link
Member

Choose a reason for hiding this comment

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

I am wondering about a conversion from Page to Address but I guess the best way would be adding a From implementation and that is something that needs to be done in the implementation and not nicely enforcible here.

@tl8roy
Copy link
Author

tl8roy commented Aug 5, 2020

I think the SPI flash chip library is non blocking. I'll have a crack at that.

@tl8roy
Copy link
Author

tl8roy commented Aug 22, 2020

What I have done so far:

  • Moved the EEPROM into its own file
  • Implemented a SPI SRAM IC driver as an example

What I am planning to do next:

  • Improve the quality of the STM32 flash example
  • Attempt to make it async as there appear to be no async SPI or I2C drivers
  • Failing that, revert the traits back to blocking only
  • Create an example of using all 3 crates, probably as a mini OTA example

@MathiasKoch
Copy link

I think it would make sense to make Address, AddressOffset and Page implement/derive a bunch of basic traits.
Of the top of my head it would make sense with something like Clone, Copy, Debug, PartialEq, PartialOrd?

Also i think it makes sense to be able to sub two addresses? very common way of getting a length?
and an Address % AddressOffset might also give value? I know the last couple here are easy to do myself, as the inner is public, but still applicable i think.

@Sympatron
Copy link

What do you think about starting with a new crate to get this going? I think something like embedded-storage would be fitting. That way people could start using it immediately.

After some time it could still be merging into embedded-hal.

@MathiasKoch
Copy link

@Sympatron I think that is the right approach! Currently i am forcing all of my crates into separate branches just to use a storage branch here, and it doesn't quite make sense.

Maybe it would make sense to get @eldruin to create it in embedded-rust-community? I think that would be a great fit!

@tl8roy
Copy link
Author

tl8roy commented Nov 13, 2020

I'm happy to support which ever solution works best for the community. I do have a bit of time this weekend.

@eldruin
Copy link
Member

eldruin commented Nov 13, 2020

embedded-storage sounds good to me. As previously discussed, it is probable that this takes a while to get ready for embedded-hal. It should be noted as well that there are two proposals for storage traits: this one and also #248.
Maybe both can live within embedded-storage until it is settled which one is best or so.
Adding it to the rust-embedded-community might be possible. I am preparing an overhaul of the org's mission.

@MathiasKoch
Copy link

@tl8roy @eldruin

I have created this: https://github.com/BlackbirdHQ/embedded-storage in an attempt to bring this forward, knowingly that it does not address all our issues, but at least it is a starting point for discussions.. It is currently a 1:1 copy of #248

I would love to see it become part of the embedded-rust-community, but had to start it somewhere else..? @eldruin If you would be okay with it, i can transfer it?

@eldruin
Copy link
Member

eldruin commented Dec 10, 2020

@MathiasKoch sure thing. It would be great if this triggers a development impulse like with embedded-nal. If you run into problems transferring it, let me know.

@MathiasKoch
Copy link

Awesome!

Let me introduce: https://github.com/rust-embedded-community/embedded-storage

@eldruin can you close #28 with a reference to the new repo?
Then i will close #248, leaving only this PR that @tl8roy could maybe move to embedded-storage for further discussion?

@tl8roy
Copy link
Author

tl8roy commented Dec 11, 2020

Now moved to rust-embedded-community/embedded-storage#8 so closing off for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Review is incomplete T-hal
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Thoughts on Flash API?
6 participants