Merge pull request #17 from xoviat/implement-uart

implement uart on serial interface
This commit is contained in:
Dario Nieuwenhuis 2021-01-14 00:42:09 +01:00 committed by GitHub
commit 0204d4e812
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 42 deletions

View file

@ -8,6 +8,7 @@
use cortex_m::singleton; use cortex_m::singleton;
use cortex_m_rt::entry; use cortex_m_rt::entry;
use embassy::executor::{task, Executor}; use embassy::executor::{task, Executor};
use embassy::uart::Uart;
use embassy::util::Forever; use embassy::util::Forever;
use embassy_stm32f4::interrupt; use embassy_stm32f4::interrupt;
use embassy_stm32f4::serial; use embassy_stm32f4::serial;
@ -27,7 +28,8 @@ async fn run(dp: stm32::Peripherals, cp: cortex_m::Peripherals) {
.pclk1(24.mhz()) .pclk1(24.mhz())
.freeze(); .freeze();
let mut serial = serial::Serial::new( let mut serial = unsafe {
serial::Serial::new(
gpioa.pa9.into_alternate_af7(), gpioa.pa9.into_alternate_af7(),
gpioa.pa10.into_alternate_af7(), gpioa.pa10.into_alternate_af7(),
interrupt::take!(DMA2_STREAM7), interrupt::take!(DMA2_STREAM7),
@ -38,12 +40,11 @@ async fn run(dp: stm32::Peripherals, cp: cortex_m::Peripherals) {
config::Parity::ParityNone, config::Parity::ParityNone,
9600.bps(), 9600.bps(),
clocks, clocks,
); )
};
let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); let buf = singleton!(: [u8; 30] = [0; 30]).unwrap();
buf[5] = 0x01; buf[5] = 0x01;
serial.send(buf).await; serial.send(buf).await;
} }

View file

@ -10,8 +10,9 @@ use core::sync::atomic::{self, Ordering};
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use embassy::interrupt::OwnedInterrupt; use embassy::interrupt::OwnedInterrupt;
use embassy::uart::{Error, Uart};
use embassy::util::Signal; use embassy::util::Signal;
use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer}; use embedded_dma::StaticWriteBuffer;
use crate::hal::dma::config::DmaConfig; use crate::hal::dma::config::DmaConfig;
use crate::hal::dma::traits::{PeriAddress, Stream}; use crate::hal::dma::traits::{PeriAddress, Stream};
@ -56,7 +57,8 @@ static STATE: State = State {
static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut(); static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut();
impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
pub fn new( // Leaking futures is forbidden!
pub unsafe fn new(
txd: PA9<Alternate<AF7>>, txd: PA9<Alternate<AF7>>,
rxd: PA10<Alternate<AF7>>, rxd: PA10<Alternate<AF7>>,
tx_int: interrupt::DMA2_STREAM7Interrupt, tx_int: interrupt::DMA2_STREAM7Interrupt,
@ -135,18 +137,19 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
STATE.rx_int.signal(()); STATE.rx_int.signal(());
} }
}
impl Uart for Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
type SendFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
type ReceiveFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
/// Sends serial data. /// Sends serial data.
/// fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a> {
/// `tx_buffer` is marked as static as per `embedded-dma` requirements.
/// It it safe to use a buffer with a non static lifetime if memory is not
/// reused until the future has finished.
pub fn send<'a, B: 'a>(&'a mut self, tx_buffer: B) -> impl Future<Output = ()> + 'a
where
B: StaticWriteBuffer<Word = u8>,
{
unsafe { INSTANCE = self }; unsafe { INSTANCE = self };
#[allow(mutable_transmutes)]
let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) };
let tx_stream = self.tx_stream.take().unwrap(); let tx_stream = self.tx_stream.take().unwrap();
let usart = self.usart.take().unwrap(); let usart = self.usart.take().unwrap();
STATE.tx_int.reset(); STATE.tx_int.reset();
@ -155,7 +158,7 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
let mut tx_transfer = Transfer::init( let mut tx_transfer = Transfer::init(
tx_stream, tx_stream,
usart, usart,
tx_buffer, static_buf,
None, None,
DmaConfig::default() DmaConfig::default()
.transfer_complete_interrupt(true) .transfer_complete_interrupt(true)
@ -172,6 +175,8 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
let (tx_stream, usart, _buf, _) = tx_transfer.free(); let (tx_stream, usart, _buf, _) = tx_transfer.free();
self.tx_stream.replace(tx_stream); self.tx_stream.replace(tx_stream);
self.usart.replace(usart); self.usart.replace(usart);
Ok(())
} }
} }
@ -181,44 +186,32 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
/// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel
/// unfinished transfers after a timeout to prevent lockup when no more data /// unfinished transfers after a timeout to prevent lockup when no more data
/// is incoming. /// is incoming.
/// fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a> {
/// `rx_buffer` is marked as static as per `embedded-dma` requirements.
/// It it safe to use a buffer with a non static lifetime if memory is not
/// reused until the future has finished.
pub fn receive<'a, B: 'a>(&'a mut self, rx_buffer: B) -> impl Future<Output = B> + 'a
where
B: StaticWriteBuffer<Word = u8> + Unpin,
{
unsafe { INSTANCE = self }; unsafe { INSTANCE = self };
let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) };
let rx_stream = self.rx_stream.take().unwrap(); let rx_stream = self.rx_stream.take().unwrap();
let usart = self.usart.take().unwrap(); let usart = self.usart.take().unwrap();
STATE.rx_int.reset(); STATE.rx_int.reset();
async move { async move {
let mut rx_transfer = Transfer::init( let mut rx_transfer = Transfer::init(
rx_stream, rx_stream,
usart, usart,
rx_buffer, static_buf,
None, None,
DmaConfig::default() DmaConfig::default()
.transfer_complete_interrupt(true) .transfer_complete_interrupt(true)
.memory_increment(true) .memory_increment(true)
.double_buffer(false), .double_buffer(false),
); );
self.rx_int.unpend(); self.rx_int.unpend();
self.rx_int.enable(); self.rx_int.enable();
rx_transfer.start(|_usart| {}); rx_transfer.start(|_usart| {});
STATE.rx_int.wait().await; STATE.rx_int.wait().await;
let (rx_stream, usart, _, _) = rx_transfer.free();
let (rx_stream, usart, buf, _) = rx_transfer.free();
self.rx_stream.replace(rx_stream); self.rx_stream.replace(rx_stream);
self.usart.replace(usart); self.usart.replace(usart);
Ok(())
buf
} }
} }
} }