diff options
Diffstat (limited to 'embassy-embedded-hal/src/shared_bus/asynch/spi.rs')
| -rw-r--r-- | embassy-embedded-hal/src/shared_bus/asynch/spi.rs | 171 |
1 files changed, 145 insertions, 26 deletions
diff --git a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs index d25716655..b5549a6cd 100644 --- a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs | |||
| @@ -25,12 +25,11 @@ | |||
| 25 | //! let spi_dev2 = SpiDevice::new(spi_bus, cs_pin2); | 25 | //! let spi_dev2 = SpiDevice::new(spi_bus, cs_pin2); |
| 26 | //! let display2 = ST7735::new(spi_dev2, dc2, rst2, Default::default(), 160, 128); | 26 | //! let display2 = ST7735::new(spi_dev2, dc2, rst2, Default::default(), 160, 128); |
| 27 | //! ``` | 27 | //! ``` |
| 28 | use core::future::Future; | ||
| 29 | 28 | ||
| 30 | use embassy_sync::blocking_mutex::raw::RawMutex; | 29 | use embassy_sync::blocking_mutex::raw::RawMutex; |
| 31 | use embassy_sync::mutex::Mutex; | 30 | use embassy_sync::mutex::Mutex; |
| 32 | use embedded_hal_1::digital::OutputPin; | 31 | use embedded_hal_1::digital::OutputPin; |
| 33 | use embedded_hal_1::spi::ErrorType; | 32 | use embedded_hal_1::spi::Operation; |
| 34 | use embedded_hal_async::spi; | 33 | use embedded_hal_async::spi; |
| 35 | 34 | ||
| 36 | use crate::shared_bus::SpiDeviceError; | 35 | use crate::shared_bus::SpiDeviceError; |
| @@ -57,33 +56,92 @@ where | |||
| 57 | type Error = SpiDeviceError<BUS::Error, CS::Error>; | 56 | type Error = SpiDeviceError<BUS::Error, CS::Error>; |
| 58 | } | 57 | } |
| 59 | 58 | ||
| 60 | unsafe impl<M, BUS, CS> spi::SpiDevice for SpiDevice<'_, M, BUS, CS> | 59 | impl<M, BUS, CS> spi::SpiDeviceRead for SpiDevice<'_, M, BUS, CS> |
| 61 | where | 60 | where |
| 62 | M: RawMutex + 'static, | 61 | M: RawMutex, |
| 63 | BUS: spi::SpiBusFlush + 'static, | 62 | BUS: spi::SpiBusRead, |
| 64 | CS: OutputPin, | 63 | CS: OutputPin, |
| 65 | { | 64 | { |
| 66 | type Bus = BUS; | 65 | async fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { |
| 66 | let mut bus = self.bus.lock().await; | ||
| 67 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 68 | |||
| 69 | let op_res: Result<(), BUS::Error> = try { | ||
| 70 | for buf in operations { | ||
| 71 | bus.read(buf).await?; | ||
| 72 | } | ||
| 73 | }; | ||
| 74 | |||
| 75 | // On failure, it's important to still flush and deassert CS. | ||
| 76 | let flush_res = bus.flush().await; | ||
| 77 | let cs_res = self.cs.set_high(); | ||
| 67 | 78 | ||
| 68 | async fn transaction<R, F, Fut>(&mut self, f: F) -> Result<R, Self::Error> | 79 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; |
| 69 | where | 80 | flush_res.map_err(SpiDeviceError::Spi)?; |
| 70 | F: FnOnce(*mut Self::Bus) -> Fut, | 81 | cs_res.map_err(SpiDeviceError::Cs)?; |
| 71 | Fut: Future<Output = Result<R, <Self::Bus as ErrorType>::Error>>, | 82 | |
| 72 | { | 83 | Ok(op_res) |
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | impl<M, BUS, CS> spi::SpiDeviceWrite for SpiDevice<'_, M, BUS, CS> | ||
| 88 | where | ||
| 89 | M: RawMutex, | ||
| 90 | BUS: spi::SpiBusWrite, | ||
| 91 | CS: OutputPin, | ||
| 92 | { | ||
| 93 | async fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { | ||
| 73 | let mut bus = self.bus.lock().await; | 94 | let mut bus = self.bus.lock().await; |
| 74 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | 95 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; |
| 75 | 96 | ||
| 76 | let f_res = f(&mut *bus).await; | 97 | let op_res: Result<(), BUS::Error> = try { |
| 98 | for buf in operations { | ||
| 99 | bus.write(buf).await?; | ||
| 100 | } | ||
| 101 | }; | ||
| 77 | 102 | ||
| 78 | // On failure, it's important to still flush and deassert CS. | 103 | // On failure, it's important to still flush and deassert CS. |
| 79 | let flush_res = bus.flush().await; | 104 | let flush_res = bus.flush().await; |
| 80 | let cs_res = self.cs.set_high(); | 105 | let cs_res = self.cs.set_high(); |
| 81 | 106 | ||
| 82 | let f_res = f_res.map_err(SpiDeviceError::Spi)?; | 107 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; |
| 83 | flush_res.map_err(SpiDeviceError::Spi)?; | 108 | flush_res.map_err(SpiDeviceError::Spi)?; |
| 84 | cs_res.map_err(SpiDeviceError::Cs)?; | 109 | cs_res.map_err(SpiDeviceError::Cs)?; |
| 85 | 110 | ||
| 86 | Ok(f_res) | 111 | Ok(op_res) |
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | impl<M, BUS, CS> spi::SpiDevice for SpiDevice<'_, M, BUS, CS> | ||
| 116 | where | ||
| 117 | M: RawMutex, | ||
| 118 | BUS: spi::SpiBus, | ||
| 119 | CS: OutputPin, | ||
| 120 | { | ||
| 121 | async fn transaction(&mut self, operations: &mut [spi::Operation<'_, u8>]) -> Result<(), Self::Error> { | ||
| 122 | let mut bus = self.bus.lock().await; | ||
| 123 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 124 | |||
| 125 | let op_res: Result<(), BUS::Error> = try { | ||
| 126 | for op in operations { | ||
| 127 | match op { | ||
| 128 | Operation::Read(buf) => bus.read(buf).await?, | ||
| 129 | Operation::Write(buf) => bus.write(buf).await?, | ||
| 130 | Operation::Transfer(read, write) => bus.transfer(read, write).await?, | ||
| 131 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?, | ||
| 132 | } | ||
| 133 | } | ||
| 134 | }; | ||
| 135 | |||
| 136 | // On failure, it's important to still flush and deassert CS. | ||
| 137 | let flush_res = bus.flush().await; | ||
| 138 | let cs_res = self.cs.set_high(); | ||
| 139 | |||
| 140 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 141 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 142 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 143 | |||
| 144 | Ok(op_res) | ||
| 87 | } | 145 | } |
| 88 | } | 146 | } |
| 89 | 147 | ||
| @@ -114,33 +172,94 @@ where | |||
| 114 | type Error = SpiDeviceError<BUS::Error, CS::Error>; | 172 | type Error = SpiDeviceError<BUS::Error, CS::Error>; |
| 115 | } | 173 | } |
| 116 | 174 | ||
| 117 | unsafe impl<M, BUS, CS> spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS> | 175 | impl<M, BUS, CS> spi::SpiDeviceWrite for SpiDeviceWithConfig<'_, M, BUS, CS> |
| 176 | where | ||
| 177 | M: RawMutex, | ||
| 178 | BUS: spi::SpiBusWrite + SetConfig, | ||
| 179 | CS: OutputPin, | ||
| 180 | { | ||
| 181 | async fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { | ||
| 182 | let mut bus = self.bus.lock().await; | ||
| 183 | bus.set_config(&self.config); | ||
| 184 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 185 | |||
| 186 | let op_res: Result<(), BUS::Error> = try { | ||
| 187 | for buf in operations { | ||
| 188 | bus.write(buf).await?; | ||
| 189 | } | ||
| 190 | }; | ||
| 191 | |||
| 192 | // On failure, it's important to still flush and deassert CS. | ||
| 193 | let flush_res = bus.flush().await; | ||
| 194 | let cs_res = self.cs.set_high(); | ||
| 195 | |||
| 196 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 197 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 198 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 199 | |||
| 200 | Ok(op_res) | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | impl<M, BUS, CS> spi::SpiDeviceRead for SpiDeviceWithConfig<'_, M, BUS, CS> | ||
| 118 | where | 205 | where |
| 119 | M: RawMutex + 'static, | 206 | M: RawMutex, |
| 120 | BUS: spi::SpiBusFlush + SetConfig + 'static, | 207 | BUS: spi::SpiBusRead + SetConfig, |
| 121 | CS: OutputPin, | 208 | CS: OutputPin, |
| 122 | { | 209 | { |
| 123 | type Bus = BUS; | 210 | async fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { |
| 211 | let mut bus = self.bus.lock().await; | ||
| 212 | bus.set_config(&self.config); | ||
| 213 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 214 | |||
| 215 | let op_res: Result<(), BUS::Error> = try { | ||
| 216 | for buf in operations { | ||
| 217 | bus.read(buf).await?; | ||
| 218 | } | ||
| 219 | }; | ||
| 220 | |||
| 221 | // On failure, it's important to still flush and deassert CS. | ||
| 222 | let flush_res = bus.flush().await; | ||
| 223 | let cs_res = self.cs.set_high(); | ||
| 224 | |||
| 225 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 226 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 227 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 228 | |||
| 229 | Ok(op_res) | ||
| 230 | } | ||
| 231 | } | ||
| 124 | 232 | ||
| 125 | async fn transaction<R, F, Fut>(&mut self, f: F) -> Result<R, Self::Error> | 233 | impl<M, BUS, CS> spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS> |
| 126 | where | 234 | where |
| 127 | F: FnOnce(*mut Self::Bus) -> Fut, | 235 | M: RawMutex, |
| 128 | Fut: Future<Output = Result<R, <Self::Bus as ErrorType>::Error>>, | 236 | BUS: spi::SpiBus + SetConfig, |
| 129 | { | 237 | CS: OutputPin, |
| 238 | { | ||
| 239 | async fn transaction(&mut self, operations: &mut [spi::Operation<'_, u8>]) -> Result<(), Self::Error> { | ||
| 130 | let mut bus = self.bus.lock().await; | 240 | let mut bus = self.bus.lock().await; |
| 131 | bus.set_config(&self.config); | 241 | bus.set_config(&self.config); |
| 132 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | 242 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; |
| 133 | 243 | ||
| 134 | let f_res = f(&mut *bus).await; | 244 | let op_res: Result<(), BUS::Error> = try { |
| 245 | for op in operations { | ||
| 246 | match op { | ||
| 247 | Operation::Read(buf) => bus.read(buf).await?, | ||
| 248 | Operation::Write(buf) => bus.write(buf).await?, | ||
| 249 | Operation::Transfer(read, write) => bus.transfer(read, write).await?, | ||
| 250 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?, | ||
| 251 | } | ||
| 252 | } | ||
| 253 | }; | ||
| 135 | 254 | ||
| 136 | // On failure, it's important to still flush and deassert CS. | 255 | // On failure, it's important to still flush and deassert CS. |
| 137 | let flush_res = bus.flush().await; | 256 | let flush_res = bus.flush().await; |
| 138 | let cs_res = self.cs.set_high(); | 257 | let cs_res = self.cs.set_high(); |
| 139 | 258 | ||
| 140 | let f_res = f_res.map_err(SpiDeviceError::Spi)?; | 259 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; |
| 141 | flush_res.map_err(SpiDeviceError::Spi)?; | 260 | flush_res.map_err(SpiDeviceError::Spi)?; |
| 142 | cs_res.map_err(SpiDeviceError::Cs)?; | 261 | cs_res.map_err(SpiDeviceError::Cs)?; |
| 143 | 262 | ||
| 144 | Ok(f_res) | 263 | Ok(op_res) |
| 145 | } | 264 | } |
| 146 | } | 265 | } |
