From 9bf09488f10b65401ec4c830c5b974c19508624f Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 4 Jan 2021 12:48:13 -0600 Subject: [PATCH] fix interrupts --- embassy-stm32f4/src/serial.rs | 90 +++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index 7efb4a0b..cc55ef32 100644 --- a/embassy-stm32f4/src/serial.rs +++ b/embassy-stm32f4/src/serial.rs @@ -5,6 +5,8 @@ //! are dropped correctly (e.g. not using `mem::forget()`). use core::future::Future; +use core::ptr; +use core::sync::atomic::{self, Ordering}; use core::task::{Context, Poll}; use embassy::interrupt::OwnedInterrupt; @@ -33,31 +35,32 @@ use crate::pac::{DMA2, USART1}; /// Interface to the Serial peripheral pub struct Serial, TSTREAM: Stream, RSTREAM: Stream> { - // tx_transfer: Transfer, Channel4, USART1, MemoryToPeripheral, &mut [u8; 20]>, - // rx_transfer: Transfer, Channel4, USART1, PeripheralToMemory, &mut [u8; 20]>, tx_stream: Option, rx_stream: Option, usart: Option, + tx_int: interrupt::DMA2_STREAM7Interrupt, + rx_int: interrupt::DMA2_STREAM2Interrupt, + usart_int: interrupt::USART1Interrupt, } struct State { - tx_done: Signal<()>, - rx_done: Signal<()>, - dma_done: Signal<()>, + tx_int: Signal<()>, + rx_int: Signal<()>, } static STATE: State = State { - tx_done: Signal::new(), - rx_done: Signal::new(), - dma_done: Signal::new(), + tx_int: Signal::new(), + rx_int: Signal::new(), }; +static mut INSTANCE: *const Serial, Stream2> = ptr::null_mut(); + impl Serial, Stream2> { pub fn new( txd: PA9>, rxd: PA10>, - tx_int: interrupt::DMA2_STREAM2Interrupt, - rx_int: interrupt::DMA2_STREAM7Interrupt, + tx_int: interrupt::DMA2_STREAM7Interrupt, + rx_int: interrupt::DMA2_STREAM2Interrupt, usart_int: interrupt::USART1Interrupt, dma: DMA2, usart: USART1, @@ -80,20 +83,14 @@ impl Serial, Stream2> { .unwrap(); serial.listen(SerialEvent::Idle); - serial.listen(SerialEvent::Txe); + // serial.listen(SerialEvent::Txe); let (usart, _) = serial.release(); // Register ISR tx_int.set_handler(Self::on_tx_irq); - tx_int.unpend(); - tx_int.enable(); - rx_int.set_handler(Self::on_rx_irq); - rx_int.unpend(); - rx_int.enable(); - - // usart_int.set_handler(Self::on_usart_irq); + usart_int.set_handler(Self::on_rx_irq); // usart_int.unpend(); // usart_int.enable(); @@ -103,40 +100,56 @@ impl Serial, Stream2> { tx_stream: Some(streams.7), rx_stream: Some(streams.2), usart: Some(usart), + tx_int: tx_int, + rx_int: rx_int, + usart_int: usart_int, } } unsafe fn on_tx_irq() { - STATE.tx_done.signal(()); + let s = &(*INSTANCE); + + s.tx_int.disable(); + + STATE.tx_int.signal(()); } unsafe fn on_rx_irq() { - STATE.rx_done.signal(()); + let s = &(*INSTANCE); + + atomic::compiler_fence(Ordering::Acquire); + s.rx_int.disable(); + s.usart_int.disable(); + atomic::compiler_fence(Ordering::Release); + + STATE.rx_int.signal(()); } unsafe fn on_usart_irq() { - /* - TODO: Signal tx_done if txe - */ + let s = &(*INSTANCE); - /* - TODO: Signal rx_done if idle - */ + atomic::compiler_fence(Ordering::Acquire); + s.rx_int.disable(); + s.usart_int.disable(); + atomic::compiler_fence(Ordering::Release); - // STATE.rx_done.signal(()); + STATE.rx_int.signal(()); } + /// Sends serial data. /// /// `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 mut self, tx_buffer: B) -> impl Future + 'a + pub fn send<'a, B: 'a>(&'a mut self, tx_buffer: B) -> impl Future + 'a where - B: WriteBuffer + 'static, + B: StaticWriteBuffer, { + unsafe { INSTANCE = self }; + let tx_stream = self.tx_stream.take().unwrap(); let usart = self.usart.take().unwrap(); - STATE.tx_done.reset(); + STATE.tx_int.reset(); async move { let mut tx_transfer = Transfer::init( @@ -150,9 +163,11 @@ impl Serial, Stream2> { .double_buffer(false), ); + self.tx_int.unpend(); + self.tx_int.enable(); tx_transfer.start(|_usart| {}); - STATE.tx_done.wait().await; + STATE.tx_int.wait().await; let (tx_stream, usart, _buf, _) = tx_transfer.free(); self.tx_stream.replace(tx_stream); @@ -170,13 +185,15 @@ impl Serial, Stream2> { /// `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 mut self, rx_buffer: B) -> impl Future + 'a + pub fn receive<'a, B: 'a>(&'a mut self, rx_buffer: B) -> impl Future + 'a where - B: WriteBuffer + 'static + Unpin, + B: StaticWriteBuffer + Unpin, { + unsafe { INSTANCE = self }; + let rx_stream = self.rx_stream.take().unwrap(); let usart = self.usart.take().unwrap(); - STATE.rx_done.reset(); + STATE.rx_int.reset(); async move { let mut rx_transfer = Transfer::init( @@ -190,9 +207,12 @@ impl Serial, Stream2> { .double_buffer(false), ); + self.rx_int.unpend(); + self.rx_int.enable(); + rx_transfer.start(|_usart| {}); - STATE.rx_done.wait().await; + STATE.rx_int.wait().await; let (rx_stream, usart, buf, _) = rx_transfer.free(); self.rx_stream.replace(rx_stream);