Skip to content
This repository was archived by the owner on Sep 2, 2025. It is now read-only.

Commit ab1b0a7

Browse files
committed
Implement async traits for serial
1 parent 0aeca2d commit ab1b0a7

File tree

1 file changed

+218
-0
lines changed

1 file changed

+218
-0
lines changed

src/serial.rs

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,224 @@ impl<UART: UartX> serial::Write<u8> for Tx<UART> {
155155
}
156156
}
157157

158+
#[cfg(feature = "async-traits")]
159+
mod async_impls {
160+
use core::convert::Infallible;
161+
use core::future::Future;
162+
use core::pin::Pin;
163+
use core::task::{Context, Poll};
164+
use async_embedded_traits::serial::{AsyncRead, AsyncWrite};
165+
use super::{UartX, Serial, Rx, Tx, uart0::RegisterBlock};
166+
167+
impl<UART: UartX + 'static, PINS> AsyncRead for Serial<UART, PINS> {
168+
type Error = Infallible;
169+
type ReadByteFuture<'f> = AsyncReadByteFuture<'f>;
170+
type ReadFuture<'f> = AsyncReadFuture<'f>;
171+
172+
fn async_read_byte(&mut self) -> Self::ReadByteFuture<'_> {
173+
AsyncReadByteFuture {
174+
uart: &self.uart,
175+
}
176+
}
177+
178+
fn async_read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'_> {
179+
AsyncReadFuture {
180+
uart: &self.uart,
181+
data,
182+
offset: 0
183+
}
184+
}
185+
}
186+
187+
impl<UART: UartX + 'static> AsyncRead for Rx<UART> {
188+
type Error = Infallible;
189+
type ReadByteFuture<'f> = AsyncReadByteFuture<'f>;
190+
type ReadFuture<'f> = AsyncReadFuture<'f>;
191+
192+
fn async_read_byte(&mut self) -> Self::ReadByteFuture<'_> {
193+
AsyncReadByteFuture {
194+
uart: &self.uart,
195+
}
196+
}
197+
198+
fn async_read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'_> {
199+
AsyncReadFuture {
200+
uart: &self.uart,
201+
data,
202+
offset: 0
203+
}
204+
}
205+
}
206+
207+
pub struct AsyncReadByteFuture<'a> {
208+
uart: &'a RegisterBlock,
209+
}
210+
211+
impl<'a> Future for AsyncReadByteFuture<'a> {
212+
type Output = Result<u8, Infallible>;
213+
214+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
215+
let rxdata = self.uart.rxdata.read();
216+
217+
if rxdata.empty().bit_is_set() {
218+
// TODO: replace with something useful
219+
cx.waker().wake_by_ref();
220+
Poll::Pending
221+
} else {
222+
let byte = rxdata.data().bits() as u8;
223+
Poll::Ready(Ok(byte))
224+
}
225+
}
226+
}
227+
228+
pub struct AsyncReadFuture<'a> {
229+
uart: &'a RegisterBlock,
230+
data: &'a mut [u8],
231+
offset: usize,
232+
}
233+
234+
impl<'a> Future for AsyncReadFuture<'a> {
235+
type Output = Result<(), Infallible>;
236+
237+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
238+
while self.offset < self.data.len() {
239+
let rxdata = self.uart.rxdata.read();
240+
241+
if rxdata.empty().bit_is_set() {
242+
// TODO: replace with something useful
243+
cx.waker().wake_by_ref();
244+
return Poll::Pending
245+
} else {
246+
let byte = rxdata.data().bits() as u8;
247+
let offset = self.offset; // Stupid Rust
248+
self.data[offset] = byte;
249+
self.offset += 1;
250+
}
251+
}
252+
Poll::Ready(Ok(()))
253+
}
254+
}
255+
256+
impl<UART: UartX + 'static, PINS> AsyncWrite for Serial<UART, PINS> {
257+
type Error = Infallible;
258+
type WriteByteFuture<'t> = AsyncWriteByteFuture<'t>;
259+
type WriteFuture<'t> = AsyncWriteFuture<'t>;
260+
type FlushFuture<'t> = AsyncFlushFuture<'t>;
261+
262+
fn async_write_byte(&mut self, byte: u8) -> Self::WriteByteFuture<'_> {
263+
AsyncWriteByteFuture {
264+
uart: &self.uart,
265+
byte
266+
}
267+
}
268+
269+
fn async_write<'a>(&'a mut self, data: &'a [u8]) -> AsyncWriteFuture<'a> {
270+
AsyncWriteFuture {
271+
uart: &self.uart,
272+
data,
273+
}
274+
}
275+
276+
fn async_flush(&mut self) -> AsyncFlushFuture<'_> {
277+
AsyncFlushFuture {
278+
uart: &self.uart,
279+
}
280+
}
281+
}
282+
283+
impl<UART: UartX + 'static> AsyncWrite for Tx<UART> {
284+
type Error = Infallible;
285+
type WriteByteFuture<'t> = AsyncWriteByteFuture<'t>;
286+
type WriteFuture<'t> = AsyncWriteFuture<'t>;
287+
type FlushFuture<'t> = AsyncFlushFuture<'t>;
288+
289+
fn async_write_byte(&mut self, byte: u8) -> Self::WriteByteFuture<'_> {
290+
AsyncWriteByteFuture {
291+
uart: &self.uart,
292+
byte
293+
}
294+
}
295+
296+
fn async_write<'a>(&'a mut self, data: &'a [u8]) -> AsyncWriteFuture<'a> {
297+
AsyncWriteFuture {
298+
uart: &self.uart,
299+
data,
300+
}
301+
}
302+
303+
fn async_flush(&mut self) -> AsyncFlushFuture<'_> {
304+
AsyncFlushFuture {
305+
uart: &self.uart,
306+
}
307+
}
308+
}
309+
310+
pub struct AsyncWriteByteFuture<'a> {
311+
uart: &'a RegisterBlock,
312+
byte: u8,
313+
}
314+
315+
impl<'a> Future for AsyncWriteByteFuture<'a> {
316+
type Output = Result<(), Infallible>;
317+
318+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
319+
let txdata = self.uart.txdata.read();
320+
321+
if txdata.full().bit_is_set() {
322+
cx.waker().wake_by_ref();
323+
Poll::Pending
324+
} else {
325+
unsafe {
326+
self.uart.txdata.write(|w| w.data().bits(self.byte));
327+
}
328+
Poll::Ready(Ok(()))
329+
}
330+
}
331+
}
332+
333+
pub struct AsyncWriteFuture<'a> {
334+
uart: &'a RegisterBlock,
335+
data: &'a [u8],
336+
}
337+
338+
impl<'a> Future for AsyncWriteFuture<'a> {
339+
type Output = Result<(), Infallible>;
340+
341+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
342+
while let Some(byte) = self.data.first() {
343+
let txdata = self.uart.txdata.read();
344+
345+
if txdata.full().bit_is_set() {
346+
cx.waker().wake_by_ref();
347+
return Poll::Pending;
348+
} else {
349+
self.uart.txdata.write(|w| unsafe { w.data().bits(*byte) });
350+
self.data = &self.data[1..];
351+
}
352+
}
353+
Poll::Ready(Ok(()))
354+
}
355+
}
356+
357+
pub struct AsyncFlushFuture<'a> {
358+
uart: &'a RegisterBlock,
359+
}
360+
361+
impl<'a> Future for AsyncFlushFuture<'a> {
362+
type Output = Result<(), Infallible>;
363+
364+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
365+
if self.uart.ip.read().txwm().bit_is_set() {
366+
// FIFO count is below the receive watermark (1)
367+
Poll::Ready(Ok(()))
368+
} else {
369+
cx.waker().wake_by_ref();
370+
Poll::Pending
371+
}
372+
}
373+
}
374+
}
375+
158376
// Backward compatibility
159377
impl<TX, RX> Serial<UART0, (TX, RX)> {
160378
/// Configures a UART peripheral to provide serial communication

0 commit comments

Comments
 (0)