fix interrupts
This commit is contained in:
parent
2ee2d18465
commit
9bf09488f1
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user