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}