Merge pull request 'update safety notes' (#1) from update-safety-notes into main
ci / Check build (macos-latest) (push) Has been cancelled
ci / Check build (ubuntu-latest) (push) Has been cancelled
ci / Check build (windows-latest) (push) Has been cancelled
ci / Run Tests (push) Has been cancelled
ci / Check MSRV (push) Has been cancelled
ci / Check Cross-Compilation (armv7-unknown-linux-gnueabihf) (push) Has been cancelled
ci / Check Cross-Compilation (thumbv7em-none-eabihf) (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
ci / Check build (macos-latest) (push) Has been cancelled
ci / Check build (ubuntu-latest) (push) Has been cancelled
ci / Check build (windows-latest) (push) Has been cancelled
ci / Run Tests (push) Has been cancelled
ci / Check MSRV (push) Has been cancelled
ci / Check Cross-Compilation (armv7-unknown-linux-gnueabihf) (push) Has been cancelled
ci / Check Cross-Compilation (thumbv7em-none-eabihf) (push) Has been cancelled
ci / Check formatting (push) Has been cancelled
ci / Check Documentation Build (push) Has been cancelled
ci / Clippy (push) Has been cancelled
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
commit
5f7ff2fc5d
3 files changed
+62
-17
No files matched your search
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v0.1.2] 2026-06-08
|
||||
|
||||
- Released with new name `raw-buffer`.
|
||||
- Added more safety notes.
|
||||
|
||||
# [v0.1.1]
|
||||
|
||||
Badge fix, points to wrong crate.
|
||||
@@ -16,5 +21,11 @@ Badge fix, points to wrong crate.
|
||||
|
||||
Initial release
|
||||
|
||||
# Release with new name
|
||||
|
||||
[v0.1.2]: https://egit.irs.uni-stuttgart.de/rust/raw-buffer/releases/tag/v0.1.2
|
||||
|
||||
# Release with old name `raw-slicee`
|
||||
|
||||
[v0.1.1]: https://egit.irs.uni-stuttgart.de/rust/raw-slice/compare/v0.1.0...v0.1.1
|
||||
[v0.1.0]: https://egit.irs.uni-stuttgart.de/rust/raw-slice/releases/tag/v0.1.0
|
||||
+4
-8
@@ -1,19 +1,15 @@
|
||||
[package]
|
||||
name = "raw-slicee"
|
||||
version = "0.1.1"
|
||||
name = "raw-buffer"
|
||||
version = "0.1.2"
|
||||
edition = "2024"
|
||||
rust-version = "1.85.1"
|
||||
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
||||
description = "Generic low-level raw slice types"
|
||||
homepage = "https://egit.irs.uni-stuttgart.de/rust/raw-slice"
|
||||
repository = "https://egit.irs.uni-stuttgart.de/rust/raw-slice"
|
||||
homepage = "https://egit.irs.uni-stuttgart.de/rust/raw-buffer"
|
||||
repository = "https://egit.irs.uni-stuttgart.de/rust/raw-buffer"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
keywords = ["no-std", "slice", "embedded", "dma", "pointer"]
|
||||
categories = ["no-std", "no-std::no-alloc", "hardware-support", "embedded", "data-structures"]
|
||||
|
||||
# Name was hogged.
|
||||
[lib]
|
||||
name = "raw_slice"
|
||||
|
||||
[dependencies]
|
||||
embedded-dma = "0.2"
|
||||
+47
-9
@@ -12,7 +12,7 @@
|
||||
//! This data structure is particularly useful in embedded systems, where data may be
|
||||
//! passed to asynchronous peripherals such as serial TX drivers using interrupts or DMA.
|
||||
//! The data may be static, but it could also reside on the stack. By using a shared [RawBufSlice],
|
||||
//! you can pass borrowed data to a driver **without** needing to explicitly manage lifetimes.
|
||||
//! you can pass borrowed data to a driver without needing to explicitly manage lifetimes.
|
||||
//!
|
||||
//! ## Safety Considerations
|
||||
//!
|
||||
@@ -22,6 +22,12 @@
|
||||
//! (e.g., an ISR and a task) requires proper synchronization.
|
||||
//! - **Immutability:** [RawSlice] provides a **read-only view** of the data. If you need
|
||||
//! mutability, [RawSliceMut] can be used.
|
||||
//! - If the raw slice wrapper is used with stack allocated slices: Higher-level APIs
|
||||
//! oftentimes rely on `Drop` implementations to allow cancelling
|
||||
//! transfers on non-blocking APIs. Using `core::mem::forget` on such implementations
|
||||
//! can leak the underlying memory. HAL and firmware authors *MUST* either use this
|
||||
//! abstraction combined with `'static` slices or ensure that the `Drop`
|
||||
//! implementations always runs properly.
|
||||
//!
|
||||
//! ## Usage Example
|
||||
//!
|
||||
@@ -30,7 +36,9 @@
|
||||
//!
|
||||
//! static DATA: &[u8] = &[1, 2, 3, 4];
|
||||
//!
|
||||
//! let raw_buf = unsafe { RawBufSlice::new(DATA) };
|
||||
//! // Safety: Your safety note here. We are using static data, your DMA might have other
|
||||
//! // requirements to the buffer used, e.g. buffer in correct RAM, with certain alignment etc.
|
||||
//! let raw_buf = unsafe { RawSlice::new(DATA) };
|
||||
//!
|
||||
//! // Later, in an ISR or different context
|
||||
//! unsafe {
|
||||
@@ -68,9 +76,9 @@ impl<T> RawSlice<T> {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`.
|
||||
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`. This is especially
|
||||
/// important if the original slice is stack allocated.
|
||||
/// - The original slice **must not** be mutated while this `RawSlice<T>` is used.
|
||||
#[allow(dead_code)]
|
||||
pub const unsafe fn new(data: &[T]) -> Self {
|
||||
Self {
|
||||
data: data.as_ptr(),
|
||||
@@ -90,7 +98,8 @@ impl<T> RawSlice<T> {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`.
|
||||
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`. This is especially
|
||||
/// important if the original slice is stack allocated.
|
||||
/// - The original slice **must not** be mutated while this `RawSlice<T>` is used.
|
||||
pub const unsafe fn set(&mut self, data: &[T]) {
|
||||
self.data = data.as_ptr();
|
||||
@@ -153,11 +162,25 @@ pub type RawU32Slice = RawSlice<u32>;
|
||||
|
||||
macro_rules! impl_dma_read_buf {
|
||||
($slice_type:ident, $ty:ident) => {
|
||||
/// This allows using [Self] in DMA APIs which expect a [embedded_dma::ReadBuffer].
|
||||
/// This allows using [Self] in DMA based APIs which expect a [embedded_dma::ReadBuffer].
|
||||
///
|
||||
/// However, the user still must ensure that any alignment rules for DMA buffers required by
|
||||
/// the hardware are met and than any MPU/MMU configuration necessary is also performed for this
|
||||
/// to work properly.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The raw slice type erases the lifetime of slice. The caller *MUST* ensure that the
|
||||
/// lifetime of the slice is valid as long as the buffer is in-use by the DMA.
|
||||
/// - It is also imperitive that the DMA system you're using returns the pointer
|
||||
/// *only after a DMA transfer is complete*. If you're unsure check the docs and if nothing
|
||||
/// is mentioned in the docs please clarify it with a project maintainer.
|
||||
/// - If the raw slice wrapper is used on a stack allocated slice: Higher-level APIs
|
||||
/// oftentimes rely on `Drop` implementations to allow cancelling
|
||||
/// transfers on non-blocking APIs. Using `core::mem::forget` on such implementations
|
||||
/// can leak the underlying memory. HAL and firmware authors *MUST* either use this
|
||||
/// abstraction combined with `'static` slices or ensure that the `Drop`
|
||||
/// implementations always runs properly.
|
||||
unsafe impl embedded_dma::ReadBuffer for $slice_type {
|
||||
type Word = $ty;
|
||||
|
||||
@@ -186,9 +209,9 @@ impl<T> RawSliceMut<T> {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`.
|
||||
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`. This is especially
|
||||
/// important if the original slice is stack allocated.
|
||||
/// - The original slice **must not** be mutated while this `RawSlice<T>` is used.
|
||||
#[allow(dead_code)]
|
||||
pub const unsafe fn new(data: &mut [T]) -> Self {
|
||||
Self {
|
||||
data: data.as_mut_ptr(),
|
||||
@@ -208,7 +231,8 @@ impl<T> RawSliceMut<T> {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`.
|
||||
/// - The caller **must** ensure that the slice outlives this `RawSlice<T>`. This is especially
|
||||
/// important if the original slice is stack allocated.
|
||||
/// - The original slice **must not** be mutated while this `RawSlice<T>` is used.
|
||||
pub const unsafe fn set(&mut self, data: &mut [T]) {
|
||||
self.data = data.as_mut_ptr();
|
||||
@@ -288,6 +312,20 @@ macro_rules! impl_dma_write_buf {
|
||||
///
|
||||
/// However, the user still must ensure that any alignment rules for DMA buffers required by
|
||||
/// the hardware are met and than any MPU/MMU configuration necessary was also performed.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The raw slice type erases the lifetime of slice. The caller *MUST* ensure that the
|
||||
/// lifetime of the slice is valid as long as the buffer is in-use by the DMA.
|
||||
/// - It is also imperitive that the DMA system you're using returns the pointer
|
||||
/// *only after a DMA transfer is complete*. If you're unsure check the docs and if nothing
|
||||
/// is mentioned in the docs please clarify it with a project maintainer.
|
||||
/// - If the raw slice wrapper is used on a stack allocated slice: Higher-level APIs
|
||||
/// oftentimes rely on `Drop` implementations to allow cancelling
|
||||
/// transfers on non-blocking APIs. Using `core::mem::forget` on such implementations
|
||||
/// can leak the underlying memory, allowing hardware to write to invalid memory
|
||||
/// locations. HAL and firmware authors *MUST* either use this abstraction combined with
|
||||
/// `'static` slices or ensure that the `Drop` implementations always runs properly.
|
||||
unsafe impl embedded_dma::WriteBuffer for $slice_type {
|
||||
type Word = $ty;
|
||||
|
||||
|
||||
Reference in new issue
Block a user