aboutsummaryrefslogtreecommitdiff
path: root/embassy-embedded-hal/src/adapter.rs
diff options
context:
space:
mode:
authorRasmus Melchior Jacobsen <[email protected]>2023-05-22 16:48:31 +0200
committerRasmus Melchior Jacobsen <[email protected]>2023-05-22 16:48:31 +0200
commitcd1bf31fedbd33170507245eef1f7ae576aa3557 (patch)
tree5e15fbe169c15ed603431f9222e6e9c99e23f713 /embassy-embedded-hal/src/adapter.rs
parentd54eb1107ee45c5030449a0de0c259da7236ca05 (diff)
Add YieldingAsync adapter
Diffstat (limited to 'embassy-embedded-hal/src/adapter.rs')
-rw-r--r--embassy-embedded-hal/src/adapter.rs248
1 files changed, 0 insertions, 248 deletions
diff --git a/embassy-embedded-hal/src/adapter.rs b/embassy-embedded-hal/src/adapter.rs
deleted file mode 100644
index 169aad5e3..000000000
--- a/embassy-embedded-hal/src/adapter.rs
+++ /dev/null
@@ -1,248 +0,0 @@
1//! Adapters between embedded-hal traits.
2
3use embassy_futures::yield_now;
4use embedded_hal_02::{blocking, serial};
5
6/// Wrapper that implements async traits using blocking implementations.
7///
8/// This allows driver writers to depend on the async traits while still supporting embedded-hal peripheral implementations.
9///
10/// BlockingAsync will implement any async trait that maps to embedded-hal traits implemented for the wrapped driver.
11///
12/// Driver users are then free to choose which implementation that is available to them.
13pub struct BlockingAsync<T> {
14 wrapped: T,
15}
16
17impl<T> BlockingAsync<T> {
18 /// Create a new instance of a wrapper for a given peripheral.
19 pub fn new(wrapped: T) -> Self {
20 Self { wrapped }
21 }
22}
23
24//
25// I2C implementations
26//
27impl<T, E> embedded_hal_1::i2c::ErrorType for BlockingAsync<T>
28where
29 E: embedded_hal_1::i2c::Error + 'static,
30 T: blocking::i2c::WriteRead<Error = E> + blocking::i2c::Read<Error = E> + blocking::i2c::Write<Error = E>,
31{
32 type Error = E;
33}
34
35impl<T, E> embedded_hal_async::i2c::I2c for BlockingAsync<T>
36where
37 E: embedded_hal_1::i2c::Error + 'static,
38 T: blocking::i2c::WriteRead<Error = E> + blocking::i2c::Read<Error = E> + blocking::i2c::Write<Error = E>,
39{
40 async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
41 self.wrapped.read(address, read)
42 }
43
44 async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
45 self.wrapped.write(address, write)
46 }
47
48 async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
49 self.wrapped.write_read(address, write, read)
50 }
51
52 async fn transaction(
53 &mut self,
54 address: u8,
55 operations: &mut [embedded_hal_1::i2c::Operation<'_>],
56 ) -> Result<(), Self::Error> {
57 let _ = address;
58 let _ = operations;
59 todo!()
60 }
61}
62
63//
64// SPI implementatinos
65//
66
67impl<T, E> embedded_hal_async::spi::ErrorType for BlockingAsync<T>
68where
69 E: embedded_hal_1::spi::Error,
70 T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
71{
72 type Error = E;
73}
74
75impl<T, E> embedded_hal_async::spi::SpiBus<u8> for BlockingAsync<T>
76where
77 E: embedded_hal_1::spi::Error + 'static,
78 T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
79{
80 async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> {
81 // Ensure we write the expected bytes
82 for i in 0..core::cmp::min(read.len(), write.len()) {
83 read[i] = write[i].clone();
84 }
85 self.wrapped.transfer(read)?;
86 Ok(())
87 }
88
89 async fn transfer_in_place<'a>(&'a mut self, _: &'a mut [u8]) -> Result<(), Self::Error> {
90 todo!()
91 }
92}
93
94impl<T, E> embedded_hal_async::spi::SpiBusFlush for BlockingAsync<T>
95where
96 E: embedded_hal_1::spi::Error + 'static,
97 T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
98{
99 async fn flush(&mut self) -> Result<(), Self::Error> {
100 Ok(())
101 }
102}
103
104impl<T, E> embedded_hal_async::spi::SpiBusWrite<u8> for BlockingAsync<T>
105where
106 E: embedded_hal_1::spi::Error + 'static,
107 T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
108{
109 async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
110 self.wrapped.write(data)?;
111 Ok(())
112 }
113}
114
115impl<T, E> embedded_hal_async::spi::SpiBusRead<u8> for BlockingAsync<T>
116where
117 E: embedded_hal_1::spi::Error + 'static,
118 T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
119{
120 async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
121 self.wrapped.transfer(data)?;
122 Ok(())
123 }
124}
125
126// Uart implementatinos
127impl<T, E> embedded_hal_1::serial::ErrorType for BlockingAsync<T>
128where
129 T: serial::Read<u8, Error = E>,
130 E: embedded_hal_1::serial::Error + 'static,
131{
132 type Error = E;
133}
134
135/// NOR flash wrapper
136use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
137use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};
138
139impl<T> ErrorType for BlockingAsync<T>
140where
141 T: ErrorType,
142{
143 type Error = T::Error;
144}
145
146impl<T> AsyncNorFlash for BlockingAsync<T>
147where
148 T: NorFlash,
149{
150 const WRITE_SIZE: usize = <T as NorFlash>::WRITE_SIZE;
151 const ERASE_SIZE: usize = <T as NorFlash>::ERASE_SIZE;
152
153 async fn write(&mut self, offset: u32, data: &[u8]) -> Result<(), Self::Error> {
154 self.wrapped.write(offset, data)?;
155 yield_now().await;
156 Ok(())
157 }
158
159 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
160 for from in (from..to).step_by(T::ERASE_SIZE) {
161 let to = core::cmp::min(from + T::ERASE_SIZE as u32, to);
162 self.wrapped.erase(from, to)?;
163 yield_now().await;
164 }
165 Ok(())
166 }
167}
168
169impl<T> AsyncReadNorFlash for BlockingAsync<T>
170where
171 T: ReadNorFlash,
172{
173 const READ_SIZE: usize = <T as ReadNorFlash>::READ_SIZE;
174 async fn read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Self::Error> {
175 self.wrapped.read(address, data)
176 }
177
178 fn capacity(&self) -> usize {
179 self.wrapped.capacity()
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186
187 extern crate std;
188
189 #[derive(Default)]
190 struct FakeFlash(Vec<(u32, u32)>);
191
192 impl embedded_storage::nor_flash::ErrorType for FakeFlash {
193 type Error = std::convert::Infallible;
194 }
195
196 impl embedded_storage::nor_flash::ReadNorFlash for FakeFlash {
197 const READ_SIZE: usize = 1;
198
199 fn read(&mut self, _offset: u32, _bytes: &mut [u8]) -> Result<(), Self::Error> {
200 unimplemented!()
201 }
202
203 fn capacity(&self) -> usize {
204 unimplemented!()
205 }
206 }
207
208 impl embedded_storage::nor_flash::NorFlash for FakeFlash {
209 const WRITE_SIZE: usize = 4;
210 const ERASE_SIZE: usize = 128;
211
212 fn write(&mut self, _offset: u32, _bytes: &[u8]) -> Result<(), Self::Error> {
213 unimplemented!()
214 }
215
216 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
217 self.0.push((from, to));
218 Ok(())
219 }
220 }
221
222 #[futures_test::test]
223 async fn can_erase() {
224 let fake = FakeFlash::default();
225 let mut yielding = BlockingAsync::new(fake);
226
227 yielding.erase(0, 256).await.unwrap();
228
229 let fake = yielding.wrapped;
230 assert_eq!(2, fake.0.len());
231 assert_eq!((0, 128), fake.0[0]);
232 assert_eq!((128, 256), fake.0[1]);
233 }
234
235 #[futures_test::test]
236 async fn can_erase_wrong_erase_size() {
237 let fake = FakeFlash::default();
238 let mut yielding = BlockingAsync::new(fake);
239
240 yielding.erase(0, 257).await.unwrap();
241
242 let fake = yielding.wrapped;
243 assert_eq!(3, fake.0.len());
244 assert_eq!((0, 128), fake.0[0]);
245 assert_eq!((128, 256), fake.0[1]);
246 assert_eq!((256, 257), fake.0[2]);
247 }
248}