@@ -9,35 +9,118 @@ use std::io;
9
9
use std:: ops;
10
10
use std:: path:: Path ;
11
11
12
- /// Newtype around [`spidev:: Spidev`] that implements the ` embedded-hal` traits
12
+ /// Spidev wrapper providing the embedded-hal [`SpiDevice`] trait.
13
13
///
14
- /// [Delay operations][delay] are capped to 65535 microseconds.
14
+ /// Use this struct when you want a single spidev device, using a Linux-managed CS pin,
15
+ /// which is already defined in your devicetree. Linux will handle sharing the bus
16
+ /// between different SPI devices, even between different processes.
15
17
///
16
- /// [`spidev::Spidev`]: https://docs.rs/spidev/0.5.2/spidev/struct.Spidev.html
17
- /// [delay]: embedded_hal::spi::Operation::DelayUs
18
- pub struct Spidev ( pub spidev:: Spidev ) ;
18
+ /// You get an object that implements [`SpiDevice`], which is what most drivers require,
19
+ /// but does not implement [`SpiBus`]. In some rare cases, you may require [`SpiBus`]
20
+ /// instead; for that refer to [`SpidevBus`] below. You may also want to use [`SpiBus`]
21
+ /// if you want to handle all the CS pins yourself using GPIO.
22
+ ///
23
+ /// This struct wraps a [`spidev::Spidev`] struct, so it can be constructed directly
24
+ /// and the inner struct accessed if needed, for example to (re)configure the SPI settings.
25
+ ///
26
+ /// Note that [delay operations] on this device are capped to 65535 microseconds.
27
+ ///
28
+ /// [`SpiDevice`]: embedded_hal::spi::SpiDevice
29
+ /// [`SpiBus`]: embedded_hal::spi::SpiBus
30
+ /// [`spidev::Spidev`]: spidev::Spidev
31
+ /// [delay operations]: embedded_hal::spi::Operation::DelayUs
32
+ pub struct SpidevDevice ( pub spidev:: Spidev ) ;
33
+
34
+ /// Spidev wrapper providing the embedded-hal [`SpiBus`] trait.
35
+ ///
36
+ /// Use this struct when you require direct access to the underlying SPI bus, for
37
+ /// example when you want to use GPIOs as software-controlled CS pins to share the
38
+ /// bus with multiple devices, or because a driver requires the entire bus (for
39
+ /// example to drive smart LEDs).
40
+ ///
41
+ /// Do not use this struct if you're accessing SPI devices that already appear in your
42
+ /// device tree; you will not be able to drive CS pins that are already used by spidev
43
+ /// as GPIOs. Instead use [`SpidevDevice`].
44
+ ///
45
+ /// This struct must still be created from a [`spidev::Spidev`] device, but there are two
46
+ /// important notes:
47
+ ///
48
+ /// 1. The CS pin associated with this spidev device will be driven whenever any device accesses
49
+ /// this bus, so it should be an unconnected or unused pin.
50
+ /// 2. No other spidev device on the same bus may be used as long as this `SpidevBus` exists,
51
+ /// as Linux will _not_ do anything to ensure this bus has exclusive access.
52
+ ///
53
+ /// It is recommended to use a dummy spidev device associated with an unused CS pin, and then use
54
+ /// regular GPIOs as CS pins if required. If you are planning to share this bus using GPIOs, the
55
+ /// [`embedded-hal-bus`] crate may be of interest.
56
+ ///
57
+ /// If necessary, you can [configure] the underlying [`spidev::Spidev`] instance with the
58
+ /// [`SPI_NO_CS`] flag set to prevent any CS pin activity.
59
+ ///
60
+ /// [`SpiDevice`]: embedded_hal::spi::SpiDevice
61
+ /// [`SpiBus`]: embedded_hal::spi::SpiBus
62
+ /// [`embedded-hal-bus`]: https://docs.rs/embedded-hal-bus/
63
+ /// [`spidev::Spidev`]: spidev::Spidev
64
+ /// [delay operations]: embedded_hal::spi::Operation::DelayUs
65
+ /// [configure]: spidev::Spidev::configure
66
+ /// [`SPI_NO_CS`]: spidev::SpiModeFlags::SPI_NO_CS
67
+ pub struct SpidevBus ( pub spidev:: Spidev ) ;
68
+
69
+ impl SpidevDevice {
70
+ /// See [`spidev::Spidev::open`] for details.
71
+ ///
72
+ /// The provided `path` is for the specific device you wish to access.
73
+ /// Access to the bus is shared with other devices via the Linux kernel.
74
+ pub fn open < P > ( path : P ) -> Result < Self , SPIError >
75
+ where
76
+ P : AsRef < Path > ,
77
+ {
78
+ spidev:: Spidev :: open ( path)
79
+ . map ( SpidevDevice )
80
+ . map_err ( |e| e. into ( ) )
81
+ }
82
+ }
19
83
20
- impl Spidev {
21
- /// See [`spidev::Spidev::open`][0] for details.
84
+ impl SpidevBus {
85
+ /// See [`spidev::Spidev::open`] for details.
22
86
///
23
- /// [0]: https://docs.rs/spidev/0.5.2/spidev/struct.Spidev.html#method.open
87
+ /// The provided `path` must be the _only_ device in use on its bus,
88
+ /// and note its own CS pin will be asserted for all device access,
89
+ /// so the path should be to a dummy device used only to access
90
+ /// the underlying bus.
24
91
pub fn open < P > ( path : P ) -> Result < Self , SPIError >
25
92
where
26
93
P : AsRef < Path > ,
27
94
{
28
- spidev:: Spidev :: open ( path) . map ( Spidev ) . map_err ( |e| e. into ( ) )
95
+ spidev:: Spidev :: open ( path)
96
+ . map ( SpidevBus )
97
+ . map_err ( |e| e. into ( ) )
29
98
}
30
99
}
31
100
32
- impl ops:: Deref for Spidev {
101
+ impl ops:: Deref for SpidevDevice {
33
102
type Target = spidev:: Spidev ;
34
103
35
104
fn deref ( & self ) -> & Self :: Target {
36
105
& self . 0
37
106
}
38
107
}
39
108
40
- impl ops:: DerefMut for Spidev {
109
+ impl ops:: DerefMut for SpidevDevice {
110
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
111
+ & mut self . 0
112
+ }
113
+ }
114
+
115
+ impl ops:: Deref for SpidevBus {
116
+ type Target = spidev:: Spidev ;
117
+
118
+ fn deref ( & self ) -> & Self :: Target {
119
+ & self . 0
120
+ }
121
+ }
122
+
123
+ impl ops:: DerefMut for SpidevBus {
41
124
fn deref_mut ( & mut self ) -> & mut Self :: Target {
42
125
& mut self . 0
43
126
}
@@ -51,11 +134,15 @@ mod embedded_hal_impl {
51
134
use std:: convert:: TryInto ;
52
135
use std:: io:: { Read , Write } ;
53
136
54
- impl ErrorType for Spidev {
137
+ impl ErrorType for SpidevDevice {
138
+ type Error = SPIError ;
139
+ }
140
+
141
+ impl ErrorType for SpidevBus {
55
142
type Error = SPIError ;
56
143
}
57
144
58
- impl SpiBus < u8 > for Spidev {
145
+ impl SpiBus < u8 > for SpidevBus {
59
146
fn read ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
60
147
self . 0 . read_exact ( words) . map_err ( |err| SPIError { err } )
61
148
}
@@ -97,7 +184,7 @@ mod embedded_hal_impl {
97
184
}
98
185
}
99
186
100
- impl SpiDevice for Spidev {
187
+ impl SpiDevice for SpidevDevice {
101
188
/// Perform a transaction against the device. [Read more][transaction]
102
189
///
103
190
/// [Delay operations][delay] are capped to 65535 microseconds.
0 commit comments