From bedfdbf94cd63133afd6f9938864aeeee3063d2c Mon Sep 17 00:00:00 2001 From: Brad Campbell Date: Fri, 23 Aug 2024 11:07:00 -0400 Subject: [PATCH] kernel: hil: spi: improve rustdoc --- kernel/src/hil/spi.rs | 613 +++++++++++++++++++++--------------------- 1 file changed, 312 insertions(+), 301 deletions(-) diff --git a/kernel/src/hil/spi.rs b/kernel/src/hil/spi.rs index e6904c0202..ac7478b105 100644 --- a/kernel/src/hil/spi.rs +++ b/kernel/src/hil/spi.rs @@ -2,10 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT // Copyright Tock Contributors 2022. -//! Interfaces for SPI controller (master) and peripheral (slave) -//! communication. We use the terms master/slave in some situations -//! because the term peripheral can also refer to a hardware peripheral -//! (e.g., memory-mapped I/O devices in ARM are called peripherals). +//! Interfaces for SPI controller (master) and peripheral (slave) communication. +//! +//! We use the terms master/slave in some situations because the term peripheral +//! can also refer to a hardware peripheral (e.g., memory-mapped I/O devices in +//! ARM are called peripherals). // Author: Alexandru Radovici // Author: Philip Levis @@ -15,39 +16,53 @@ use crate::ErrorCode; -/// Data order defines the order of bits sent over the wire: most -/// significant first, or least significant first. +/// Data order defines the order of bits sent over the wire: most significant +/// first, or least significant first. #[derive(Copy, Clone, Debug)] pub enum DataOrder { + /// Send the most significant byte first. MSBFirst, + /// Send the least significant byte first. LSBFirst, } -/// Clock polarity (CPOL) defines whether the SPI clock is high -/// or low when idle. +/// Clock polarity (CPOL) defines whether the SPI clock is high or low when +/// idle. #[derive(Copy, Clone, Debug, PartialEq)] pub enum ClockPolarity { + /// The clock is low when the SPI bus is not active. This is CPOL = 0. IdleLow, + /// The clock is high when the SPI bus is not active. This is CPOL = 1. IdleHigh, } -/// Clock phase (CPHA) defines whether to sample and send data on -/// a leading or trailing clock edge; consult a SPI reference -/// on how CPHA interacts with CPOL. +/// Clock phase (CPHA) defines whether to sample and send data on a leading or +/// trailing clock edge. +/// +/// Consult a SPI reference on how CPHA interacts with CPOL. #[derive(Copy, Clone, Debug, PartialEq)] pub enum ClockPhase { + /// Sample on the leading clock edge. This is CPHA = 0. If CPOL is 0, then + /// this samples on the rising edge of the clock. If CPOL is 1, then this + /// samples on the falling edge of the clock. SampleLeading, + /// Sample on the trailing clock edge. This is CPHA = 1. If CPOL is 0, then + /// this samples on the falling edge of the clock. If CPOL is 1, then this + /// samples on the rising edge of the clock. SampleTrailing, } -/// Utility types for modeling chip select pins in a [SpiMaster] implementation. +/// Utility types for modeling chip select pins in a [`SpiMaster`] +/// implementation. pub mod cs { - /// Represents the Polarity of a chip-select pin (i.e. whether - /// high or low indicates the peripheral is active) + /// Represents the Polarity of a chip-select pin (i.e. whether high or low + /// indicates the peripheral is active). #[derive(Copy, Clone)] pub enum Polarity { + /// Chip select is active high. High, + /// Chip select is active low. Low, } @@ -55,21 +70,21 @@ pub mod cs { pub trait Sealed {} } - /// Marker trait indicating whether a peripheral requires active - /// high or low polarity as well as whether a [SpiMaster](super::SpiMaster) + /// Marker trait indicating whether a peripheral requires active high or low + /// polarity as well as whether a [`SpiMaster`](super::SpiMaster) /// implementation can support either or both polarities. /// - /// This trait is sealed and only implemented for [ActiveLow] and - /// [ActiveHigh]. + /// This trait is sealed and only implemented for [`ActiveLow`] and + /// [`ActiveHigh`]. pub trait ChipSelectActivePolarity: private::Sealed { const POLARITY: Polarity; } - /// Marks a peripheral as requiring or controller as supprting - /// active low chip select pins + /// Marks a peripheral as requiring or controller as supporting active low + /// chip select pins. pub enum ActiveLow {} - /// Marks a peripheral as requiring or controller as supprting - /// active high chip select pins + /// Marks a peripheral as requiring or controller as supporting active high + /// chip select pins. pub enum ActiveHigh {} impl private::Sealed for ActiveLow {} @@ -84,21 +99,22 @@ pub mod cs { } /// A type that can be converted to the appropriate type for - /// [SpiMaster::ChipSelect](super::SpiMaster::ChipSelect) for a - /// particular `POLARITY`. + /// [`SpiMaster::ChipSelect`](super::SpiMaster::ChipSelect) for a particular + /// `POLARITY`. /// /// Instantiating a driver for any SPI peripheral should require a type that - /// implements [IntoChipSelect]. That enforces that whatever object is used - /// as the chip select can support the correct polarity for the particular SPI - /// peripheral. This is mostly commonly handled by the component for the - /// peripheral, which requires an object with type [IntoChipSelect] and then - /// converts the object to the [SpiMaster::ChipSelect](super::SpiMaster::ChipSelect) - /// type. + /// implements [`IntoChipSelect`]. That enforces that whatever object is + /// used as the chip select can support the correct polarity for the + /// particular SPI peripheral. This is mostly commonly handled by the + /// component for the peripheral, which requires an object with type + /// [`IntoChipSelect`] and then converts the object to the + /// [`SpiMaster::ChipSelect`](super::SpiMaster::ChipSelect) type. + /// /// # Examples: /// - /// Some SPI host controllers only support active low or active - /// high chip select pins. Such a controller might provide a unit - /// implementation of this trait _only_ for the [ActiveLow] marker. + /// Some SPI host controllers only support active low or active high chip + /// select pins. Such a controller might provide a unit implementation of + /// this trait _only_ for the [`ActiveLow`] marker. /// /// ```rust /// use kernel::hil::spi::cs::*; @@ -114,23 +130,22 @@ pub mod cs { /// } /// ``` /// - /// Many other controllers can handle both active low and active - /// high chip select pins, in which case, they should implement - /// both the [ActiveLow] and [ActiveHigh] variants, for example, - /// using the [ChipSelectPolar] wrapper struct (which implements - /// both). + /// Many other controllers can handle both active low and active high chip + /// select pins, in which case, they should implement both the [`ActiveLow`] + /// and [`ActiveHigh`] variants, for example, using the [`ChipSelectPolar`] + /// wrapper struct (which implements both). pub trait IntoChipSelect { fn into_cs(self) -> T; } - /// A convenience wrapper type around - /// [Output](crate::hil::gpio::Output) GPIO pins that implements - /// [IntoChipSelect] for both [ActiveLow] and [ActiveHigh]. + /// A convenience wrapper type around [`Output`](crate::hil::gpio::Output) + /// GPIO pins that implements [`IntoChipSelect`] for both [`ActiveLow`] and + /// [`ActiveHigh`]. pub struct ChipSelectPolar<'a, P: crate::hil::gpio::Output> { - /// The underlying chip select "pin" + /// The underlying chip select "pin". pub pin: &'a P, /// The polarity from which this wrapper was derived using - /// [IntoChipSelect] + /// [`IntoChipSelect`]. pub polarity: Polarity, } @@ -154,13 +169,14 @@ pub mod cs { } /// When wrapping a GPIO pin that implements - /// [gpio::Output](crate::hil::gpio::Output), users can use the - /// `activate` and `deactivate` methods to automatically set or - /// clear the chip select pin based on the stored polarity. + /// [`gpio::Output`](crate::hil::gpio::Output), users can use the + /// [`activate`](ChipSelectPolar::activate) and + /// [`deactivate`](ChipSelectPolar::deactivate) methods to automatically set + /// or clear the chip select pin based on the stored polarity. impl<'a, P: crate::hil::gpio::Output> ChipSelectPolar<'a, P> { - /// Deactive the chip select pin + /// Deactivate the chip select pin. /// - /// High if active low, low if active high + /// High if active low, low if active high. pub fn deactivate(&self) { match self.polarity { Polarity::Low => self.pin.set(), @@ -168,9 +184,9 @@ pub mod cs { } } - /// Active the chip select pin + /// Active the chip select pin. /// - /// Low if active low, high if active high + /// Low if active low, high if active high. pub fn activate(&self) { match self.polarity { Polarity::Low => self.pin.clear(), @@ -182,9 +198,9 @@ pub mod cs { /// Trait for clients of a SPI bus in master mode. pub trait SpiMasterClient { - /// Callback when a read/write operation finishes: `read_buffer` - /// is an `Option` because the call passes an `Option` (with - /// `None` if it's a write-only operation. + /// Callback when a read/write operation finishes: `read_buffer` is an + /// `Option` because the call passes an `Option` (with `None` if it's a + /// write-only operation. fn read_write_done( &self, write_buffer: &'static mut [u8], @@ -193,93 +209,101 @@ pub trait SpiMasterClient { status: Result<(), ErrorCode>, ); } -/// The `SpiMaster` trait for interacting with SPI slave -/// devices at a byte or buffer level. +/// Trait for interacting with SPI peripheral devices at a byte or buffer level. +/// +/// Using [`SpiMaster`] normally involves three steps: +/// +/// 1. Configure the SPI bus for a peripheral. /// -/// Using SpiMaster normally involves three steps: +/// 1. Call [`SpiMaster::specify_chip_select`] to select which peripheral and +/// turn on SPI. /// -/// 1. Configure the SPI bus for a peripheral -/// 1a. Call set_chip_select to select which peripheral and -/// turn on SPI -/// 1b. Call set operations as needed to configure bus -/// NOTE: You MUST select the chip select BEFORE configuring -/// SPI settings. -/// 2. Invoke read, write, read_write on SpiMaster -/// 3a. Call clear_chip_select to turn off bus, or -/// 3b. Call set_chip_select to choose another peripheral, -/// go to step 1b or 2. +/// 2. Call set operations as needed to configure the bus. **NOTE**: You MUST +/// select the chip select BEFORE configuring SPI settings. /// -/// The SPI configuration for a particular peripheral persists across -/// changes to the chip select. For example, this set of calls +/// 2. Invoke [`SpiMaster::read_write_bytes`] on [`SpiMaster`]. /// -/// specify_chip_select(1); -/// set_phase(SampleLeading); -/// specify_chip_select(2); -/// set_phase(SampleTrailing); -/// specify_chip_select(1); -/// write_byte(0); // Uses SampleLeading +/// 3. Go back to step 2 to complete another transaction, or call +/// [`SpiMaster::specify_chip_select`] to choose another peripheral and go to +/// step 1.2 or 2. /// -/// will have a SampleLeading phase in the final `write_byte` call, -/// because the configuration of chip select 1 is saved, and restored -/// when chip select is set back to 1. +/// The SPI configuration for a particular peripheral persists across changes to +/// the chip select. For example, this set of calls: /// -/// If additional chip selects are needed, they can be performed -/// with GPIO and manual re-initialization of settings. Note that -/// a SPI chip select (CS) line is usually active low. +/// ```rust,ignore +/// SpiMaster::specify_chip_select(1); +/// SpiMaster::set_phase(ClockPhase::SampleLeading); +/// SpiMaster::specify_chip_select(2); +/// SpiMaster::set_phase(ClockPhase::SampleTrailing); +/// SpiMaster::specify_chip_select(1); +/// SpiMaster::write_byte(0); // Uses SampleLeading +/// ``` /// -/// specify_chip_select(0); -/// set_phase(SampleLeading); -/// pin_a.clear(); // Select A -/// write_byte(0xaa); // Uses SampleLeading -/// pin_a.set(); // Unselect A -/// set_phase(SampleTrailing); -/// pin_b.clear(); // Select B -/// write_byte(0xaa); // Uses SampleTrailing +/// will have a [`ClockPhase::SampleLeading`] phase in the final +/// [`SpiMaster::write_byte`] call, because the configuration of chip select 1 +/// is saved, and restored when chip select is set back to 1. /// +/// If additional chip selects are needed, they can be performed with GPIO and +/// manual re-initialization of settings. Note that a SPI chip select (CS) line +/// is usually active low. +/// +/// ```rust,ignore +/// specify_chip_select(0); +/// set_phase(ClockPhase::SampleLeading); +/// pin_a.clear(); // Select A +/// write_byte(0xaa); // Uses SampleLeading +/// pin_a.set(); // Unselect A +/// set_phase(ClockPhase::SampleTrailing); +/// pin_b.clear(); // Select B +/// write_byte(0xaa); // Uses SampleTrailing +/// ``` pub trait SpiMaster<'a> { - /// Chip select is an associated type because different SPI - /// buses may have different numbers of chip selects. This - /// allows peripheral implementations to define their own type. + /// Chip select is an associated type because different SPI buses may have + /// different numbers of chip selects. This allows peripheral + /// implementations to define their own type. type ChipSelect: Copy; - /// Initialize this SPI interface. Call this once before - /// invoking any other operations. Return values are: - /// - Ok(()): initialized correctly - /// - Err(OFF): not currently powered so can't be initialized - /// - Err(RESERVE): no clock is configured yet - /// - Err(FAIL): other failure condition + /// Initialize this SPI interface. Call this once before invoking any other + /// operations. + /// + /// ### Return values + /// + /// - `Ok(())`: initialized correctly + /// - `Err(OFF)`: not currently powered so can't be initialized + /// - `Err(RESERVE)`: no clock is configured yet + /// - `Err(FAIL)`: other failure condition fn init(&self) -> Result<(), ErrorCode>; - /// Change the callback handler for `read_write_bytes` - /// calls. + /// Change the callback handler for [`SpiMaster::read_write_bytes`] calls. fn set_client(&self, client: &'a dyn SpiMasterClient); - /// Return whether the SPI peripheral is busy with `read_write_bytes` - /// call. + /// Return whether the SPI peripheral is busy with a + /// [`SpiMaster::read_write_bytes`] operation. fn is_busy(&self) -> bool; - /// Perform an asynchronous read/write operation, whose - /// completion is signaled by invoking SpiMasterClient on - /// the client. Write-only operations may pass `None` for - /// `read_buffer`, while read-write operations pass `Some` - /// for `read_buffer`. + /// Perform an asynchronous read/write operation, whose completion is + /// signaled by invoking [`SpiMasterClient`] on the client. Write-only + /// operations may pass `None` for `read_buffer`, while read-write + /// operations pass `Some` for `read_buffer`. + /// + /// If `read_buffer` is `None`, the number of bytes written will be the + /// minimum of the length of `write_buffer` and the `len` argument. If + /// `read_buffer` is `Some`, the number of bytes read/written will be the + /// minimum of the `len` argument, the length of `write_buffer`, and the + /// length of `read_buffer`. /// - /// If `read_buffer` is `None`, the - /// number of bytes written will be the mimumum of the length of - /// `write_buffer` and the `len` argument. If `read_buffer` - /// is `Some`, the number of bytes read/written will be the - /// minimum of the `len` argument, the length of `write_buffer`, - /// and the length of `read_buffer`. + /// ### Return values /// /// If `read_write_bytes` returns `Ok(())`, the operation will be /// attempted and a callback will be called. If it returns `Err`, /// no callback will be called and the buffers are returned. - /// - Ok(()): the operation will be attempted and the callback will - /// be called. - /// - Err(OFF): the SPI bus is powered down. - /// - Err(INVAL): length is 0 - /// - Err(BUSY): the SPI bus is busy with a prior `read_write_bytes` - /// operation whose callback hasn't been called yet. + /// - `Ok(())`: the operation will be attempted and the callback will be + /// called. + /// - `Err(OFF)`: the SPI bus is powered down. + /// - `Err(INVAL)`: length is 0 + /// - `Err(BUSY)`: the SPI bus is busy with a prior + /// [`SpiMaster::read_write_bytes`] operation whose callback hasn't been + /// called yet. fn read_write_bytes( &self, write_buffer: &'static mut [u8], @@ -287,93 +311,118 @@ pub trait SpiMaster<'a> { len: usize, ) -> Result<(), (ErrorCode, &'static mut [u8], Option<&'static mut [u8]>)>; - /// Synchronously write a single byte on the bus. Not for general - /// use because it is blocking: intended for debugging. - /// Return values: - /// - Ok(()): the byte was written - /// - Err(OFF): the SPI bus is powered down - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// Synchronously write a single byte on the bus. Not for general use + /// because it is blocking: intended for debugging. + /// + /// ### Return values + /// + /// - `Ok(())`: the byte was written + /// - `Err(OFF)`: the SPI bus is powered down + /// - `Err(BUSY)`: the SPI bus is busy with a + /// [`SpiMaster::read_write_bytes`] operation whose callback hasn't been + /// called yet. + /// - `Err(FAIL)`: other failure fn write_byte(&self, val: u8) -> Result<(), ErrorCode>; - /// Synchronously write a 0 and read a single byte from the bus. - /// Not for general use because it is blocking: intended for debugging. - /// Return values: - /// - Ok((u8)): the read byte - /// - Err(OFF): the SPI bus is powered down - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// Synchronously write a 0 and read a single byte from the bus. Not for + /// general use because it is blocking: intended for debugging. + /// + /// ### Return values + /// + /// - `Ok(u8)`: the read byte + /// - `Err(OFF)`: the SPI bus is powered down + /// - `Err(BUSY)`: the SPI bus is busy with a + /// [`SpiMaster::read_write_bytes`] operation whose callback hasn't been + /// called yet. + /// - `Err(FAIL)`: other failure fn read_byte(&self) -> Result; - /// Synchronously write and read a single byte. - /// Not for general use because it is blocking: intended for debugging. - /// Return values: - /// - Ok((u8)): the read byte - /// - Err(OFF): the SPI bus is powered down - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// Synchronously write and read a single byte. Not for general use because + /// it is blocking: intended for debugging. + /// + /// ### Return values + /// + /// - `Ok(u8)`: the read byte + /// - `Err(OFF)`: the SPI bus is powered down + /// - `Err(BUSY)`: the SPI bus is busy with a + /// [`SpiMaster::read_write_bytes`] operation whose callback hasn't been + /// called yet. + /// - `Err(FAIL)`: other failure fn read_write_byte(&self, val: u8) -> Result; - /// Specify which chip select to use. Configuration settings - /// (rate, polarity, phase) are chip-select specific and are - /// stored for that chip select. + /// Specify which chip select to use. Configuration settings (rate, + /// polarity, phase) are chip-select specific and are stored for that chip + /// select. fn specify_chip_select(&self, cs: Self::ChipSelect) -> Result<(), ErrorCode>; - /// Set the clock/data rate for the current chip select. Return values: - /// - Ok(u32): the actual data rate set (limited by clock precision) - /// - Err(INVAL): a rate outside the bounds of the bus was passed - /// - Err(BUSY): the SPI bus is busy with a read_write_bytes - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// Set the clock/data rate for the current chip select. + /// + /// ### Return values + /// + /// - `Ok(u32)`: the actual data rate set (limited by clock precision) + /// - `Err(INVAL)`: a rate outside the bounds of the bus was passed + /// - `Err(BUSY)`: the SPI bus is busy with a + /// [`SpiMaster::read_write_bytes`] operation whose callback hasn't been + /// called yet. + /// - `Err(FAIL)`: other failure fn set_rate(&self, rate: u32) -> Result; + /// Return the current chip select's clock rate. fn get_rate(&self) -> u32; /// Set the bus polarity (whether idle is high or low) for the - /// current chip select. Return values: - /// - Ok(()): the polarity was set. - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// current chip select. + /// + /// ### Return values + /// + /// - `Ok(())`: the polarity was set. + /// - `Err(BUSY)`: the SPI bus is busy with a + /// [`SpiMaster::read_write_bytes`] operation whose callback hasn't been + /// called yet. + /// - `Err(FAIL)`: other failure fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode>; + /// Return the current bus polarity. fn get_polarity(&self) -> ClockPolarity; /// Set the bus phase for the current chip select (whether data is /// sent/received on leading or trailing edges). - /// - Ok(()): the phase was set. - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// + /// ### Return values + /// + /// - `Ok(())`: the phase was set. + /// - `Err(BUSY)`: the SPI bus is busy with a + /// [`SpiMaster::read_write_bytes`] operation whose callback hasn't been + /// called yet. + /// - `Err(FAIL)`: other failure fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode>; /// Get the current bus phase for the current chip select. fn get_phase(&self) -> ClockPhase; - // These two functions determine what happens to the chip - // select line between transfers. If hold_low() is called, - // then the chip select line is held low after transfers - // complete. If release_low() is called, then the chip select - // line is brought high after a transfer completes. A "transfer" - // is any of the read/read_write calls. These functions - // allow an application to manually control when the - // CS line is high or low, such that it can issue longer - // read/writes with multiple read_write_bytes calls. - - /// Hold the chip select line low after a read_write_bytes completes. - /// This allows a client to make one long SPI read/write with + // These two functions determine what happens to the chip select line + // between transfers. If hold_low() is called, then the chip select line is + // held low after transfers complete. If release_low() is called, then the + // chip select line is brought high after a transfer completes. A "transfer" + // is any of the read/read_write calls. These functions allow an application + // to manually control when the CS line is high or low, such that it can + // issue longer read/writes with multiple read_write_bytes calls. + + /// Hold the chip select line low after a [`SpiMaster::read_write_bytes`] + /// completes. This allows a client to make one long SPI read/write with /// multiple calls to `read_write_bytes`. fn hold_low(&self); - /// Raise the chip select line after a read_write_bytes completes. - /// This will complete the SPI operation. + + /// Raise the chip select line after a [`SpiMaster::read_write_bytes`] + /// completes. This will complete the SPI operation. fn release_low(&self); } -/// SPIMasterDevice provides a chip-select-specific interface to the SPI -/// Master hardware, such that a client cannot changethe chip select line. +/// A chip-select-specific interface to the SPI Controller hardware, such that a +/// client cannot change the chip select line. +/// +/// This restricts the SPI peripherals the client can access to a specific +/// peripheral. pub trait SpiMasterDevice<'a> { /// Set the callback for read_write operations. fn set_client(&self, client: &'a dyn SpiMasterClient); @@ -381,28 +430,7 @@ pub trait SpiMasterDevice<'a> { /// Configure the bus for this chip select. fn configure(&self, cpol: ClockPolarity, cpal: ClockPhase, rate: u32) -> Result<(), ErrorCode>; - /// Perform an asynchronous read/write operation, whose - /// completion is signaled by invoking SpiMasterClient on - /// the client. Write-only operations may pass `None` for - /// `read_buffer`, while read-write operations pass `Some` - /// for `read_buffer`. - /// - /// If `read_buffer` is `None`, the - /// number of bytes written will be the mimumum of the length of - /// `write_buffer` and the `len` argument. If `read_buffer` - /// is `Some`, the number of bytes read/written will be the - /// minimum of the `len` argument, the length of `write_buffer`, - /// and the length of `read_buffer`. - /// - /// If `read_write_bytes` returns `Ok(())`, the operation will be - /// attempted and a callback will be called. If it returns `Err`, - /// no callback will be called and the buffers are returned. - /// - Ok(()): the operation will be attempted and the callback will - /// be called. - /// - Err(OFF): the SPI bus is powered down. - /// - Err(INVAL): length is 0 - /// - Err(BUSY): the SPI bus is busy with a prior `read_write_bytes` - /// operation whose callback hasn't been called yet. + /// Same as [`SpiMaster::read_write_bytes`]. fn read_write_bytes( &self, write_buffer: &'static mut [u8], @@ -410,32 +438,19 @@ pub trait SpiMasterDevice<'a> { len: usize, ) -> Result<(), (ErrorCode, &'static mut [u8], Option<&'static mut [u8]>)>; - /// Set the clock/data rate for this chip select. Return values: - /// - Ok(): set successfully. Note actual rate may differ, check with get_rate. - /// - Err(INVAL): a rate outside the bounds of the bus was passed - /// - Err(BUSY): the SPI bus is busy with a read_write_bytes - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// Same as [`SpiMaster::set_rate`]. fn set_rate(&self, rate: u32) -> Result<(), ErrorCode>; + /// Return the current chip select's clock rate. fn get_rate(&self) -> u32; - /// Set the bus polarity (whether idle is high or low) for this - /// chip select. Return values: - /// - Ok(()): the polarity was set. - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// Same as [`SpiMaster::set_polarity`]. fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode>; + /// Return the current bus polarity. fn get_polarity(&self) -> ClockPolarity; - /// Set the bus phase for this chip select (whether data is - /// sent/received on leading or trailing edges). - /// - Ok(()): the phase was set. - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// Same as [`SpiMaster::set_phase`]. fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode>; /// Get the current bus phase for the current chip select. @@ -443,25 +458,28 @@ pub trait SpiMasterDevice<'a> { } /// Trait for SPI peripherals (slaves) to receive callbacks when the -/// corresponding controller (master) issues operations. A SPI operation -/// begins with a callback of `chip_selected`. If the client has -/// provided buffers with `SpiSlave::read_write_bytes`, these buffers -/// are written from and read into until the operation completes or one -/// of them fills, at which point a `SpiSlaveClient::read_write_done` -/// callback is called. If the client needs to read/write more it -/// can call `SpiSlave::read_write_bytes` again. Note that there is -/// no notification when the chip select line goes high. +/// corresponding controller (master) issues operations. +/// +/// A SPI operation begins with a callback of [`SpiSlaveClient::chip_selected`]. +/// If the client has provided buffers with [`SpiSlave::read_write_bytes`], +/// these buffers are written from and read into until the operation completes +/// or one of them fills, at which point a [`SpiSlaveClient::read_write_done`] +/// callback is called. If the client needs to read/write more it can call +/// [`SpiSlave::read_write_bytes`] again. +/// +/// Note that there is no notification when the chip select line goes high. pub trait SpiSlaveClient { /// Notification that the chip select has been brought low. fn chip_selected(&self); - /// Callback issued when the controller completes an SPI operation - /// to this peripheral. `write_buffer` and `read_buffer` are - /// the values passed in the previous call to - /// `SpiSlave::read_write_bytes`. The `len` parameter specifies - /// how many bytes were written from/read into `Some` values of - /// these buffers. `len` may be shorter than the size of these - /// buffers if the operation did not fill them. + /// Callback issued when the controller completes an SPI operation to this + /// peripheral. + /// + /// `write_buffer` and `read_buffer` are the values passed in the previous + /// call to [`SpiSlave::read_write_bytes`]. The `len` parameter specifies + /// how many bytes were written from/read into `Some` values of these + /// buffers. `len` may be shorter than the size of these buffers if the + /// operation did not fill them. fn read_write_done( &self, write_buffer: Option<&'static mut [u8]>, @@ -472,46 +490,53 @@ pub trait SpiSlaveClient { } /// Trait for SPI peripherals (slaves) to exchange data with a contoller -/// (master). This is a low-level trait typically implemented by hardware: -/// higher level software typically uses the `SpiSlaveDevice` trait, -/// which is provided by a virtualizing/multiplexing layer. +/// (master). +/// +/// This is a low-level trait typically implemented by hardware: higher level +/// software typically uses the [`SpiSlaveDevice`] trait, which is provided by a +/// virtualizing/multiplexing layer. pub trait SpiSlave<'a> { /// Initialize the SPI device to be in peripheral mode. - /// Return values: - /// - Ok(()): the device is in peripheral mode - /// - Err(BUSY): the device is busy with an operation and cannot - /// be initialized - /// - Err(FAIL): other failure condition + /// + /// ### Return values + /// + /// - `Ok(())`: the device is in peripheral mode + /// - `Err(BUSY)`: the device is busy with an operation and cannot be + /// initialized + /// - `Err(FAIL)`: other failure condition fn init(&self) -> Result<(), ErrorCode>; - /// Returns true if there is a client. Useful for verifying that - /// two software drivers do not both try to take control of the - /// device. + /// Returns true if there is a client. Useful for verifying that two + /// software drivers do not both try to take control of the device. fn has_client(&self) -> bool; - /// Set the callback for slave operations, passing `None` to - /// disable peripheral mode. + /// Set the callback for slave operations, passing `None` to disable + /// peripheral mode. fn set_client(&self, client: Option<&'a dyn SpiSlaveClient>); - /// Set a single byte to write in response to a read/write - /// operation from a controller. Useful for devices that always - /// send a status code in their first byte. + /// Set a single byte to write in response to a read/write operation from a + /// controller. Useful for devices that always send a status code in their + /// first byte. fn set_write_byte(&self, write_byte: u8); - /// Provide buffers for the peripheral to write from and read - /// into when a controller performs a `read_write_bytes` operation. + /// Provide buffers for the peripheral to write from and read into when a + /// controller performs a `read_write_bytes` operation. + /// /// The device will issue a callback when one of four things occurs: - /// - The controller completes the operation by bringing the chip - /// select high. - /// - A `Some` write buffer is written. - /// - A `Some` read buffer is filled. - /// - `len` bytes are read/written - /// Return values: - /// - Ok(()): the SPI bus will read/write the provided buffers on - /// the next SPI operation requested by the controller. - /// - Err(BUSY): the device is busy with an existing - /// `read_write_bytes` operation. - /// - Err(INVAL): the `len` parameter is 0 + /// + /// - The controller completes the operation by bringing the chip select + /// high. + /// - A `Some` write buffer is written. + /// - A `Some` read buffer is filled. + /// - `len` bytes are read/written + /// + /// ### Return values + /// + /// - `Ok(())`: the SPI bus will read/write the provided buffers on the next + /// SPI operation requested by the controller. + /// - `Err(BUSY)`: the device is busy with an existing `read_write_bytes` + /// operation. + /// - `Err(INVAL)`: the `len` parameter is 0 /// /// `Err` return values return the passed buffer `Option`s. fn read_write_bytes( @@ -527,54 +552,47 @@ pub trait SpiSlave<'a> { Option<&'static mut [u8]>, ), >; - /// Set the bus polarity (whether idle is high or low). Return values: - /// - Ok(()): the polarity was set. - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + + /// Set the bus polarity (whether idle is high or low). + /// + /// ### Return values + /// + /// - `Ok(())`: the polarity was set. + /// - `Err(BUSY)`: the SPI bus is busy with a [`SpiSlave::read_write_bytes`] + /// operation whose callback hasn't been called yet. + /// - `Err(FAIL)`: other failure fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode>; + /// Return the current bus polarity. fn get_polarity(&self) -> ClockPolarity; /// Set the bus phase (whether data is sent/received on leading or /// trailing edges). - /// - Ok(()): the phase was set. - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// + /// ### Return values + /// + /// - `Ok(())`: the phase was set. + /// - `Err(BUSY)`: the SPI bus is busy with a [`SpiSlave::read_write_bytes`] + /// operation whose callback hasn't been called yet. + /// - `Err(FAIL)`: other failure fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode>; /// Return the current bus phase. fn get_phase(&self) -> ClockPhase; } -/// SPISlaveDevice is an interface to a SPI bus in peripheral mode. -/// It is the standard trait used by services within the kernel: -/// `SpiSlave` is for lower-level access responsible for initializing -/// hardware. +/// An interface to a SPI bus in peripheral mode. +/// +/// It is the standard trait used by services within the kernel: [`SpiSlave`] is +/// for lower-level access responsible for initializing hardware. pub trait SpiSlaveDevice<'a> { - /// Specify the callback of `read_write_bytes` operations: + /// Specify the callback of [`SpiSlaveDevice::read_write_bytes`] operations. fn set_client(&self, client: &'a dyn SpiSlaveClient); /// Setup the SPI settings and speed of the bus. fn configure(&self, cpol: ClockPolarity, cpal: ClockPhase) -> Result<(), ErrorCode>; - /// Provide buffers for the peripheral to write from and read - /// into when a controller performs a `read_write_bytes` operation. - /// The device will issue a callback when one of four things occurs: - /// - The controller completes the operation by bringing the chip - /// select high. - /// - A `Some` write buffer is written. - /// - A `Some` read buffer is filled. - /// - `len` bytes are read/written - /// Return values: - /// - Ok(()): the SPI bus will read/write the provided buffers on - /// the next SPI operation requested by the controller. - /// - Err(BUSY): the device is busy with an existing - /// `read_write_bytes` operation. - /// - Err(INVAL): the `len` parameter is 0 - /// - /// `Err` return values return the passed buffer `Option`s. + /// Same as [`SpiSlave::read_write_bytes`]. fn read_write_bytes( &self, write_buffer: Option<&'static mut [u8]>, @@ -588,21 +606,14 @@ pub trait SpiSlaveDevice<'a> { Option<&'static mut [u8]>, ), >; - /// Set the bus polarity (whether idle is high or low). Return values: - /// - Ok(()): the polarity was set. - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + + /// Same as [`SpiSlave::set_polarity`]. fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode>; + /// Return the current bus polarity. fn get_polarity(&self) -> ClockPolarity; - /// Set the bus phase (whether data is sent/received on leading or - /// trailing edges). - /// - Ok(()): the phase was set. - /// - Err(BUSY): the SPI bus is busy with a `read_write_bytes` - /// operation whose callback hasn't been called yet. - /// - Err(FAIL): other failure + /// Same as [`SpiSlave::set_phase`]. fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode>; /// Return the current bus phase.