From 576e804447bcf74b291b82721c01306593a14bbb Mon Sep 17 00:00:00 2001 From: jerrysxie Date: Wed, 21 May 2025 15:31:33 -0500 Subject: [PATCH 1/2] Initialize repo as a workspace with storage-bus - Set up as workspace - Add storage-bus as a submodule - Update README --- .gitignore | 4 -- .vscode/settings.json | 1 - Cargo.lock | 7 +++ Cargo.toml | 23 +++---- README.md | 64 +------------------- src/baremetal/mod.rs | 6 -- src/main.rs | 18 ------ storage-bus/Cargo.toml | 10 ++++ storage-bus/README.md | 43 ++++++++++++++ storage-bus/src/lib.rs | 4 ++ storage-bus/src/nand.rs | 7 +++ storage-bus/src/nor.rs | 129 ++++++++++++++++++++++++++++++++++++++++ 12 files changed, 211 insertions(+), 105 deletions(-) create mode 100644 Cargo.lock delete mode 100644 src/baremetal/mod.rs delete mode 100644 src/main.rs create mode 100644 storage-bus/Cargo.toml create mode 100644 storage-bus/README.md create mode 100644 storage-bus/src/lib.rs create mode 100644 storage-bus/src/nand.rs create mode 100644 storage-bus/src/nor.rs diff --git a/.gitignore b/.gitignore index 6985cf1..73fab07 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,6 @@ debug/ target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - # These are backup files generated by rustfmt **/*.rs.bk diff --git a/.vscode/settings.json b/.vscode/settings.json index ace00d4..4d8d96d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,7 +2,6 @@ "editor.formatOnSave": true, "rust-analyzer.checkOnSave": true, "rust-analyzer.check.allTargets": false, - "rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf", "rust-analyzer.cargo.features": "all", "rust-analyzer.check.command": "clippy", "[toml]": { diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7216e66 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "storage_bus" +version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index 71c4806..7448645 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,19 +1,12 @@ -[package] -name = "embedded-rust-template" +[workspace] +resolver = "2" +members = ["storage-bus"] + +[workspace.package] version = "0.1.0" edition = "2021" license = "MIT" -repository = "https://github.com/OpenDevicePartnership/embedded-rust-template" -rust-version = "1.85" - -[dependencies] -# dependencies for all targets - -[target.'cfg(target_os = "none")'.dependencies] -# dependencies for no-std targets +repository = "https://github.com/OpenDevicePartnership/embedded-mcu" -[lints.clippy] -suspicious = "forbid" -correctness = "forbid" -perf = "forbid" -style = "forbid" +[workspace.dependencies] +embedded-services = { git = "https://github.com/OpenDevicePartnership/embedded-services" } diff --git a/README.md b/README.md index 60b09c0..4003b89 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,5 @@ -# embedded-rust-template -Template repository for Embedded Rust development +# embedded-mcu -## Customizing This Template +This houses a colletion of MCU agnostic traits + libraries to manipulate hardware peripherals. It is similar to embedded-hal except mapping to high level of abstraction like USB C PD and HID. Some of the traits housed here will be upstreamed to embedded-hal if the community aligns to the same vision. -### Changing the Target Architecture - -This template is configured for `thumbv8m.main-none-eabihf`, by default, but you can modify it for other targets (i.e. `aarch64-unknown-none`): - -1. **VSCode Settings**: Update the target in `.vscode/settings.json`: - ```json - "rust-analyzer.cargo.target": "your-target-architecture" - ``` - - -This configuration ensures that: -- Only the specified target architecture is analyzed, not the host platform -- Code is checked against the no_std environment - -To temporarily analyze code for the host platform instead, you can remove the `rust-analyzer.cargo.target` setting. - -2. **GitHub Workflows**: Modify the target in two workflow files: - - `.github/workflows/nostd.yml`: Update the targets in the matrix: - ```yaml - matrix: - target: [your-target-architecture] - ``` - - `.github/workflows/check.yml`: If there are any target-specific checks, update them accordingly. - -3. **Cargo Configuration**: If needed, you can add target-specific configuration in a `.cargo/config.toml` file. - -### Converting from Binary to Library - -To convert this project from a binary to a library: - -1. **Cargo.toml**: Update your project structure: - ```toml - [lib] - name = "your_library_name" - ``` - -2. **Directory Structure**: - - For a library, ensure you have a `src/lib.rs` file instead of `src/main.rs` - - Move your code from `main.rs` to `lib.rs` and adjust as needed - -3. **No-std Configuration**: If you're creating a no-std library, ensure you have: - ```rust - // In lib.rs - #![cfg_attr(target_os = "none", no_std)] - // Add other attributes as needed - ``` - -### Project Dependencies - -Update the dependencies in `Cargo.toml` based on your target platform: - -```toml -[dependencies] -# Common dependencies for all targets - -[target.'cfg(target_os = "none")'.dependencies] -# Dependencies for no-std targets -``` +This repo is not intended to link to any MCU specific code. \ No newline at end of file diff --git a/src/baremetal/mod.rs b/src/baremetal/mod.rs deleted file mode 100644 index c03b953..0000000 --- a/src/baremetal/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -use core::panic::PanicInfo; - -#[panic_handler] -fn panic(_info: &PanicInfo) -> ! { - loop {} -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 7111536..0000000 --- a/src/main.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![cfg_attr(target_os = "none", no_std)] -#![cfg_attr(target_os = "none", no_main)] - -#[cfg(target_os = "none")] -mod baremetal; - -#[cfg(not(target_os = "none"))] -fn main() { - println!("Hello, world!"); -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} diff --git a/storage-bus/Cargo.toml b/storage-bus/Cargo.toml new file mode 100644 index 0000000..200e1ad --- /dev/null +++ b/storage-bus/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "storage_bus" +version = "0.1.1" +edition = "2021" +description = "Storage Bus interfaces" +repository = "https://github.com/OpenDevicePartnership/embedded-services" +rust-version = "1.85" +license = "MIT" + +[dependencies] diff --git a/storage-bus/README.md b/storage-bus/README.md new file mode 100644 index 0000000..e89844a --- /dev/null +++ b/storage-bus/README.md @@ -0,0 +1,43 @@ +# Introduction +The goal of this design is to propose a generic Storage Bus Driver interface to all flash Device drivers. Flash device drivers such as Macronix or Winbond driver can access storage devices over different kinds of busses. E.g. communication could be through SPI bus or FlexSPI Bus based on platform design. + +Bus drivers introduce abstraction using generic storage traits and expose them to NOR device drivers such as Macronix or Winbond to communicate with the Hardware without worrying about low level bus protocol details. + +Bus driver + generic storage traits can handle other protocol such as I2C or NVMe without any impact to the device drivers. + +# Static Design + +## Storage Bus Driver design +```mermaid + classDiagram + class Macronix-Device-Driver + class Storage-Bus["Storage Bus trait"] + class Spi-Storage-Bus + class Spi-Hal + class Winbond-Device-Driver + Winbond-Device-Driver <|--|> Storage-Bus + <> Storage-Bus + Macronix-Device-Driver <|--|> Storage-Bus + Storage-Bus <|--|> Spi-Storage-Bus + Spi-Hal <|--|> Spi-Storage-Bus +``` + +## Example +``` +/// SPI Bus driver instance + +pub struct SpiNorStorageBus { + // Structure Fields +} + +impl BlockingNorStorageBusDriver for SpiNorStorageBus { + fn send_command( + &mut self, + cmd: NorStorageCmd, + read_buf: Option<&mut [u8]>, + write_buf: Option<&[u8]>, + ) -> Result<(), impl NorStorageBusError> { + // Handle the storage commands + } +} +``` diff --git a/storage-bus/src/lib.rs b/storage-bus/src/lib.rs new file mode 100644 index 0000000..34e80df --- /dev/null +++ b/storage-bus/src/lib.rs @@ -0,0 +1,4 @@ +#![no_std] + +pub mod nand; +pub mod nor; diff --git a/storage-bus/src/nand.rs b/storage-bus/src/nand.rs new file mode 100644 index 0000000..5debd7e --- /dev/null +++ b/storage-bus/src/nand.rs @@ -0,0 +1,7 @@ +/// Blocking NAND Storage Driver. The trait introduces a method to send command to the bus +/// The NAND device driver should use this trait APIs to send command to the bus +pub trait BlockingNandStorageBusDriver {} + +/// Async NAND Storage Driver. The trait introduces a method to send command to the bus +/// The NAND device driver should use this trait APIs to send command to the bus +pub trait AsyncNandStorageBusDriver {} diff --git a/storage-bus/src/nor.rs b/storage-bus/src/nor.rs new file mode 100644 index 0000000..a035722 --- /dev/null +++ b/storage-bus/src/nor.rs @@ -0,0 +1,129 @@ +#[derive(Debug, Copy, Clone, PartialEq)] +/// Storage Mode +pub enum NorStorageCmdMode { + /// Double Data Rate mode for data transfer + DDR, + /// Single Data Rate mode for data transfer + SDR, +} +#[derive(Debug, Copy, Clone)] +/// Storage Command Type +pub enum NorStorageCmdType { + /// Read transfer type + Read, + /// Write transfer type + Write, +} + +#[derive(Debug, Copy, Clone)] +/// Bus Width +pub enum NorStorageBusWidth { + /// 1 bit bus width + Single, + /// 2 bit bus width + Dual, + /// 4 bit bus width + Quad, + /// 8 bit bus width + Octal, +} + +#[derive(Debug, Copy, Clone)] +/// enum for dummy cycles +pub enum NorStorageDummyCycles { + /// Dummy cycles in terms of clock cycles + Clocks(u8), + /// Dummy cycles in terms of bytes + Bytes(u8), +} + +#[derive(Debug, Copy, Clone)] +/// NOR Storage Command to be passed by NOR based storage device drivers +pub struct NorStorageCmd { + /// Nor Storage Command lower byte + pub cmd_lb: u8, + /// Nor Storage Command upper byte + pub cmd_ub: Option, + /// Address of the command + pub addr: Option, + /// Address width in bytes + pub addr_width: Option, + /// DDR or SDR mode + pub mode: NorStorageCmdMode, + /// Number of Dummy clock cycles. Assuming max 256 dummy cycles beyond which its impractical + pub dummy: NorStorageDummyCycles, + /// Command type - Reading data or writing data + pub cmdtype: Option, + /// Bus Width - This represents width in terms of signals + /// SPI - Single + /// QSPI - Quad + /// OctalSPI - Octal + /// I2C - 1 + pub bus_width: NorStorageBusWidth, + /// Number of data bytes to be transferred for this command + pub data_bytes: Option, +} + +/// Enum with storage errors +pub enum NorStorageBusError { + /// Bus not available could be used for example + /// 1. Bus is not available due to arbitration lost in multi master bus + /// 2. Bus is not powered up + StorageBusNotAvailable, + /// Bus IO error while sending command + /// Could be used for example + /// 1 - Bus read error + /// 2 - Bus write error + StorageBusIoError, + /// Bus internal error + StorageBusInternalError, +} + +/// Blocking NOR Storage Driver. The trait introduces a method to send command to the bus +/// The NOR device driver should use this trait to send command to the bus +/// NOR Storage Bus driver shall implement this trait to support NOR storage access over the bus +/// Bus Examples - +/// - SPI +/// - FlexSPI +/// - Hyperbus +pub trait BlockingNorStorageBusDriver { + /// Send Command to the bus + /// Parameters: + /// cmd - Command to be sent to the bus + /// read_buf - Read buffer to store the data read from the bus + /// write_buf - Write buffer to write the data to the bus + /// Returns: + /// Result<(), NorStorageBusError> - Result of the command sent to the bus + /// NorStorageBusError - Error code if the command failed + fn send_command( + &mut self, + cmd: NorStorageCmd, + read_buf: Option<&mut [u8]>, + write_buf: Option<&[u8]>, + ) -> Result<(), NorStorageBusError>; +} + +#[allow(async_fn_in_trait)] +/// Async NOR Storage Driver. The trait introduces a method to send command to the bus +/// The NOR Storage device driver should use this trait to send command to the bus +/// NOR Storage Bus driver shall implement this trait to support NOR storage access over the bus +/// Bus Examples - +/// - SPI +/// - FlexSPI +/// - Hyperbus +pub trait AsyncNorStorageBusDriver { + /// Send Command to the bus + /// Parameters: + /// cmd - Command to be sent to the bus + /// read_buf - Read buffer to store the data read from the bus + /// write_buf - Write buffer to write the data to the bus + /// Returns: + /// Result<(), NorStorageBusError> - Result of the command sent to the bus + /// NorStorageBusError - Error code if the command failed + async fn send_command( + &mut self, + cmd: NorStorageCmd, + read_buf: Option<&mut [u8]>, + write_buf: Option<&[u8]>, + ) -> Result<(), NorStorageBusError>; +} From b0c754df456e43e895330d691734a24f25538e2f Mon Sep 17 00:00:00 2001 From: jerrysxie Date: Thu, 22 May 2025 11:25:07 -0500 Subject: [PATCH 2/2] Remove storage-bus and add dymmy crate instead --- Cargo.lock | 4 +- Cargo.toml | 2 +- mcu-traits/Cargo.toml | 8 +++ mcu-traits/src/lib.rs | 5 ++ storage-bus/Cargo.toml | 10 ---- storage-bus/README.md | 43 -------------- storage-bus/src/lib.rs | 4 -- storage-bus/src/nand.rs | 7 --- storage-bus/src/nor.rs | 129 ---------------------------------------- 9 files changed, 16 insertions(+), 196 deletions(-) create mode 100644 mcu-traits/Cargo.toml create mode 100644 mcu-traits/src/lib.rs delete mode 100644 storage-bus/Cargo.toml delete mode 100644 storage-bus/README.md delete mode 100644 storage-bus/src/lib.rs delete mode 100644 storage-bus/src/nand.rs delete mode 100644 storage-bus/src/nor.rs diff --git a/Cargo.lock b/Cargo.lock index 7216e66..1780010 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,5 +3,5 @@ version = 4 [[package]] -name = "storage_bus" -version = "0.1.1" +name = "mcu-traits" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 7448645..4ac1f37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["storage-bus"] +members = ["mcu-traits"] [workspace.package] version = "0.1.0" diff --git a/mcu-traits/Cargo.toml b/mcu-traits/Cargo.toml new file mode 100644 index 0000000..12b6cac --- /dev/null +++ b/mcu-traits/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "mcu-traits" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] diff --git a/mcu-traits/src/lib.rs b/mcu-traits/src/lib.rs new file mode 100644 index 0000000..c17229b --- /dev/null +++ b/mcu-traits/src/lib.rs @@ -0,0 +1,5 @@ +#![no_std] + +pub fn add(left: u64, right: u64) -> u64 { + left + right +} diff --git a/storage-bus/Cargo.toml b/storage-bus/Cargo.toml deleted file mode 100644 index 200e1ad..0000000 --- a/storage-bus/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "storage_bus" -version = "0.1.1" -edition = "2021" -description = "Storage Bus interfaces" -repository = "https://github.com/OpenDevicePartnership/embedded-services" -rust-version = "1.85" -license = "MIT" - -[dependencies] diff --git a/storage-bus/README.md b/storage-bus/README.md deleted file mode 100644 index e89844a..0000000 --- a/storage-bus/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Introduction -The goal of this design is to propose a generic Storage Bus Driver interface to all flash Device drivers. Flash device drivers such as Macronix or Winbond driver can access storage devices over different kinds of busses. E.g. communication could be through SPI bus or FlexSPI Bus based on platform design. - -Bus drivers introduce abstraction using generic storage traits and expose them to NOR device drivers such as Macronix or Winbond to communicate with the Hardware without worrying about low level bus protocol details. - -Bus driver + generic storage traits can handle other protocol such as I2C or NVMe without any impact to the device drivers. - -# Static Design - -## Storage Bus Driver design -```mermaid - classDiagram - class Macronix-Device-Driver - class Storage-Bus["Storage Bus trait"] - class Spi-Storage-Bus - class Spi-Hal - class Winbond-Device-Driver - Winbond-Device-Driver <|--|> Storage-Bus - <> Storage-Bus - Macronix-Device-Driver <|--|> Storage-Bus - Storage-Bus <|--|> Spi-Storage-Bus - Spi-Hal <|--|> Spi-Storage-Bus -``` - -## Example -``` -/// SPI Bus driver instance - -pub struct SpiNorStorageBus { - // Structure Fields -} - -impl BlockingNorStorageBusDriver for SpiNorStorageBus { - fn send_command( - &mut self, - cmd: NorStorageCmd, - read_buf: Option<&mut [u8]>, - write_buf: Option<&[u8]>, - ) -> Result<(), impl NorStorageBusError> { - // Handle the storage commands - } -} -``` diff --git a/storage-bus/src/lib.rs b/storage-bus/src/lib.rs deleted file mode 100644 index 34e80df..0000000 --- a/storage-bus/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![no_std] - -pub mod nand; -pub mod nor; diff --git a/storage-bus/src/nand.rs b/storage-bus/src/nand.rs deleted file mode 100644 index 5debd7e..0000000 --- a/storage-bus/src/nand.rs +++ /dev/null @@ -1,7 +0,0 @@ -/// Blocking NAND Storage Driver. The trait introduces a method to send command to the bus -/// The NAND device driver should use this trait APIs to send command to the bus -pub trait BlockingNandStorageBusDriver {} - -/// Async NAND Storage Driver. The trait introduces a method to send command to the bus -/// The NAND device driver should use this trait APIs to send command to the bus -pub trait AsyncNandStorageBusDriver {} diff --git a/storage-bus/src/nor.rs b/storage-bus/src/nor.rs deleted file mode 100644 index a035722..0000000 --- a/storage-bus/src/nor.rs +++ /dev/null @@ -1,129 +0,0 @@ -#[derive(Debug, Copy, Clone, PartialEq)] -/// Storage Mode -pub enum NorStorageCmdMode { - /// Double Data Rate mode for data transfer - DDR, - /// Single Data Rate mode for data transfer - SDR, -} -#[derive(Debug, Copy, Clone)] -/// Storage Command Type -pub enum NorStorageCmdType { - /// Read transfer type - Read, - /// Write transfer type - Write, -} - -#[derive(Debug, Copy, Clone)] -/// Bus Width -pub enum NorStorageBusWidth { - /// 1 bit bus width - Single, - /// 2 bit bus width - Dual, - /// 4 bit bus width - Quad, - /// 8 bit bus width - Octal, -} - -#[derive(Debug, Copy, Clone)] -/// enum for dummy cycles -pub enum NorStorageDummyCycles { - /// Dummy cycles in terms of clock cycles - Clocks(u8), - /// Dummy cycles in terms of bytes - Bytes(u8), -} - -#[derive(Debug, Copy, Clone)] -/// NOR Storage Command to be passed by NOR based storage device drivers -pub struct NorStorageCmd { - /// Nor Storage Command lower byte - pub cmd_lb: u8, - /// Nor Storage Command upper byte - pub cmd_ub: Option, - /// Address of the command - pub addr: Option, - /// Address width in bytes - pub addr_width: Option, - /// DDR or SDR mode - pub mode: NorStorageCmdMode, - /// Number of Dummy clock cycles. Assuming max 256 dummy cycles beyond which its impractical - pub dummy: NorStorageDummyCycles, - /// Command type - Reading data or writing data - pub cmdtype: Option, - /// Bus Width - This represents width in terms of signals - /// SPI - Single - /// QSPI - Quad - /// OctalSPI - Octal - /// I2C - 1 - pub bus_width: NorStorageBusWidth, - /// Number of data bytes to be transferred for this command - pub data_bytes: Option, -} - -/// Enum with storage errors -pub enum NorStorageBusError { - /// Bus not available could be used for example - /// 1. Bus is not available due to arbitration lost in multi master bus - /// 2. Bus is not powered up - StorageBusNotAvailable, - /// Bus IO error while sending command - /// Could be used for example - /// 1 - Bus read error - /// 2 - Bus write error - StorageBusIoError, - /// Bus internal error - StorageBusInternalError, -} - -/// Blocking NOR Storage Driver. The trait introduces a method to send command to the bus -/// The NOR device driver should use this trait to send command to the bus -/// NOR Storage Bus driver shall implement this trait to support NOR storage access over the bus -/// Bus Examples - -/// - SPI -/// - FlexSPI -/// - Hyperbus -pub trait BlockingNorStorageBusDriver { - /// Send Command to the bus - /// Parameters: - /// cmd - Command to be sent to the bus - /// read_buf - Read buffer to store the data read from the bus - /// write_buf - Write buffer to write the data to the bus - /// Returns: - /// Result<(), NorStorageBusError> - Result of the command sent to the bus - /// NorStorageBusError - Error code if the command failed - fn send_command( - &mut self, - cmd: NorStorageCmd, - read_buf: Option<&mut [u8]>, - write_buf: Option<&[u8]>, - ) -> Result<(), NorStorageBusError>; -} - -#[allow(async_fn_in_trait)] -/// Async NOR Storage Driver. The trait introduces a method to send command to the bus -/// The NOR Storage device driver should use this trait to send command to the bus -/// NOR Storage Bus driver shall implement this trait to support NOR storage access over the bus -/// Bus Examples - -/// - SPI -/// - FlexSPI -/// - Hyperbus -pub trait AsyncNorStorageBusDriver { - /// Send Command to the bus - /// Parameters: - /// cmd - Command to be sent to the bus - /// read_buf - Read buffer to store the data read from the bus - /// write_buf - Write buffer to write the data to the bus - /// Returns: - /// Result<(), NorStorageBusError> - Result of the command sent to the bus - /// NorStorageBusError - Error code if the command failed - async fn send_command( - &mut self, - cmd: NorStorageCmd, - read_buf: Option<&mut [u8]>, - write_buf: Option<&[u8]>, - ) -> Result<(), NorStorageBusError>; -}