|
1 | 1 | //! SPI master mode traits. |
2 | 2 |
|
3 | | -use core::fmt::Debug; |
4 | | - |
5 | | -use embedded_hal::digital::OutputPin; |
6 | | -use embedded_hal::spi as blocking; |
7 | 3 | pub use embedded_hal::spi::{ |
8 | 4 | Error, ErrorKind, ErrorType, Mode, Operation, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3, |
9 | 5 | }; |
10 | 6 |
|
11 | | -use crate::delay::DelayUs; |
12 | | - |
13 | 7 | /// SPI device trait |
14 | 8 | /// |
15 | 9 | /// `SpiDevice` represents ownership over a single SPI device on a (possibly shared) bus, selected |
@@ -170,149 +164,3 @@ impl<T: SpiBus<Word> + ?Sized, Word: 'static + Copy> SpiBus<Word> for &mut T { |
170 | 164 | T::flush(self).await |
171 | 165 | } |
172 | 166 | } |
173 | | - |
174 | | -/// Error type for [`ExclusiveDevice`] operations. |
175 | | -#[derive(Copy, Clone, Eq, PartialEq, Debug)] |
176 | | -pub enum ExclusiveDeviceError<BUS, CS> { |
177 | | - /// An inner SPI bus operation failed |
178 | | - Spi(BUS), |
179 | | - /// Asserting or deasserting CS failed |
180 | | - Cs(CS), |
181 | | -} |
182 | | - |
183 | | -impl<BUS, CS> Error for ExclusiveDeviceError<BUS, CS> |
184 | | -where |
185 | | - BUS: Error + Debug, |
186 | | - CS: Debug, |
187 | | -{ |
188 | | - fn kind(&self) -> ErrorKind { |
189 | | - match self { |
190 | | - Self::Spi(e) => e.kind(), |
191 | | - Self::Cs(_) => ErrorKind::ChipSelectFault, |
192 | | - } |
193 | | - } |
194 | | -} |
195 | | - |
196 | | -/// [`SpiDevice`] implementation with exclusive access to the bus (not shared). |
197 | | -/// |
198 | | -/// This is the most straightforward way of obtaining an [`SpiDevice`] from an [`SpiBus`], |
199 | | -/// ideal for when no sharing is required (only one SPI device is present on the bus). |
200 | | -pub struct ExclusiveDevice<BUS, CS, D> { |
201 | | - bus: BUS, |
202 | | - cs: CS, |
203 | | - delay: D, |
204 | | -} |
205 | | - |
206 | | -impl<BUS, CS, D> ExclusiveDevice<BUS, CS, D> { |
207 | | - /// Create a new ExclusiveDevice |
208 | | - pub fn new(bus: BUS, cs: CS, delay: D) -> Self { |
209 | | - Self { bus, cs, delay } |
210 | | - } |
211 | | - |
212 | | - /// Returns a reference to the underlying bus object. |
213 | | - pub fn bus(&self) -> &BUS { |
214 | | - &self.bus |
215 | | - } |
216 | | - |
217 | | - /// Returns a mutable reference to the underlying bus object. |
218 | | - pub fn bus_mut(&mut self) -> &mut BUS { |
219 | | - &mut self.bus |
220 | | - } |
221 | | -} |
222 | | - |
223 | | -impl<BUS, CS, D> ErrorType for ExclusiveDevice<BUS, CS, D> |
224 | | -where |
225 | | - BUS: ErrorType, |
226 | | - CS: OutputPin, |
227 | | -{ |
228 | | - type Error = ExclusiveDeviceError<BUS::Error, CS::Error>; |
229 | | -} |
230 | | - |
231 | | -impl<Word: Copy + 'static, BUS, CS, D> blocking::SpiDevice<Word> for ExclusiveDevice<BUS, CS, D> |
232 | | -where |
233 | | - BUS: blocking::SpiBus<Word>, |
234 | | - CS: OutputPin, |
235 | | - D: embedded_hal::delay::DelayUs, |
236 | | -{ |
237 | | - fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> { |
238 | | - self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?; |
239 | | - |
240 | | - let op_res = 'ops: { |
241 | | - for op in operations { |
242 | | - let res = match op { |
243 | | - Operation::Read(buf) => self.bus.read(buf), |
244 | | - Operation::Write(buf) => self.bus.write(buf), |
245 | | - Operation::Transfer(read, write) => self.bus.transfer(read, write), |
246 | | - Operation::TransferInPlace(buf) => self.bus.transfer_in_place(buf), |
247 | | - Operation::DelayUs(us) => match self.bus.flush() { |
248 | | - Err(e) => Err(e), |
249 | | - Ok(()) => { |
250 | | - self.delay.delay_us(*us); |
251 | | - Ok(()) |
252 | | - } |
253 | | - }, |
254 | | - }; |
255 | | - if let Err(e) = res { |
256 | | - break 'ops Err(e); |
257 | | - } |
258 | | - } |
259 | | - Ok(()) |
260 | | - }; |
261 | | - |
262 | | - // On failure, it's important to still flush and deassert CS. |
263 | | - let flush_res = self.bus.flush(); |
264 | | - let cs_res = self.cs.set_high(); |
265 | | - |
266 | | - op_res.map_err(ExclusiveDeviceError::Spi)?; |
267 | | - flush_res.map_err(ExclusiveDeviceError::Spi)?; |
268 | | - cs_res.map_err(ExclusiveDeviceError::Cs)?; |
269 | | - |
270 | | - Ok(()) |
271 | | - } |
272 | | -} |
273 | | - |
274 | | -impl<Word: Copy + 'static, BUS, CS, D> SpiDevice<Word> for ExclusiveDevice<BUS, CS, D> |
275 | | -where |
276 | | - BUS: SpiBus<Word>, |
277 | | - CS: OutputPin, |
278 | | - D: DelayUs, |
279 | | -{ |
280 | | - async fn transaction( |
281 | | - &mut self, |
282 | | - operations: &mut [Operation<'_, Word>], |
283 | | - ) -> Result<(), Self::Error> { |
284 | | - self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?; |
285 | | - |
286 | | - let op_res = 'ops: { |
287 | | - for op in operations { |
288 | | - let res = match op { |
289 | | - Operation::Read(buf) => self.bus.read(buf).await, |
290 | | - Operation::Write(buf) => self.bus.write(buf).await, |
291 | | - Operation::Transfer(read, write) => self.bus.transfer(read, write).await, |
292 | | - Operation::TransferInPlace(buf) => self.bus.transfer_in_place(buf).await, |
293 | | - Operation::DelayUs(us) => match self.bus.flush().await { |
294 | | - Err(e) => Err(e), |
295 | | - Ok(()) => { |
296 | | - self.delay.delay_us(*us).await; |
297 | | - Ok(()) |
298 | | - } |
299 | | - }, |
300 | | - }; |
301 | | - if let Err(e) = res { |
302 | | - break 'ops Err(e); |
303 | | - } |
304 | | - } |
305 | | - Ok(()) |
306 | | - }; |
307 | | - |
308 | | - // On failure, it's important to still flush and deassert CS. |
309 | | - let flush_res = self.bus.flush().await; |
310 | | - let cs_res = self.cs.set_high(); |
311 | | - |
312 | | - op_res.map_err(ExclusiveDeviceError::Spi)?; |
313 | | - flush_res.map_err(ExclusiveDeviceError::Spi)?; |
314 | | - cs_res.map_err(ExclusiveDeviceError::Cs)?; |
315 | | - |
316 | | - Ok(()) |
317 | | - } |
318 | | -} |
0 commit comments