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

Relax the MultiwriteNorFlash to only need clearing of words #63

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

korken89
Copy link
Contributor

@korken89 korken89 commented Aug 4, 2024

This relaxes the requirement on the ItemHeader so flashes that do not allow for MultiwriteNorFlash can be used.
A new bound in introduced which encodes that only clearing of words are required.

This change is a breaking change for flashes that have word sizes > 4 bytes.
For words sizes of 4 or smaller the old behavior is kept.

The new trait resides in the crate for now, but should be up-streamed to embedded-storage.
Up-streaming PR: rust-embedded-community/embedded-storage#57

};

#[derive(Debug, Clone)]
pub struct ItemHeader {
pub struct ItemHeader<S> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not in love with the S here, but it's a good way to achieve the goal. So it can stay

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I agree, basically all methods had the <S> before so it was a "not better not worse" change. :)

Comment on lines +47 to +51
const DATA_CRC_LENGTH: usize = if <S as NorFlashExt>::WORD_SIZE < 4 {
4 // The minimum is 4 to hold the CRC32.
} else {
<S as NorFlashExt>::WORD_SIZE
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah I can see this work!

However, this punishes people with true multiwrite flashes with >4 wordsize.
I wonder if we can find a way to do the selection based on the implemented trait.
Any ideas?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Directly I'm having issues comping up with a way.

As the supertrait chain is: NorFlash -> WordclearNorFlash -> MultiwriteNorFlash
I'm getting ambiguity errors when trying to add another DataCrcSize trait that is implemented on different T.
More or less:

trait DataCrcSize {
    const SIZE: usize;
}

impl<T> DataCrcSize for T where T: MultiwriteNorFlash {
    const SIZE: usize = 4;
}

impl<T> DataCrcSize for T where T: WordclearNorFlash {
    const SIZE: usize = if <S as NorFlashExt>::WORD_SIZE < 4 {
        4 // The minimum is 4 to hold the CRC32.
    } else {
        <S as NorFlashExt>::WORD_SIZE
    };
}

Do you know of any other approach?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, that doesn't work yeah.

Like I said in your embedded-storage PR, if MultiwriteNorFlash had a const instead of having an extra trait, this could be made to work.

Except, probably not! Because the ItemHeader is generic over NorFlash, so it still wouldn't have access to that info...
Hmmmm annoying.

Maybe using extension traits to encode this info is the wrong way to do it?
Maybe NorFlash should provide that info directly?
But const generics probably aren't implemented far enough to then have a function with bounds for Multiwrite.

pub trait NorFlash: ReadNorFlash {
	const WRITE_SIZE: usize;
	const ERASE_SIZE: usize;

        const CLEAR_WORDS: bool;
        const MULTI_WRITE_WORDS: bool;

	fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error>;
	fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error>;
}

???

This sucks as well...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Your point in my PR to embedded-storage makes sense though. If the trait had a bool the check can be made.

I'll update to that and give it a try!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah right, that's not very nice either. As then the entire header needs to be bound to MultiwriteNorFlash, which puts unnecessary bounds on reading.

Is this OK in your opinion?

Copy link
Collaborator

Choose a reason for hiding this comment

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

No, I really want to support non-multiwrite as well

@korken89
Copy link
Contributor Author

korken89 commented Aug 4, 2024

On another note, the failing test is also on master. Not sure what is wrong TBH.

@diondokter
Copy link
Collaborator

On another note, the failing test is also on master. Not sure what is wrong TBH.

Oh! Thanks for noticing. I'll look at it

@diondokter
Copy link
Collaborator

diondokter commented Aug 4, 2024

On another note, the failing test is also on master. Not sure what is wrong TBH.

Oh! Thanks for noticing. I'll look at it

You sure? Just reran it: https://github.com/tweedegolf/sequential-storage/actions/runs/10097189388/job/28315754842
Seems to work and the test error seems specific to this branch...

@diondokter
Copy link
Collaborator

Ah I see what's happening in the error. There is some fun being had with the mock flash so it can be used in doc tests, but not have it available in the normal API... Let's ignore for now until we have something we can actually merge

@korken89
Copy link
Contributor Author

korken89 commented Aug 4, 2024

Ah there were 2 failures 😅 there is one actual test that is failing and one that is related to doc-comments.
But as you say we can fix that in the end :)

@kaspar030
Copy link

This would enable use of sequential-storage on the esp-hal flash, right?

@diondokter
Copy link
Collaborator

This would enable use of sequential-storage on the esp-hal flash, right?

Hey! I'd love for RIOT-rs to use this.

So this PR is kinda stuck. I'd like to have the ability, but with this implementation it comes at great cost for people on big STM32 chips. An item header is 8 bytes, padded to the next flash word boundary. On big STM32 chips the word size is 32 bytes, so that's already a giant waste of space.

With this PR the item header will always cover two words to make it work. That'd mean a 64 byte header! And only 12.5% of it would be used.

I can't really accept that. But also I can't fix that with the existing set of traits.
Two months ago I proposed a new one: rust-embedded-community/embedded-storage#58 (comment)
But people didn't seem to like it, although I think it'd unlock a bunch of usecases.

So what really needs to happen is:

  1. I should make my own crate with that trait (or do it within s-s)
  2. Create adapters for my trait on top of the embedded-storage traits
  3. Change s-s to use that trait
  4. Make the item header layout depend on the WRITE_MAX_COUNT

This only really works if my trait is actually a good idea. For now it remains unproven.

This is a non-trivial amount of work, but work I do want to do at some point.
For now my open source attention has been going my device-driver crate (though that should be done quite soon).

Are you blocked on this?

@kaspar030
Copy link

Are you blocked on this?

Not blocked on this, already s-s is awesome enough that we'll use even if esp doesn't work yet!

@diondokter
Copy link
Collaborator

Are you blocked on this?

Not blocked on this, already s-s is awesome enough that we'll use even if esp doesn't work yet!

Thanks!

Can't promise anything but we've got a hackday coming up in two weeks. Might spend my time on this.

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.

3 participants