aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRagarnoy <[email protected]>2024-04-30 02:10:54 +0200
committerDario Nieuwenhuis <[email protected]>2024-05-20 10:56:43 +0200
commitc5a183fa82614f1fdd8d7783d101bf2c45cd32e1 (patch)
tree35215913c0ccc4716ec22519a212983c85031f4e
parent621dbecedac3e57a15f070343608e9d631b55f08 (diff)
Improve flexibility by introducing SPI word size as a generic parameter
-rw-r--r--embassy-embedded-hal/src/shared_bus/blocking/spi.rs79
1 files changed, 63 insertions, 16 deletions
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
index 801899f9f..b01012695 100644
--- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
+++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
@@ -28,19 +28,21 @@ use crate::shared_bus::SpiDeviceError;
28use crate::SetConfig; 28use crate::SetConfig;
29 29
30/// SPI device on a shared bus. 30/// SPI device on a shared bus.
31pub struct SpiDevice<'a, M: RawMutex, BUS, CS> { 31pub struct SpiDevice<'a, M: RawMutex, BUS, CS, Word> {
32 bus: &'a Mutex<M, RefCell<BUS>>, 32 bus: &'a Mutex<M, RefCell<BUS>>,
33 cs: CS, 33 cs: CS,
34 _word: core::marker::PhantomData<Word>,
34} 35}
35 36
36impl<'a, M: RawMutex, BUS, CS> SpiDevice<'a, M, BUS, CS> { 37impl<'a, M: RawMutex, BUS, CS, Word> SpiDevice<'a, M, BUS, CS, Word> {
37 /// Create a new `SpiDevice`. 38 /// Create a new `SpiDevice`.
38 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, cs: CS) -> Self { 39 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, cs: CS) -> Self {
39 Self { bus, cs } 40 Self { bus, cs
41 , _word: core::marker::PhantomData}
40 } 42 }
41} 43}
42 44
43impl<'a, M: RawMutex, BUS, CS> spi::ErrorType for SpiDevice<'a, M, BUS, CS> 45impl<'a, M: RawMutex, BUS, CS, Word> spi::ErrorType for SpiDevice<'a, M, BUS, CS, Word>
44where 46where
45 BUS: spi::ErrorType, 47 BUS: spi::ErrorType,
46 CS: OutputPin, 48 CS: OutputPin,
@@ -48,13 +50,14 @@ where
48 type Error = SpiDeviceError<BUS::Error, CS::Error>; 50 type Error = SpiDeviceError<BUS::Error, CS::Error>;
49} 51}
50 52
51impl<BUS, M, CS> embedded_hal_1::spi::SpiDevice for SpiDevice<'_, M, BUS, CS> 53impl<BUS, M, CS, Word> embedded_hal_1::spi::SpiDevice<Word> for SpiDevice<'_, M, BUS, CS, Word>
52where 54where
53 M: RawMutex, 55 M: RawMutex,
54 BUS: SpiBus, 56 BUS: SpiBus<Word>,
55 CS: OutputPin, 57 CS: OutputPin,
58 Word: Copy + 'static,
56{ 59{
57 fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> { 60 fn transaction(&mut self, operations: &mut [embedded_hal_1::spi::Operation<'_, Word>]) -> Result<(), Self::Error> {
58 if cfg!(not(feature = "time")) && operations.iter().any(|op| matches!(op, Operation::DelayNs(_))) { 61 if cfg!(not(feature = "time")) && operations.iter().any(|op| matches!(op, Operation::DelayNs(_))) {
59 return Err(SpiDeviceError::DelayNotSupported); 62 return Err(SpiDeviceError::DelayNotSupported);
60 } 63 }
@@ -90,7 +93,7 @@ where
90 } 93 }
91} 94}
92 95
93impl<'d, M, BUS, CS, BusErr, CsErr> embedded_hal_02::blocking::spi::Transfer<u8> for SpiDevice<'_, M, BUS, CS> 96impl<'d, M, BUS, CS, BusErr, CsErr, Word> embedded_hal_02::blocking::spi::Transfer<u8> for SpiDevice<'_, M, BUS, CS, Word>
94where 97where
95 M: RawMutex, 98 M: RawMutex,
96 BUS: embedded_hal_02::blocking::spi::Transfer<u8, Error = BusErr>, 99 BUS: embedded_hal_02::blocking::spi::Transfer<u8, Error = BusErr>,
@@ -110,7 +113,7 @@ where
110 } 113 }
111} 114}
112 115
113impl<'d, M, BUS, CS, BusErr, CsErr> embedded_hal_02::blocking::spi::Write<u8> for SpiDevice<'_, M, BUS, CS> 116impl<'d, M, BUS, CS, BusErr, CsErr, Word> embedded_hal_02::blocking::spi::Write<u8> for SpiDevice<'_, M, BUS, CS, Word>
114where 117where
115 M: RawMutex, 118 M: RawMutex,
116 BUS: embedded_hal_02::blocking::spi::Write<u8, Error = BusErr>, 119 BUS: embedded_hal_02::blocking::spi::Write<u8, Error = BusErr>,
@@ -131,21 +134,63 @@ where
131 } 134 }
132} 135}
133 136
137impl<'d, M, BUS, CS, BusErr, CsErr, Word> embedded_hal_02::blocking::spi::Transfer<u16> for SpiDevice<'_, M, BUS, CS, Word>
138 where
139 M: RawMutex,
140 BUS: embedded_hal_02::blocking::spi::Transfer<u16, Error = BusErr>,
141 CS: OutputPin<Error = CsErr>,
142{
143 type Error = SpiDeviceError<BusErr, CsErr>;
144 fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> {
145 self.bus.lock(|bus| {
146 let mut bus = bus.borrow_mut();
147 self.cs.set_low().map_err(SpiDeviceError::Cs)?;
148 let op_res = bus.transfer(words);
149 let cs_res = self.cs.set_high();
150 let op_res = op_res.map_err(SpiDeviceError::Spi)?;
151 cs_res.map_err(SpiDeviceError::Cs)?;
152 Ok(op_res)
153 })
154 }
155}
156
157impl<'d, M, BUS, CS, BusErr, CsErr, Word> embedded_hal_02::blocking::spi::Write<u16> for SpiDevice<'_, M, BUS, CS, Word>
158 where
159 M: RawMutex,
160 BUS: embedded_hal_02::blocking::spi::Write<u16, Error = BusErr>,
161 CS: OutputPin<Error = CsErr>,
162{
163 type Error = SpiDeviceError<BusErr, CsErr>;
164
165 fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> {
166 self.bus.lock(|bus| {
167 let mut bus = bus.borrow_mut();
168 self.cs.set_low().map_err(SpiDeviceError::Cs)?;
169 let op_res = bus.write(words);
170 let cs_res = self.cs.set_high();
171 let op_res = op_res.map_err(SpiDeviceError::Spi)?;
172 cs_res.map_err(SpiDeviceError::Cs)?;
173 Ok(op_res)
174 })
175 }
176}
177
134/// SPI device on a shared bus, with its own configuration. 178/// SPI device on a shared bus, with its own configuration.
135/// 179///
136/// This is like [`SpiDevice`], with an additional bus configuration that's applied 180/// This is like [`SpiDevice`], with an additional bus configuration that's applied
137/// to the bus before each use using [`SetConfig`]. This allows different 181/// to the bus before each use using [`SetConfig`]. This allows different
138/// devices on the same bus to use different communication settings. 182/// devices on the same bus to use different communication settings.
139pub struct SpiDeviceWithConfig<'a, M: RawMutex, BUS: SetConfig, CS> { 183pub struct SpiDeviceWithConfig<'a, M: RawMutex, BUS: SetConfig, CS, Word> {
140 bus: &'a Mutex<M, RefCell<BUS>>, 184 bus: &'a Mutex<M, RefCell<BUS>>,
141 cs: CS, 185 cs: CS,
142 config: BUS::Config, 186 config: BUS::Config,
187 _word: core::marker::PhantomData<Word>,
143} 188}
144 189
145impl<'a, M: RawMutex, BUS: SetConfig, CS> SpiDeviceWithConfig<'a, M, BUS, CS> { 190impl<'a, M: RawMutex, BUS: SetConfig, CS, Word> SpiDeviceWithConfig<'a, M, BUS, CS, Word> {
146 /// Create a new `SpiDeviceWithConfig`. 191 /// Create a new `SpiDeviceWithConfig`.
147 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, cs: CS, config: BUS::Config) -> Self { 192 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, cs: CS, config: BUS::Config) -> Self {
148 Self { bus, cs, config } 193 Self { bus, cs, config, _word: core::marker::PhantomData }
149 } 194 }
150 195
151 /// Change the device's config at runtime 196 /// Change the device's config at runtime
@@ -154,22 +199,24 @@ impl<'a, M: RawMutex, BUS: SetConfig, CS> SpiDeviceWithConfig<'a, M, BUS, CS> {
154 } 199 }
155} 200}
156 201
157impl<'a, M, BUS, CS> spi::ErrorType for SpiDeviceWithConfig<'a, M, BUS, CS> 202impl<'a, M, BUS, CS, Word> spi::ErrorType for SpiDeviceWithConfig<'a, M, BUS, CS, Word>
158where 203where
159 M: RawMutex, 204 M: RawMutex,
160 BUS: spi::ErrorType + SetConfig, 205 BUS: spi::ErrorType + SetConfig,
161 CS: OutputPin, 206 CS: OutputPin,
207 Word: Copy + 'static,
162{ 208{
163 type Error = SpiDeviceError<BUS::Error, CS::Error>; 209 type Error = SpiDeviceError<BUS::Error, CS::Error>;
164} 210}
165 211
166impl<BUS, M, CS> embedded_hal_1::spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS> 212impl<BUS, M, CS, Word> embedded_hal_1::spi::SpiDevice<Word> for SpiDeviceWithConfig<'_, M, BUS, CS, Word>
167where 213where
168 M: RawMutex, 214 M: RawMutex,
169 BUS: SpiBus + SetConfig, 215 BUS: SpiBus<Word> + SetConfig,
170 CS: OutputPin, 216 CS: OutputPin,
217 Word: Copy + 'static,
171{ 218{
172 fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> { 219 fn transaction(&mut self, operations: &mut [embedded_hal_1::spi::Operation<'_, Word>]) -> Result<(), Self::Error> {
173 if cfg!(not(feature = "time")) && operations.iter().any(|op| matches!(op, Operation::DelayNs(_))) { 220 if cfg!(not(feature = "time")) && operations.iter().any(|op| matches!(op, Operation::DelayNs(_))) {
174 return Err(SpiDeviceError::DelayNotSupported); 221 return Err(SpiDeviceError::DelayNotSupported);
175 } 222 }