Validate configuration through its owning schemas and keep board declarations separate from shared F722 resource ownership. Bound USB transitions, isolate transport failures and retain restart-only activation. Migrate navigation and flight consumers with the sensor and schema contracts. Require explicit installation data and synchronous output authority; board motor outputs remain inhibited. Validation: assembled-prefix host tests, strict Clippy, platform/USB tests and both ARM release builds. Final-source coverage and scoped Miri/Kani evidence are retained separately from hardware qualification.
82 lines
3.5 KiB
Rust
82 lines
3.5 KiB
Rust
//! Non-blocking, chip-select-scoped SPI transfer contract.
|
|
//!
|
|
//! A selected device owns electrical chip-select behavior and asynchronous
|
|
//! transfer storage. Submission copies in; successful completion copies out.
|
|
//! No caller borrow or caller address may survive either method call.
|
|
|
|
#![no_std]
|
|
|
|
pub mod dma;
|
|
|
|
/// Terminal outcome reported by a selected SPI device.
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub enum SpiCompletion {
|
|
/// The bound interrupt does not report a terminal event.
|
|
NotPending,
|
|
/// The submitted full-duplex transfer completed.
|
|
Complete,
|
|
/// The submitted transfer failed and its receive bytes are unusable.
|
|
TransferFault,
|
|
}
|
|
|
|
/// Failure to accept and copy out a completed transfer. No receive bytes are
|
|
/// changed on error.
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub enum CompletionError {
|
|
/// No terminal event: leave the active transfer entirely untouched.
|
|
NotPending,
|
|
/// There is no submitted transfer to complete.
|
|
NotActive,
|
|
/// The destination length differs from the submitted length.
|
|
InvalidLength,
|
|
/// The transfer failed; no receive bytes are usable.
|
|
TransferFault,
|
|
/// Quiescence could not be proven. Storage and route are permanently held.
|
|
Quarantined,
|
|
}
|
|
|
|
/// Owns one chip-select-scoped, non-blocking SPI route.
|
|
///
|
|
/// Moving, dropping, or forgetting the device or caller buffers during a
|
|
/// transfer must be memory-safe. Hardware accesses only implementation-owned
|
|
/// storage whose allocation outlives hardware activity, including cancellation.
|
|
pub trait SpiDevice {
|
|
/// Failure to submit a transfer.
|
|
type StartError;
|
|
|
|
/// Identifies a temporary admission rejection. No transfer was accepted.
|
|
/// Drivers may retry the same pending operation within their deadline.
|
|
fn is_busy(_error: &Self::StartError) -> bool {
|
|
false
|
|
}
|
|
|
|
/// Copies `transmit` into bounded route-owned storage and starts one
|
|
/// full-duplex transfer. Empty/oversized submissions must fail safely.
|
|
///
|
|
/// No pointer into `transmit` is retained. Chip select is asserted before
|
|
/// submission; rejecting a concurrent submission must not disturb it.
|
|
fn start_transfer(&mut self, transmit: &[u8]) -> Result<(), Self::StartError>;
|
|
|
|
/// On `Complete`, proves hardware quiescence before copying exactly the
|
|
/// submitted number of bytes to an equally sized `receive` and releasing
|
|
/// chip select. An interrupt notification alone is not proof of quiescence.
|
|
///
|
|
/// `NotPending` returns that error without aborting or changing anything.
|
|
/// Faults cancel the transfer without copying out. Any bounded hardware
|
|
/// shutdown that cannot prove quiescence must quarantine the route and its
|
|
/// storage permanently, preventing reuse. No destination pointer is retained.
|
|
/// Passing `TransferFault` also requests cancellation without an IRQ. It must
|
|
/// perform the same bounded shutdown and return `TransferFault` only after
|
|
/// quiescence, or `Quarantined` if that cannot be proved. No bytes are copied.
|
|
///
|
|
/// Providers must validate current hardware progress, not trust a notification
|
|
/// from a previous transfer. Before reuse, drain old hardware flags/data. A
|
|
/// delayed notification may fault a new incomplete transfer but must never
|
|
/// publish old receive storage as a new result.
|
|
fn complete_transfer(
|
|
&mut self,
|
|
completion: SpiCompletion,
|
|
receive: &mut [u8],
|
|
) -> Result<(), CompletionError>;
|
|
}
|