fix interrupts

This commit is contained in:
xoviat 2021-01-04 12:48:13 -06:00
parent 2ee2d18465
commit 9bf09488f1

View File

@ -5,6 +5,8 @@
//! are dropped correctly (e.g. not using `mem::forget()`). //! are dropped correctly (e.g. not using `mem::forget()`).
use core::future::Future; use core::future::Future;
use core::ptr;
use core::sync::atomic::{self, Ordering};
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use embassy::interrupt::OwnedInterrupt; use embassy::interrupt::OwnedInterrupt;
@ -33,31 +35,32 @@ use crate::pac::{DMA2, USART1};
/// Interface to the Serial peripheral /// Interface to the Serial peripheral
pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> { pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> {
// tx_transfer: Transfer<Stream7<DMA2>, Channel4, USART1, MemoryToPeripheral, &mut [u8; 20]>,
// rx_transfer: Transfer<Stream2<DMA2>, Channel4, USART1, PeripheralToMemory, &mut [u8; 20]>,
tx_stream: Option<TSTREAM>, tx_stream: Option<TSTREAM>,
rx_stream: Option<RSTREAM>, rx_stream: Option<RSTREAM>,
usart: Option<USART>, usart: Option<USART>,
tx_int: interrupt::DMA2_STREAM7Interrupt,
rx_int: interrupt::DMA2_STREAM2Interrupt,
usart_int: interrupt::USART1Interrupt,
} }
struct State { struct State {
tx_done: Signal<()>, tx_int: Signal<()>,
rx_done: Signal<()>, rx_int: Signal<()>,
dma_done: Signal<()>,
} }
static STATE: State = State { static STATE: State = State {
tx_done: Signal::new(), tx_int: Signal::new(),
rx_done: Signal::new(), rx_int: Signal::new(),
dma_done: Signal::new(),
}; };
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( pub fn new(
txd: PA9<Alternate<AF7>>, txd: PA9<Alternate<AF7>>,
rxd: PA10<Alternate<AF7>>, rxd: PA10<Alternate<AF7>>,
tx_int: interrupt::DMA2_STREAM2Interrupt, tx_int: interrupt::DMA2_STREAM7Interrupt,
rx_int: interrupt::DMA2_STREAM7Interrupt, rx_int: interrupt::DMA2_STREAM2Interrupt,
usart_int: interrupt::USART1Interrupt, usart_int: interrupt::USART1Interrupt,
dma: DMA2, dma: DMA2,
usart: USART1, usart: USART1,
@ -80,20 +83,14 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
.unwrap(); .unwrap();
serial.listen(SerialEvent::Idle); serial.listen(SerialEvent::Idle);
serial.listen(SerialEvent::Txe); // serial.listen(SerialEvent::Txe);
let (usart, _) = serial.release(); let (usart, _) = serial.release();
// Register ISR // Register ISR
tx_int.set_handler(Self::on_tx_irq); tx_int.set_handler(Self::on_tx_irq);
tx_int.unpend();
tx_int.enable();
rx_int.set_handler(Self::on_rx_irq); rx_int.set_handler(Self::on_rx_irq);
rx_int.unpend(); usart_int.set_handler(Self::on_rx_irq);
rx_int.enable();
// usart_int.set_handler(Self::on_usart_irq);
// usart_int.unpend(); // usart_int.unpend();
// usart_int.enable(); // usart_int.enable();
@ -103,40 +100,56 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
tx_stream: Some(streams.7), tx_stream: Some(streams.7),
rx_stream: Some(streams.2), rx_stream: Some(streams.2),
usart: Some(usart), usart: Some(usart),
tx_int: tx_int,
rx_int: rx_int,
usart_int: usart_int,
} }
} }
unsafe fn on_tx_irq() { 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() { 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() { unsafe fn on_usart_irq() {
/* let s = &(*INSTANCE);
TODO: Signal tx_done if txe
*/
/* atomic::compiler_fence(Ordering::Acquire);
TODO: Signal rx_done if idle s.rx_int.disable();
*/ s.usart_int.disable();
atomic::compiler_fence(Ordering::Release);
// STATE.rx_done.signal(()); STATE.rx_int.signal(());
} }
/// Sends serial data. /// Sends serial data.
/// ///
/// `tx_buffer` is marked as static as per `embedded-dma` requirements. /// `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 /// It it safe to use a buffer with a non static lifetime if memory is not
/// reused until the future has finished. /// reused until the future has finished.
pub fn send<'a, B>(&'a mut self, tx_buffer: B) -> impl Future<Output = ()> + 'a pub fn send<'a, B: 'a>(&'a mut self, tx_buffer: B) -> impl Future<Output = ()> + 'a
where where
B: WriteBuffer<Word = u8> + 'static, B: StaticWriteBuffer<Word = u8>,
{ {
unsafe { INSTANCE = self };
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_done.reset(); STATE.tx_int.reset();
async move { async move {
let mut tx_transfer = Transfer::init( let mut tx_transfer = Transfer::init(
@ -150,9 +163,11 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
.double_buffer(false), .double_buffer(false),
); );
self.tx_int.unpend();
self.tx_int.enable();
tx_transfer.start(|_usart| {}); tx_transfer.start(|_usart| {});
STATE.tx_done.wait().await; STATE.tx_int.wait().await;
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);
@ -170,13 +185,15 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
/// `rx_buffer` is marked as static as per `embedded-dma` requirements. /// `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 /// It it safe to use a buffer with a non static lifetime if memory is not
/// reused until the future has finished. /// reused until the future has finished.
pub fn receive<'a, B>(&'a mut self, rx_buffer: B) -> impl Future<Output = B> + 'a pub fn receive<'a, B: 'a>(&'a mut self, rx_buffer: B) -> impl Future<Output = B> + 'a
where where
B: WriteBuffer<Word = u8> + 'static + Unpin, B: StaticWriteBuffer<Word = u8> + Unpin,
{ {
unsafe { INSTANCE = self };
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_done.reset(); STATE.rx_int.reset();
async move { async move {
let mut rx_transfer = Transfer::init( let mut rx_transfer = Transfer::init(
@ -190,9 +207,12 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
.double_buffer(false), .double_buffer(false),
); );
self.rx_int.unpend();
self.rx_int.enable();
rx_transfer.start(|_usart| {}); rx_transfer.start(|_usart| {});
STATE.rx_done.wait().await; STATE.rx_int.wait().await;
let (rx_stream, usart, buf, _) = rx_transfer.free(); let (rx_stream, usart, buf, _) = rx_transfer.free();
self.rx_stream.replace(rx_stream); self.rx_stream.replace(rx_stream);