@@ -9,35 +9,114 @@ 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) . map ( SpidevDevice ) . map_err ( |e| e. into ( ) )
79
+ }
80
+ }
19
81
20
- impl Spidev {
21
- /// See [`spidev::Spidev::open`][0] for details.
82
+ impl SpidevBus {
83
+ /// See [`spidev::Spidev::open`] for details.
22
84
///
23
- /// [0]: https://docs.rs/spidev/0.5.2/spidev/struct.Spidev.html#method.open
85
+ /// The provided `path` must be the _only_ device in use on its bus,
86
+ /// and note its own CS pin will be asserted for all device access,
87
+ /// so the path should be to a dummy device used only to access
88
+ /// the underlying bus.
24
89
pub fn open < P > ( path : P ) -> Result < Self , SPIError >
25
90
where
26
91
P : AsRef < Path > ,
27
92
{
28
- spidev:: Spidev :: open ( path) . map ( Spidev ) . map_err ( |e| e. into ( ) )
93
+ spidev:: Spidev :: open ( path) . map ( SpidevBus ) . map_err ( |e| e. into ( ) )
29
94
}
30
95
}
31
96
32
- impl ops:: Deref for Spidev {
97
+ impl ops:: Deref for SpidevDevice {
33
98
type Target = spidev:: Spidev ;
34
99
35
100
fn deref ( & self ) -> & Self :: Target {
36
101
& self . 0
37
102
}
38
103
}
39
104
40
- impl ops:: DerefMut for Spidev {
105
+ impl ops:: DerefMut for SpidevDevice {
106
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
107
+ & mut self . 0
108
+ }
109
+ }
110
+
111
+ impl ops:: Deref for SpidevBus {
112
+ type Target = spidev:: Spidev ;
113
+
114
+ fn deref ( & self ) -> & Self :: Target {
115
+ & self . 0
116
+ }
117
+ }
118
+
119
+ impl ops:: DerefMut for SpidevBus {
41
120
fn deref_mut ( & mut self ) -> & mut Self :: Target {
42
121
& mut self . 0
43
122
}
@@ -51,11 +130,15 @@ mod embedded_hal_impl {
51
130
use std:: convert:: TryInto ;
52
131
use std:: io:: { Read , Write } ;
53
132
54
- impl ErrorType for Spidev {
133
+ impl ErrorType for SpidevDevice {
134
+ type Error = SPIError ;
135
+ }
136
+
137
+ impl ErrorType for SpidevBus {
55
138
type Error = SPIError ;
56
139
}
57
140
58
- impl SpiBus < u8 > for Spidev {
141
+ impl SpiBus < u8 > for SpidevBus {
59
142
fn read ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
60
143
self . 0 . read_exact ( words) . map_err ( |err| SPIError { err } )
61
144
}
@@ -97,7 +180,7 @@ mod embedded_hal_impl {
97
180
}
98
181
}
99
182
100
- impl SpiDevice for Spidev {
183
+ impl SpiDevice for SpidevDevice {
101
184
/// Perform a transaction against the device. [Read more][transaction]
102
185
///
103
186
/// [Delay operations][delay] are capped to 65535 microseconds.
0 commit comments