aboutsummaryrefslogtreecommitdiff
path: root/embassy-traits/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-01-03 14:17:21 +0000
committerGitHub <[email protected]>2022-01-03 14:17:21 +0000
commitcdfd128185897b67bc1e478af6b637c863b66565 (patch)
treea0e7d475f34788fbfb355e9922c7450b3d26f6d1 /embassy-traits/src
parentc0e94a7042a9a91bbdef64ad0177cee21816c793 (diff)
parent3811c0a401281ece6e7adb24238ebf7ff39a2362 (diff)
Merge #545
545: Add adapter for implementing async traits for blocking types r=lulf a=lulf This allows writing drivers relying on async traits, while still functioning with implementations that already implement the embedded-hal traits. Co-authored-by: Ulf Lilleengen <[email protected]>
Diffstat (limited to 'embassy-traits/src')
-rw-r--r--embassy-traits/src/adapter.rs166
-rw-r--r--embassy-traits/src/lib.rs1
2 files changed, 167 insertions, 0 deletions
diff --git a/embassy-traits/src/adapter.rs b/embassy-traits/src/adapter.rs
new file mode 100644
index 000000000..ce7dd411f
--- /dev/null
+++ b/embassy-traits/src/adapter.rs
@@ -0,0 +1,166 @@
1use core::future::Future;
2use embedded_hal::blocking;
3use embedded_hal::serial;
4
5/// BlockingAsync is a wrapper that implements async traits using blocking peripherals. This allows
6/// driver writers to depend on the async traits while still supporting embedded-hal peripheral implementations.
7///
8/// BlockingAsync will implement any async trait that maps to embedded-hal traits implemented for the wrapped driver.
9///
10/// Driver users are then free to choose which implementation that is available to them.
11pub struct BlockingAsync<T> {
12 wrapped: T,
13}
14
15impl<T> BlockingAsync<T> {
16 /// Create a new instance of a wrapper for a given peripheral.
17 pub fn new(wrapped: T) -> Self {
18 Self { wrapped }
19 }
20}
21
22//
23// I2C implementatinos
24//
25
26impl<T, E> crate::i2c::I2c for BlockingAsync<T>
27where
28 E: 'static,
29 T: blocking::i2c::WriteRead<Error = E>
30 + blocking::i2c::Read<Error = E>
31 + blocking::i2c::Write<Error = E>,
32{
33 type Error = E;
34
35 #[rustfmt::skip]
36 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
37 #[rustfmt::skip]
38 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
39 #[rustfmt::skip]
40 type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
41
42 fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
43 async move { self.wrapped.read(address, buffer) }
44 }
45
46 fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
47 async move { self.wrapped.write(address, bytes) }
48 }
49
50 fn write_read<'a>(
51 &'a mut self,
52 address: u8,
53 bytes: &'a [u8],
54 buffer: &'a mut [u8],
55 ) -> Self::WriteReadFuture<'a> {
56 async move { self.wrapped.write_read(address, bytes, buffer) }
57 }
58}
59
60//
61// SPI implementatinos
62//
63
64impl<T, E, Word> crate::spi::Spi<Word> for BlockingAsync<T>
65where
66 T: blocking::spi::Write<Word, Error = E>,
67{
68 type Error = E;
69}
70
71impl<T, E, Word> crate::spi::FullDuplex<Word> for BlockingAsync<T>
72where
73 E: 'static,
74 Word: Clone,
75 T: blocking::spi::Transfer<Word, Error = E> + blocking::spi::Write<Word, Error = E>,
76{
77 #[rustfmt::skip]
78 type WriteReadFuture<'a> where Word: 'a, Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
79
80 fn read_write<'a>(
81 &'a mut self,
82 read: &'a mut [Word],
83 write: &'a [Word],
84 ) -> Self::WriteReadFuture<'a> {
85 async move {
86 // Ensure we write the expected bytes
87 for i in 0..core::cmp::min(read.len(), write.len()) {
88 read[i] = write[i].clone();
89 }
90 self.wrapped.transfer(read)?;
91 Ok(())
92 }
93 }
94}
95
96impl<T, E, Word> crate::spi::Write<Word> for BlockingAsync<T>
97where
98 E: 'static,
99 Word: Clone,
100 T: blocking::spi::Write<Word, Error = E>,
101{
102 #[rustfmt::skip]
103 type WriteFuture<'a> where Word: 'a, Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
104
105 fn write<'a>(&'a mut self, data: &'a [Word]) -> Self::WriteFuture<'a> {
106 async move { self.wrapped.write(data) }
107 }
108}
109
110impl<T, E, Word> crate::spi::Read<Word> for BlockingAsync<T>
111where
112 E: 'static,
113 Word: Clone,
114 T: blocking::spi::Transfer<Word, Error = E> + blocking::spi::Write<Word, Error = E>,
115{
116 #[rustfmt::skip]
117 type ReadFuture<'a> where Word: 'a, Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
118
119 fn read<'a>(&'a mut self, data: &'a mut [Word]) -> Self::ReadFuture<'a> {
120 async move {
121 self.wrapped.transfer(data)?;
122 Ok(())
123 }
124 }
125}
126
127// Uart implementatinos
128impl<T> crate::uart::Read for BlockingAsync<T>
129where
130 T: serial::Read<u8>,
131{
132 #[rustfmt::skip]
133 type ReadFuture<'a> where T: 'a = impl Future<Output = Result<(), crate::uart::Error>> + 'a;
134 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
135 async move {
136 let mut pos = 0;
137 while pos < buf.len() {
138 match self.wrapped.read() {
139 Err(nb::Error::WouldBlock) => {}
140 Err(_) => return Err(crate::uart::Error::Other),
141 Ok(b) => {
142 buf[pos] = b;
143 pos += 1;
144 }
145 }
146 }
147 Ok(())
148 }
149 }
150}
151
152impl<T> crate::uart::Write for BlockingAsync<T>
153where
154 T: blocking::serial::Write<u8>,
155{
156 #[rustfmt::skip]
157 type WriteFuture<'a> where T: 'a = impl Future<Output = Result<(), crate::uart::Error>> + 'a;
158 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
159 async move {
160 self.wrapped
161 .bwrite_all(buf)
162 .map_err(|_| crate::uart::Error::Other)?;
163 self.wrapped.bflush().map_err(|_| crate::uart::Error::Other)
164 }
165 }
166}
diff --git a/embassy-traits/src/lib.rs b/embassy-traits/src/lib.rs
index 65fb95bd4..a5342b77e 100644
--- a/embassy-traits/src/lib.rs
+++ b/embassy-traits/src/lib.rs
@@ -2,6 +2,7 @@
2#![feature(generic_associated_types)] 2#![feature(generic_associated_types)]
3#![feature(type_alias_impl_trait)] 3#![feature(type_alias_impl_trait)]
4 4
5pub mod adapter;
5pub mod delay; 6pub mod delay;
6pub mod flash; 7pub mod flash;
7pub mod gpio; 8pub mod gpio;