kernel/hil/
spi.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Interfaces for SPI controller (master) and peripheral (slave) communication.
6//!
7//! We use the terms master/slave in some situations because the term peripheral
8//! can also refer to a hardware peripheral (e.g., memory-mapped I/O devices in
9//! ARM are called peripherals).
10
11// Author: Alexandru Radovici <msg4alex@gmail.com>
12// Author: Philip Levis <pal@cs.stanford.edu>
13// Author: Hubert Teo <hubert.teo.hk@gmail.com>
14// Author: Brad Campbell <bradjc5@gmail.com>
15// Author: Amit Aryeh Levy <amit@amitlevy.com>
16
17use crate::{utilities::leasable_buffer::SubSliceMut, ErrorCode};
18
19/// Data order defines the order of bits sent over the wire: most significant
20/// first, or least significant first.
21#[derive(Copy, Clone, Debug)]
22pub enum DataOrder {
23    /// Send the most significant byte first.
24    MSBFirst,
25    /// Send the least significant byte first.
26    LSBFirst,
27}
28
29/// Clock polarity (CPOL) defines whether the SPI clock is high or low when
30/// idle.
31#[derive(Copy, Clone, Debug, PartialEq)]
32pub enum ClockPolarity {
33    /// The clock is low when the SPI bus is not active. This is CPOL = 0.
34    IdleLow,
35    /// The clock is high when the SPI bus is not active. This is CPOL = 1.
36    IdleHigh,
37}
38
39/// Clock phase (CPHA) defines whether to sample and send data on a leading or
40/// trailing clock edge.
41///
42/// Consult a SPI reference on how CPHA interacts with CPOL.
43#[derive(Copy, Clone, Debug, PartialEq)]
44pub enum ClockPhase {
45    /// Sample on the leading clock edge. This is CPHA = 0. If CPOL is 0, then
46    /// this samples on the rising edge of the clock. If CPOL is 1, then this
47    /// samples on the falling edge of the clock.
48    SampleLeading,
49    /// Sample on the trailing clock edge. This is CPHA = 1. If CPOL is 0, then
50    /// this samples on the falling edge of the clock. If CPOL is 1, then this
51    /// samples on the rising edge of the clock.
52    SampleTrailing,
53}
54
55/// Utility types for modeling chip select pins in a [`SpiMaster`]
56/// implementation.
57pub mod cs {
58
59    /// Represents the Polarity of a chip-select pin (i.e. whether high or low
60    /// indicates the peripheral is active).
61    #[derive(Copy, Clone)]
62    pub enum Polarity {
63        /// Chip select is active high.
64        High,
65        /// Chip select is active low.
66        Low,
67    }
68
69    mod private {
70        pub trait Sealed {}
71    }
72
73    /// Marker trait indicating whether a peripheral requires active high or low
74    /// polarity as well as whether a [`SpiMaster`](super::SpiMaster)
75    /// implementation can support either or both polarities.
76    ///
77    /// This trait is sealed and only implemented for [`ActiveLow`] and
78    /// [`ActiveHigh`].
79    pub trait ChipSelectActivePolarity: private::Sealed {
80        const POLARITY: Polarity;
81    }
82
83    /// Marks a peripheral as requiring or controller as supporting active low
84    /// chip select pins.
85    pub enum ActiveLow {}
86    /// Marks a peripheral as requiring or controller as supporting active high
87    /// chip select pins.
88    pub enum ActiveHigh {}
89
90    impl private::Sealed for ActiveLow {}
91    impl private::Sealed for ActiveHigh {}
92
93    impl ChipSelectActivePolarity for ActiveLow {
94        const POLARITY: Polarity = Polarity::Low;
95    }
96
97    impl ChipSelectActivePolarity for ActiveHigh {
98        const POLARITY: Polarity = Polarity::High;
99    }
100
101    /// A type that can be converted to the appropriate type for
102    /// [`SpiMaster::ChipSelect`](super::SpiMaster::ChipSelect) for a particular
103    /// `POLARITY`.
104    ///
105    /// Instantiating a driver for any SPI peripheral should require a type that
106    /// implements [`IntoChipSelect`]. That enforces that whatever object is
107    /// used as the chip select can support the correct polarity for the
108    /// particular SPI peripheral. This is mostly commonly handled by the
109    /// component for the peripheral, which requires an object with type
110    /// [`IntoChipSelect`] and then converts the object to the
111    /// [`SpiMaster::ChipSelect`](super::SpiMaster::ChipSelect) type.
112    ///
113    /// # Examples:
114    ///
115    /// Some SPI host controllers only support active low or active high chip
116    /// select pins. Such a controller might provide a unit implementation of
117    /// this trait _only_ for the [`ActiveLow`] marker.
118    ///
119    /// ```rust
120    /// use kernel::hil::spi::cs::*;
121    ///
122    /// #[derive(Copy, Clone)]
123    /// enum PeripheralSelect {
124    ///     Peripheral0,
125    ///     Peripheral1,
126    /// }
127    ///
128    /// impl IntoChipSelect<PeripheralSelect, ActiveLow> for PeripheralSelect {
129    ///     fn into_cs(self) -> Self { self }
130    /// }
131    /// ```
132    ///
133    /// Many other controllers can handle both active low and active high chip
134    /// select pins, in which case, they should implement both the [`ActiveLow`]
135    /// and [`ActiveHigh`] variants, for example, using the [`ChipSelectPolar`]
136    /// wrapper struct (which implements both).
137    pub trait IntoChipSelect<T, POLARITY> {
138        fn into_cs(self) -> T;
139    }
140
141    /// A convenience wrapper type around [`Output`](crate::hil::gpio::Output)
142    /// GPIO pins that implements [`IntoChipSelect`] for both [`ActiveLow`] and
143    /// [`ActiveHigh`].
144    pub struct ChipSelectPolar<'a, P: crate::hil::gpio::Output> {
145        /// The underlying chip select "pin".
146        pub pin: &'a P,
147        /// The polarity from which this wrapper was derived using
148        /// [`IntoChipSelect`].
149        pub polarity: Polarity,
150    }
151
152    impl<P: crate::hil::gpio::Output> Clone for ChipSelectPolar<'_, P> {
153        fn clone(&self) -> Self {
154            *self
155        }
156    }
157
158    impl<P: crate::hil::gpio::Output> Copy for ChipSelectPolar<'_, P> {}
159
160    impl<'a, P: crate::hil::gpio::Output, A: ChipSelectActivePolarity>
161        IntoChipSelect<ChipSelectPolar<'a, P>, A> for &'a P
162    {
163        fn into_cs(self) -> ChipSelectPolar<'a, P> {
164            ChipSelectPolar {
165                pin: self,
166                polarity: A::POLARITY,
167            }
168        }
169    }
170
171    /// When wrapping a GPIO pin that implements
172    /// [`gpio::Output`](crate::hil::gpio::Output), users can use the
173    /// [`activate`](ChipSelectPolar::activate) and
174    /// [`deactivate`](ChipSelectPolar::deactivate) methods to automatically set
175    /// or clear the chip select pin based on the stored polarity.
176    impl<P: crate::hil::gpio::Output> ChipSelectPolar<'_, P> {
177        /// Deactivate the chip select pin.
178        ///
179        /// High if active low, low if active high.
180        pub fn deactivate(&self) {
181            match self.polarity {
182                Polarity::Low => self.pin.set(),
183                Polarity::High => self.pin.clear(),
184            }
185        }
186
187        /// Active the chip select pin.
188        ///
189        /// Low if active low, high if active high.
190        pub fn activate(&self) {
191            match self.polarity {
192                Polarity::Low => self.pin.clear(),
193                Polarity::High => self.pin.set(),
194            }
195        }
196    }
197}
198
199/// Trait for clients of a SPI bus in master mode.
200pub trait SpiMasterClient {
201    /// Callback issued when a read/write operation finishes.
202    ///
203    /// `write_buffer` and `read_buffer` always contain the buffers
204    /// passed to the [SpiMaster::read_write_bytes]
205    /// down-call, with `read_buffer` as an `Option` because the
206    /// down-call passes an `Option`. The contents of `write_buffer`
207    /// is unmodified, while `read_buffer` contains the bytes read
208    /// over SPI. Each buffer's bounds are unmodified from their state
209    /// when `read_write_bytes` is called.
210    ///
211    /// `status` signals if the operation was successful, and if so,
212    /// the length of the operation, or an appropriate `ErrorCode`.
213    fn read_write_done(
214        &self,
215        write_buffer: SubSliceMut<'static, u8>,
216        read_buffer: Option<SubSliceMut<'static, u8>>,
217        status: Result<usize, ErrorCode>,
218    );
219}
220/// Trait for interacting with SPI peripheral devices at a byte or buffer level.
221///
222/// Using [`SpiMaster`] normally involves three steps:
223///
224/// 1. Configure the SPI bus for a peripheral.
225///
226///    1. Call [`SpiMaster::specify_chip_select`] to select which peripheral and
227///       turn on SPI.
228///
229///    2. Call set operations as needed to configure the bus. **NOTE**: You MUST
230///       select the chip select BEFORE configuring SPI settings.
231///
232/// 2. Invoke [`SpiMaster::read_write_bytes`] on [`SpiMaster`].
233///
234/// 3. Go back to step 2 to complete another transaction, or call
235///    [`SpiMaster::specify_chip_select`] to choose another peripheral and go to
236///    step 1.2 or 2.
237///
238/// The SPI configuration for a particular peripheral persists across changes to
239/// the chip select. For example, this set of calls:
240///
241/// ```rust,ignore
242/// SpiMaster::specify_chip_select(1);
243/// SpiMaster::set_phase(ClockPhase::SampleLeading);
244/// SpiMaster::specify_chip_select(2);
245/// SpiMaster::set_phase(ClockPhase::SampleTrailing);
246/// SpiMaster::specify_chip_select(1);
247/// SpiMaster::write_byte(0); // Uses SampleLeading
248/// ```
249///
250/// will have a [`ClockPhase::SampleLeading`] phase in the final
251/// [`SpiMaster::write_byte`] call, because the configuration of chip select 1
252/// is saved, and restored when chip select is set back to 1.
253///
254/// If additional chip selects are needed, they can be performed with GPIO and
255/// manual re-initialization of settings. Note that a SPI chip select (CS) line
256/// is usually active low.
257///
258/// ```rust,ignore
259/// specify_chip_select(0);
260/// set_phase(ClockPhase::SampleLeading);
261/// pin_a.clear(); // Select A
262/// write_byte(0xaa); // Uses SampleLeading
263/// pin_a.set(); // Unselect A
264/// set_phase(ClockPhase::SampleTrailing);
265/// pin_b.clear(); // Select B
266/// write_byte(0xaa); // Uses SampleTrailing
267/// ```
268pub trait SpiMaster<'a> {
269    /// Chip select is an associated type because different SPI buses may have
270    /// different numbers of chip selects. This allows peripheral
271    /// implementations to define their own type.
272    type ChipSelect: Copy;
273
274    /// Initialize this SPI interface. Call this once before invoking any other
275    /// operations.
276    ///
277    /// ### Return values
278    ///
279    /// - `Ok(())`: initialized correctly
280    /// - `Err(OFF)`: not currently powered so can't be initialized
281    /// - `Err(RESERVE)`: no clock is configured yet
282    /// - `Err(FAIL)`: other failure condition
283    fn init(&self) -> Result<(), ErrorCode>;
284
285    /// Change the callback handler for [`SpiMaster::read_write_bytes`] calls.
286    fn set_client(&self, client: &'a dyn SpiMasterClient);
287
288    /// Return whether the SPI peripheral is busy with a
289    /// [`SpiMaster::read_write_bytes`] operation.
290    fn is_busy(&self) -> bool;
291
292    /// Perform an asynchronous read/write operation, whose completion is
293    /// signaled by invoking [`SpiMasterClient`] on the client. Write-only
294    /// operations may pass `None` for `read_buffer`, while read-write
295    /// operations pass `Some` for `read_buffer`.
296    ///
297    /// If `read_buffer` is `None`, the number of bytes written will
298    /// be the the length of `write_buffer`. If `read_buffer` is
299    /// `Some`, the number of bytes read/written will be the minimum
300    /// of the length of `write_buffer` and the length of
301    /// `read_buffer`.
302    ///
303    /// ### Return values
304    ///
305    /// If `read_write_bytes` returns `Ok(())`, the operation will be
306    /// attempted and a callback will be called. If it returns `Err`,
307    /// no callback will be called and the buffers are returned.
308    /// - `Ok(())`: the operation will be attempted and the callback will be
309    ///   called.
310    /// - `Err(OFF)`: the SPI bus is powered down.
311    /// - `Err(INVAL)`: length is 0
312    /// - `Err(BUSY)`: the SPI bus is busy with a prior
313    ///   [`SpiMaster::read_write_bytes`] operation whose callback hasn't been
314    ///   called yet.
315    fn read_write_bytes(
316        &self,
317        write_buffer: SubSliceMut<'static, u8>,
318        read_buffer: Option<SubSliceMut<'static, u8>>,
319    ) -> Result<
320        (),
321        (
322            ErrorCode,
323            SubSliceMut<'static, u8>,
324            Option<SubSliceMut<'static, u8>>,
325        ),
326    >;
327
328    /// Synchronously write a single byte on the bus. Not for general use
329    /// because it is blocking: intended for debugging.
330    ///
331    /// ### Return values
332    ///
333    /// - `Ok(())`: the byte was written
334    /// - `Err(OFF)`: the SPI bus is powered down
335    /// - `Err(BUSY)`: the SPI bus is busy with a
336    ///   [`SpiMaster::read_write_bytes`] operation whose callback hasn't been
337    ///   called yet.
338    /// - `Err(FAIL)`: other failure
339    fn write_byte(&self, val: u8) -> Result<(), ErrorCode>;
340
341    /// Synchronously write a 0 and read a single byte from the bus. Not for
342    /// general use because it is blocking: intended for debugging.
343    ///
344    /// ### Return values
345    ///
346    /// - `Ok(u8)`: the read byte
347    /// - `Err(OFF)`: the SPI bus is powered down
348    /// - `Err(BUSY)`: the SPI bus is busy with a
349    ///   [`SpiMaster::read_write_bytes`] operation whose callback hasn't been
350    ///   called yet.
351    /// - `Err(FAIL)`: other failure
352    fn read_byte(&self) -> Result<u8, ErrorCode>;
353
354    /// Synchronously write and read a single byte. Not for general use because
355    /// it is blocking: intended for debugging.
356    ///
357    /// ### Return values
358    ///
359    /// - `Ok(u8)`: the read byte
360    /// - `Err(OFF)`: the SPI bus is powered down
361    /// - `Err(BUSY)`: the SPI bus is busy with a
362    ///   [`SpiMaster::read_write_bytes`] operation whose callback hasn't been
363    ///   called yet.
364    /// - `Err(FAIL)`: other failure
365    fn read_write_byte(&self, val: u8) -> Result<u8, ErrorCode>;
366
367    /// Specify which chip select to use. Configuration settings (rate,
368    /// polarity, phase) are chip-select specific and are stored for that chip
369    /// select.
370    fn specify_chip_select(&self, cs: Self::ChipSelect) -> Result<(), ErrorCode>;
371
372    /// Set the clock/data rate for the current chip select.
373    ///
374    /// ### Return values
375    ///
376    /// - `Ok(u32)`: the actual data rate set (limited by clock precision)
377    /// - `Err(INVAL)`: a rate outside the bounds of the bus was passed
378    /// - `Err(BUSY)`: the SPI bus is busy with a
379    ///   [`SpiMaster::read_write_bytes`] operation whose callback hasn't been
380    ///   called yet.
381    /// - `Err(FAIL)`: other failure
382    fn set_rate(&self, rate: u32) -> Result<u32, ErrorCode>;
383
384    /// Return the current chip select's clock rate.
385    fn get_rate(&self) -> u32;
386
387    /// Set the bus polarity (whether idle is high or low) for the
388    /// current chip select.
389    ///
390    /// ### Return values
391    ///
392    /// - `Ok(())`: the polarity was set.
393    /// - `Err(BUSY)`: the SPI bus is busy with a
394    ///   [`SpiMaster::read_write_bytes`] operation whose callback hasn't been
395    ///   called yet.
396    /// - `Err(FAIL)`: other failure
397    fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode>;
398
399    /// Return the current bus polarity.
400    fn get_polarity(&self) -> ClockPolarity;
401
402    /// Set the bus phase for the current chip select (whether data is
403    /// sent/received on leading or trailing edges).
404    ///
405    /// ### Return values
406    ///
407    /// - `Ok(())`: the phase was set.
408    /// - `Err(BUSY)`: the SPI bus is busy with a
409    ///   [`SpiMaster::read_write_bytes`] operation whose callback hasn't been
410    ///   called yet.
411    /// - `Err(FAIL)`: other failure
412    fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode>;
413
414    /// Get the current bus phase for the current chip select.
415    fn get_phase(&self) -> ClockPhase;
416
417    // These two functions determine what happens to the chip select line
418    // between transfers. If hold_low() is called, then the chip select line is
419    // held low after transfers complete. If release_low() is called, then the
420    // chip select line is brought high after a transfer completes. A "transfer"
421    // is any of the read/read_write calls. These functions allow an application
422    // to manually control when the CS line is high or low, such that it can
423    // issue longer read/writes with multiple read_write_bytes calls.
424
425    /// Hold the chip select line low after a [`SpiMaster::read_write_bytes`]
426    /// completes. This allows a client to make one long SPI read/write with
427    /// multiple calls to `read_write_bytes`.
428    fn hold_low(&self);
429
430    /// Raise the chip select line after a [`SpiMaster::read_write_bytes`]
431    /// completes. This will complete the SPI operation.
432    fn release_low(&self);
433}
434
435/// A chip-select-specific interface to the SPI Controller hardware, such that a
436/// client cannot change the chip select line.
437///
438/// This restricts the SPI peripherals the client can access to a specific
439/// peripheral.
440pub trait SpiMasterDevice<'a> {
441    /// Set the callback for read_write operations.
442    fn set_client(&self, client: &'a dyn SpiMasterClient);
443
444    /// Configure the bus for this chip select.
445    fn configure(&self, cpol: ClockPolarity, cpal: ClockPhase, rate: u32) -> Result<(), ErrorCode>;
446
447    /// Same as [`SpiMaster::read_write_bytes`].
448    fn read_write_bytes(
449        &self,
450        write_buffer: SubSliceMut<'static, u8>,
451        read_buffer: Option<SubSliceMut<'static, u8>>,
452    ) -> Result<
453        (),
454        (
455            ErrorCode,
456            SubSliceMut<'static, u8>,
457            Option<SubSliceMut<'static, u8>>,
458        ),
459    >;
460
461    /// Same as [`SpiMaster::set_rate`].
462    fn set_rate(&self, rate: u32) -> Result<(), ErrorCode>;
463
464    /// Return the current chip select's clock rate.
465    fn get_rate(&self) -> u32;
466
467    /// Same as [`SpiMaster::set_polarity`].
468    fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode>;
469
470    /// Return the current bus polarity.
471    fn get_polarity(&self) -> ClockPolarity;
472
473    /// Same as [`SpiMaster::set_phase`].
474    fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode>;
475
476    /// Get the current bus phase for the current chip select.
477    fn get_phase(&self) -> ClockPhase;
478}
479
480/// Trait for SPI peripherals (slaves) to receive callbacks when the
481/// corresponding controller (master) issues operations.
482///
483/// A SPI operation begins with a callback of [`SpiSlaveClient::chip_selected`].
484/// If the client has provided buffers with [`SpiSlave::read_write_bytes`],
485/// these buffers are written from and read into until the operation completes
486/// or one of them fills, at which point a [`SpiSlaveClient::read_write_done`]
487/// callback is called. If the client needs to read/write more it can call
488/// [`SpiSlave::read_write_bytes`] again.
489///
490/// Note that there is no notification when the chip select line goes high.
491pub trait SpiSlaveClient {
492    /// Notification that the chip select has been brought low.
493    fn chip_selected(&self);
494
495    /// Callback issued when the controller completes an SPI operation to this
496    /// peripheral.
497    ///
498    /// `write_buffer` and `read_buffer` are the values passed in the previous
499    /// call to [`SpiSlave::read_write_bytes`]. The `len` parameter specifies
500    /// how many bytes were written from/read into `Some` values of these
501    /// buffers. `len` may be shorter than the size of these buffers if the
502    /// operation did not fill them.
503    fn read_write_done(
504        &self,
505        write_buffer: Option<&'static mut [u8]>,
506        read_buffer: Option<&'static mut [u8]>,
507        len: usize,
508        status: Result<(), ErrorCode>,
509    );
510}
511
512/// Trait for SPI peripherals (slaves) to exchange data with a contoller
513/// (master).
514///
515/// This is a low-level trait typically implemented by hardware: higher level
516/// software typically uses the [`SpiSlaveDevice`] trait, which is provided by a
517/// virtualizing/multiplexing layer.
518pub trait SpiSlave<'a> {
519    /// Initialize the SPI device to be in peripheral mode.
520    ///
521    /// ### Return values
522    ///
523    /// - `Ok(())`: the device is in peripheral mode
524    /// - `Err(BUSY)`: the device is busy with an operation and cannot be
525    ///   initialized
526    /// - `Err(FAIL)`: other failure condition
527    fn init(&self) -> Result<(), ErrorCode>;
528
529    /// Returns true if there is a client. Useful for verifying that two
530    /// software drivers do not both try to take control of the device.
531    fn has_client(&self) -> bool;
532
533    /// Set the callback for slave operations, passing `None` to disable
534    /// peripheral mode.
535    fn set_client(&self, client: Option<&'a dyn SpiSlaveClient>);
536
537    /// Set a single byte to write in response to a read/write operation from a
538    /// controller. Useful for devices that always send a status code in their
539    /// first byte.
540    fn set_write_byte(&self, write_byte: u8);
541
542    /// Provide buffers for the peripheral to write from and read into when a
543    /// controller performs a `read_write_bytes` operation.
544    ///
545    /// The device will issue a callback when one of four things occurs:
546    ///
547    /// - The controller completes the operation by bringing the chip select
548    ///   high.
549    /// - A `Some` write buffer is written.
550    /// - A `Some` read buffer is filled.
551    /// - `len` bytes are read/written
552    ///
553    /// ### Return values
554    ///
555    /// - `Ok(())`: the SPI bus will read/write the provided buffers on the next
556    ///   SPI operation requested by the controller.
557    /// - `Err(BUSY)`: the device is busy with an existing `read_write_bytes`
558    ///   operation.
559    /// - `Err(INVAL)`: the `len` parameter is 0
560    ///
561    /// `Err` return values return the passed buffer `Option`s.
562    fn read_write_bytes(
563        &self,
564        write_buffer: Option<&'static mut [u8]>,
565        read_buffer: Option<&'static mut [u8]>,
566        len: usize,
567    ) -> Result<
568        (),
569        (
570            ErrorCode,
571            Option<&'static mut [u8]>,
572            Option<&'static mut [u8]>,
573        ),
574    >;
575
576    /// Set the bus polarity (whether idle is high or low).
577    ///
578    /// ### Return values
579    ///
580    /// - `Ok(())`: the polarity was set.
581    /// - `Err(BUSY)`: the SPI bus is busy with a [`SpiSlave::read_write_bytes`]
582    ///   operation whose callback hasn't been called yet.
583    /// - `Err(FAIL)`: other failure
584    fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode>;
585
586    /// Return the current bus polarity.
587    fn get_polarity(&self) -> ClockPolarity;
588
589    /// Set the bus phase (whether data is sent/received on leading or
590    /// trailing edges).
591    ///
592    /// ### Return values
593    ///
594    /// - `Ok(())`: the phase was set.
595    /// - `Err(BUSY)`: the SPI bus is busy with a [`SpiSlave::read_write_bytes`]
596    ///   operation whose callback hasn't been called yet.
597    /// - `Err(FAIL)`: other failure
598    fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode>;
599
600    /// Return the current bus phase.
601    fn get_phase(&self) -> ClockPhase;
602}
603
604/// An interface to a SPI bus in peripheral mode.
605///
606/// It is the standard trait used by services within the kernel: [`SpiSlave`] is
607/// for lower-level access responsible for initializing hardware.
608pub trait SpiSlaveDevice<'a> {
609    /// Specify the callback of [`SpiSlaveDevice::read_write_bytes`] operations.
610    fn set_client(&self, client: &'a dyn SpiSlaveClient);
611
612    /// Setup the SPI settings and speed of the bus.
613    fn configure(&self, cpol: ClockPolarity, cpal: ClockPhase) -> Result<(), ErrorCode>;
614
615    /// Same as [`SpiSlave::read_write_bytes`].
616    fn read_write_bytes(
617        &self,
618        write_buffer: Option<&'static mut [u8]>,
619        read_buffer: Option<&'static mut [u8]>,
620        len: usize,
621    ) -> Result<
622        (),
623        (
624            ErrorCode,
625            Option<&'static mut [u8]>,
626            Option<&'static mut [u8]>,
627        ),
628    >;
629
630    /// Same as [`SpiSlave::set_polarity`].
631    fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode>;
632
633    /// Return the current bus polarity.
634    fn get_polarity(&self) -> ClockPolarity;
635
636    /// Same as [`SpiSlave::set_phase`].
637    fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode>;
638
639    /// Return the current bus phase.
640    fn get_phase(&self) -> ClockPhase;
641}