diff options
Diffstat (limited to 'embassy-embedded-hal/src/shared_bus/spi.rs')
| -rw-r--r-- | embassy-embedded-hal/src/shared_bus/spi.rs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/embassy-embedded-hal/src/shared_bus/spi.rs b/embassy-embedded-hal/src/shared_bus/spi.rs index fd4b6d565..04378c330 100644 --- a/embassy-embedded-hal/src/shared_bus/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/spi.rs | |||
| @@ -34,6 +34,8 @@ use embedded_hal_1::digital::blocking::OutputPin; | |||
| 34 | use embedded_hal_1::spi::ErrorType; | 34 | use embedded_hal_1::spi::ErrorType; |
| 35 | use embedded_hal_async::spi; | 35 | use embedded_hal_async::spi; |
| 36 | 36 | ||
| 37 | use crate::SetConfig; | ||
| 38 | |||
| 37 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | 39 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] |
| 38 | pub enum SpiBusDeviceError<BUS, CS> { | 40 | pub enum SpiBusDeviceError<BUS, CS> { |
| 39 | Spi(BUS), | 41 | Spi(BUS), |
| @@ -109,3 +111,62 @@ where | |||
| 109 | } | 111 | } |
| 110 | } | 112 | } |
| 111 | } | 113 | } |
| 114 | |||
| 115 | pub struct SpiBusDeviceWithConfig<'a, M: RawMutex, BUS, CS, C> { | ||
| 116 | bus: &'a Mutex<M, BUS>, | ||
| 117 | cs: CS, | ||
| 118 | config: C, | ||
| 119 | } | ||
| 120 | |||
| 121 | impl<'a, M: RawMutex, BUS, CS, C> SpiBusDeviceWithConfig<'a, M, BUS, CS, C> { | ||
| 122 | pub fn new(bus: &'a Mutex<M, BUS>, cs: CS, config: C) -> Self { | ||
| 123 | Self { bus, cs, config } | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | impl<'a, M: RawMutex, BUS, CS, C> spi::ErrorType for SpiBusDeviceWithConfig<'a, M, BUS, CS, C> | ||
| 128 | where | ||
| 129 | BUS: spi::ErrorType, | ||
| 130 | CS: OutputPin, | ||
| 131 | { | ||
| 132 | type Error = SpiBusDeviceError<BUS::Error, CS::Error>; | ||
| 133 | } | ||
| 134 | |||
| 135 | impl<M, BUS, CS, C> spi::SpiDevice for SpiBusDeviceWithConfig<'_, M, BUS, CS, C> | ||
| 136 | where | ||
| 137 | M: RawMutex + 'static, | ||
| 138 | BUS: spi::SpiBusFlush + SetConfig<C> + 'static, | ||
| 139 | CS: OutputPin, | ||
| 140 | { | ||
| 141 | type Bus = BUS; | ||
| 142 | |||
| 143 | type TransactionFuture<'a, R, F, Fut> = impl Future<Output = Result<R, Self::Error>> + 'a | ||
| 144 | where | ||
| 145 | Self: 'a, R: 'a, F: FnOnce(*mut Self::Bus) -> Fut + 'a, | ||
| 146 | Fut: Future<Output = Result<R, <Self::Bus as ErrorType>::Error>> + 'a; | ||
| 147 | |||
| 148 | fn transaction<'a, R, F, Fut>(&'a mut self, f: F) -> Self::TransactionFuture<'a, R, F, Fut> | ||
| 149 | where | ||
| 150 | R: 'a, | ||
| 151 | F: FnOnce(*mut Self::Bus) -> Fut + 'a, | ||
| 152 | Fut: Future<Output = Result<R, <Self::Bus as ErrorType>::Error>> + 'a, | ||
| 153 | { | ||
| 154 | async move { | ||
| 155 | let mut bus = self.bus.lock().await; | ||
| 156 | bus.set_config(&self.config); | ||
| 157 | self.cs.set_low().map_err(SpiBusDeviceError::Cs)?; | ||
| 158 | |||
| 159 | let f_res = f(&mut *bus).await; | ||
| 160 | |||
| 161 | // On failure, it's important to still flush and deassert CS. | ||
| 162 | let flush_res = bus.flush().await; | ||
| 163 | let cs_res = self.cs.set_high(); | ||
| 164 | |||
| 165 | let f_res = f_res.map_err(SpiBusDeviceError::Spi)?; | ||
| 166 | flush_res.map_err(SpiBusDeviceError::Spi)?; | ||
| 167 | cs_res.map_err(SpiBusDeviceError::Cs)?; | ||
| 168 | |||
| 169 | Ok(f_res) | ||
| 170 | } | ||
| 171 | } | ||
| 172 | } | ||
