-
Notifications
You must be signed in to change notification settings - Fork 24
Introduce flash traits, client and service #236
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
Draft
cfrantz
wants to merge
12
commits into
OpenPRoT:main
Choose a base branch
from
cfrantz:flash_impl
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
d351df1
util: precise errors infrastructure
cfrantz eccb165
util: power-of-2, blocking types
cfrantz 51148a1
util: integrate hexdump into console
cfrantz 725c7ff
util_ipc: ipc wrapper
cfrantz cde3b7d
hal: add a hal for accessing flash memories
cfrantz 77ff9db
services: flash client/server
cfrantz bc6bec9
earlgrey: utililty functions
cfrantz 6589d07
earlgrey: Add earlgrey-specific flash address constructors
cfrantz ddffcce
earlgrey: eflash driver
cfrantz fbec6bf
earlgrey: eflash test
cfrantz a4f0fbd
flash: user documentation
cfrantz e862bdd
Make the trait error types an associated type
cfrantz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # Licensed under the Apache-2.0 license | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") | ||
|
|
||
| rust_library( | ||
| name = "driver", | ||
| srcs = [ | ||
| "driver.rs", | ||
| ], | ||
| crate_name = "hal_flash_driver", | ||
| edition = "2024", | ||
| visibility = ["//visibility:public"], | ||
| deps = [ | ||
| "//util/types", | ||
| "@rust_crates//:zerocopy", | ||
| ], | ||
| ) | ||
|
|
||
| rust_library( | ||
| name = "flash", | ||
| srcs = [ | ||
| "flash.rs", | ||
| ], | ||
| crate_name = "hal_flash", | ||
| edition = "2024", | ||
| visibility = ["//visibility:public"], | ||
| deps = [ | ||
| ":driver", | ||
| "//util/io", | ||
| "//util/types", | ||
| ], | ||
| ) | ||
|
|
||
| rust_test( | ||
| name = "flash_test", | ||
| crate = ":flash", | ||
| rustc_flags = [ | ||
| "-C", | ||
| "debug-assertions", | ||
| ], | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| //! Low-level flash driver interface. | ||
|
|
||
| #![no_std] | ||
|
|
||
| use core::num::NonZero; | ||
|
|
||
| use util_types::PowerOf2Usize; | ||
| use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; | ||
|
|
||
| /// Low-level flash driver interface. | ||
| /// | ||
| /// This trait defines the interface for interacting with flash hardware at a low level. | ||
| /// It supports asynchronous-style operations (start/is_busy/complete) but can also be | ||
| /// implemented for synchronous drivers. | ||
| pub trait FlashDriver { | ||
| type Error; | ||
| /// A bitmap of supported erase block sizes. | ||
| /// | ||
| /// Each bit i represents a supported erase block size of 2^i bytes. | ||
| const ERASABLE_SIZES_BITMAP: u32; | ||
| /// The maximum size of a single program operation. | ||
| const PROGRAM_WINDOW_SIZE: usize; | ||
| /// The maximum size of a single read operation. | ||
| const MAX_READ_SIZE: usize; | ||
| /// The alignment required for read operations. | ||
| const READ_ALIGNMENT: usize; | ||
| /// The alignment required for program operations. | ||
| const PROGRAM_ALIGNMENT: usize; | ||
|
|
||
| /// Returns the total size of the flash in bytes. | ||
| fn size(&self) -> NonZero<usize>; | ||
|
|
||
| /// Reads data from flash. | ||
| /// | ||
| /// # Arguments | ||
| /// * `start_addr`: The address to start reading from. | ||
| /// * `buf`: The buffer to read data into. | ||
| fn read(&mut self, start_addr: FlashAddress, buf: &mut [u8]) -> Result<(), Self::Error>; | ||
|
|
||
| /// Starts an erase operation. | ||
| /// | ||
| /// # Arguments | ||
| /// * `start_addr`: The start address of the block to erase. | ||
| /// * `size`: The size of the block to erase. | ||
| fn start_erase( | ||
| &mut self, | ||
| start_addr: FlashAddress, | ||
| size: PowerOf2Usize, | ||
| ) -> Result<(), Self::Error>; | ||
|
|
||
| /// Starts a program operation. | ||
| /// | ||
| /// # Arguments | ||
| /// * `start_address`: The address to start programming at. | ||
| /// * `data`: The data to program. | ||
| fn start_program( | ||
| &mut self, | ||
| start_address: FlashAddress, | ||
| data: &[u8], | ||
| ) -> Result<(), Self::Error>; | ||
|
|
||
| /// Returns whether the driver is currently busy with an operation. | ||
| fn is_busy(&mut self) -> bool; | ||
|
|
||
| /// Completes a pending operation and returns the result. | ||
| fn complete_op(&mut self) -> Result<(), Self::Error>; | ||
| } | ||
|
|
||
| /// Represents an address in flash memory. | ||
| /// | ||
| /// A flash address consists of a device identifier and an offset within that | ||
| /// device's address space. | ||
| #[derive(Default, Clone, Copy, PartialEq, Eq, IntoBytes, Immutable, FromBytes, KnownLayout)] | ||
| #[repr(C)] | ||
| pub struct FlashAddress { | ||
| device_id: u32, | ||
| offset: u32, | ||
| } | ||
|
|
||
| impl core::fmt::Display for FlashAddress { | ||
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
| write!(f, "{}:0x{:08x}", self.device_id, self.offset) | ||
| } | ||
| } | ||
|
|
||
| impl core::fmt::Debug for FlashAddress { | ||
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
| core::fmt::Display::fmt(self, f) | ||
| } | ||
| } | ||
|
|
||
| impl FlashAddress { | ||
| /// Creates a new `FlashAddress`. | ||
| pub const fn new(device_id: u32, offset: u32) -> Self { | ||
| Self { device_id, offset } | ||
| } | ||
|
|
||
| /// Returns the device identifier. | ||
| pub fn device_id(&self) -> u32 { | ||
| self.device_id | ||
| } | ||
|
|
||
| /// Returns the offset within the device's address space. | ||
| pub fn offset(&self) -> u32 { | ||
| self.offset | ||
| } | ||
| } | ||
|
|
||
| impl core::ops::Add<usize> for FlashAddress { | ||
| type Output = Self; | ||
| fn add(self, other: usize) -> Self { | ||
| Self { | ||
| device_id: self.device_id, | ||
| offset: self.offset + other as u32, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl core::ops::AddAssign<usize> for FlashAddress { | ||
| fn add_assign(&mut self, other: usize) { | ||
| self.offset += other as u32; | ||
| } | ||
| } | ||
|
|
||
| impl core::ops::BitAnd<usize> for FlashAddress { | ||
| type Output = Self; | ||
| fn bitand(self, other: usize) -> Self { | ||
| Self { | ||
| device_id: self.device_id, | ||
| offset: self.offset & other as u32, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl core::ops::BitAndAssign<usize> for FlashAddress { | ||
| fn bitand_assign(&mut self, other: usize) { | ||
| self.offset &= other as u32; | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The routing key concept should leverage the PW capability model
The flash service protocol carries a `device_id field in every address, implying
multi-device support.
It follows that routing key is client-supplied — it lives inside the message payload.
A client can set
device_idto any value. Nothing in the current design prevents a taskthat should only access one flash device from addressing another. Enforcement would have to be a software check inside the server, applied after the message is already received.
Nothing stops one task from accessing another task's flash device. The kernel's capability model is bypassed at the device-selection boundary.
Device-level access control is delegated to software rather than enforced by the kernel.