stm32f4: implement idle on serial

This commit is contained in:
xoviat 2021-03-20 23:51:24 -05:00
parent d1ac703830
commit 556942a6bf
2 changed files with 31 additions and 12 deletions

View file

@ -36,6 +36,7 @@ defmt = { version = "0.2.0", optional = true }
log = { version = "0.4.11", optional = true }
cortex-m-rt = "0.6.13"
cortex-m = "0.7.1"
futures = { version = "0.3.5", default-features = false, features = ["async-await"] }
embedded-hal = { version = "0.2.4" }
embedded-dma = { version = "0.1.2" }
stm32f4xx-hal = { version = "0.8.3", features = ["rt", "can"], git = "https://github.com/stm32-rs/stm32f4xx-hal.git"}

View file

@ -7,6 +7,8 @@
use core::future::Future;
use core::marker::PhantomData;
use futures::{select_biased, FutureExt};
use embassy::interrupt::Interrupt;
use embassy::traits::uart::{Error, Uart};
use embassy::util::InterruptFuture;
@ -19,7 +21,7 @@ use crate::hal::{
rcc::Clocks,
serial,
serial::config::{Config as SerialConfig, DmaConfig as SerialDmaConfig},
serial::{Event as SerialEvent, Pins, Serial as HalSerial},
serial::{Event as SerialEvent, Pins},
};
use crate::interrupt;
use crate::pac;
@ -29,14 +31,14 @@ pub struct Serial<
USART: PeriAddress<MemSize = u8> + WithInterrupt,
TSTREAM: Stream + WithInterrupt,
RSTREAM: Stream + WithInterrupt,
CHANNEL: dma::traits::Channel,
CHANNEL: Channel,
> {
tx_stream: Option<TSTREAM>,
rx_stream: Option<RSTREAM>,
usart: Option<USART>,
tx_int: TSTREAM::Interrupt,
rx_int: RSTREAM::Interrupt,
_usart_int: USART::Interrupt,
usart_int: USART::Interrupt,
channel: PhantomData<CHANNEL>,
}
@ -68,12 +70,10 @@ where
PINS: Pins<USART>,
{
config.dma = SerialDmaConfig::TxRx;
let mut serial = HalSerial::new(usart, pins, config, clocks).unwrap();
serial.listen(SerialEvent::Idle);
// serial.listen(SerialEvent::Txe);
let (usart, _) = serial.release();
let (usart, _) = serial::Serial::new(usart, pins, config, clocks)
.unwrap()
.release();
let (tx_stream, rx_stream) = streams;
@ -83,8 +83,8 @@ where
usart: Some(usart),
tx_int: tx_int,
rx_int: rx_int,
_usart_int: usart_int,
channel: core::marker::PhantomData,
usart_int: usart_int,
channel: PhantomData,
}
}
}
@ -127,10 +127,10 @@ where
let fut = InterruptFuture::new(&mut self.tx_int);
tx_transfer.start(|_usart| {});
fut.await;
let (tx_stream, usart, _buf, _) = tx_transfer.free();
self.tx_stream.replace(tx_stream);
self.usart.replace(usart);
@ -151,6 +151,15 @@ where
let usart = self.usart.take().unwrap();
async move {
unsafe {
/* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */
(*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit());
/* __HAL_UART_CLEAR_IDLEFLAG(&uart->UartHandle); */
(*USART::ptr()).sr.read();
(*USART::ptr()).dr.read();
};
let mut rx_transfer = Transfer::init(
rx_stream,
usart,
@ -163,11 +172,20 @@ where
);
let fut = InterruptFuture::new(&mut self.rx_int);
let fut_idle = InterruptFuture::new(&mut self.usart_int);
rx_transfer.start(|_usart| {});
fut.await;
select_biased! {
() = fut.fuse() => {},
() = fut_idle.fuse() => {},
}
let (rx_stream, usart, _, _) = rx_transfer.free();
unsafe {
(*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit());
}
self.rx_stream.replace(rx_stream);
self.usart.replace(usart);