mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-22 14:53:03 +00:00
implement on irqs
This commit is contained in:
parent
cc8d162859
commit
d5cb9bebaa
@ -329,34 +329,34 @@ pub use stm32f4xx_hal::stm32 as pac;
|
|||||||
///
|
///
|
||||||
/// [`Waker`]: core::task::Waker
|
/// [`Waker`]: core::task::Waker
|
||||||
/// [`Future::poll`]: core::future::Future::poll
|
/// [`Future::poll`]: core::future::Future::poll
|
||||||
macro_rules! waker_interrupt {
|
// macro_rules! waker_interrupt {
|
||||||
($INT:ident, $waker:expr) => {{
|
// ($INT:ident, $waker:expr) => {{
|
||||||
use core::sync::atomic::{self, Ordering};
|
// use core::sync::atomic::{self, Ordering};
|
||||||
use core::task::Waker;
|
// use core::task::Waker;
|
||||||
use stm32f4xx_hal::pac::{interrupt, Interrupt, NVIC};
|
// use stm32f4xx_hal::pac::{interrupt, Interrupt, NVIC};
|
||||||
|
//
|
||||||
static mut WAKER: Option<Waker> = None;
|
// static mut WAKER: Option<Waker> = None;
|
||||||
|
//
|
||||||
#[interrupt]
|
// #[interrupt]
|
||||||
fn $INT() {
|
// fn $INT() {
|
||||||
// Safety: This context is disabled while the lower priority context accesses WAKER
|
// // Safety: This context is disabled while the lower priority context accesses WAKER
|
||||||
if let Some(waker) = unsafe { WAKER.as_ref() } {
|
// if let Some(waker) = unsafe { WAKER.as_ref() } {
|
||||||
waker.wake_by_ref();
|
// waker.wake_by_ref();
|
||||||
|
//
|
||||||
NVIC::mask(Interrupt::$INT);
|
// NVIC::mask(Interrupt::$INT);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
NVIC::mask(Interrupt::$INT);
|
// NVIC::mask(Interrupt::$INT);
|
||||||
atomic::compiler_fence(Ordering::Acquire);
|
// atomic::compiler_fence(Ordering::Acquire);
|
||||||
// Safety: The other relevant context, the interrupt, is disabled
|
// // Safety: The other relevant context, the interrupt, is disabled
|
||||||
unsafe { WAKER = Some($waker) }
|
// unsafe { WAKER = Some($waker) }
|
||||||
NVIC::unpend(Interrupt::$INT);
|
// NVIC::unpend(Interrupt::$INT);
|
||||||
atomic::compiler_fence(Ordering::Release);
|
// atomic::compiler_fence(Ordering::Release);
|
||||||
// Safety: This is the end of a mask-based critical section
|
// // Safety: This is the end of a mask-based critical section
|
||||||
unsafe { NVIC::unmask(Interrupt::$INT) }
|
// unsafe { NVIC::unmask(Interrupt::$INT) }
|
||||||
}};
|
// }};
|
||||||
}
|
// }
|
||||||
|
|
||||||
// This mod MUST go first, so that the others see its macros.
|
// This mod MUST go first, so that the others see its macros.
|
||||||
pub(crate) mod fmt;
|
pub(crate) mod fmt;
|
||||||
|
@ -4,31 +4,20 @@
|
|||||||
//! Lowest power consumption can only be guaranteed if the send receive futures
|
//! Lowest power consumption can only be guaranteed if the send receive futures
|
||||||
//! are dropped correctly (e.g. not using `mem::forget()`).
|
//! are dropped correctly (e.g. not using `mem::forget()`).
|
||||||
|
|
||||||
use core::cell::UnsafeCell;
|
|
||||||
use core::cmp::min;
|
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::marker::PhantomPinned;
|
|
||||||
use core::ops::Deref;
|
|
||||||
use core::pin::Pin;
|
|
||||||
use core::ptr;
|
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
|
||||||
use core::task::{Context, Poll};
|
use core::task::{Context, Poll};
|
||||||
use cortex_m::singleton;
|
|
||||||
|
|
||||||
|
use embassy::interrupt::OwnedInterrupt;
|
||||||
use embassy::util::Signal;
|
use embassy::util::Signal;
|
||||||
use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer};
|
use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer};
|
||||||
|
|
||||||
use crate::fmt::assert;
|
|
||||||
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};
|
||||||
use crate::hal::dma::{
|
use crate::hal::dma::{
|
||||||
Channel4, Channel7, MemoryToPeripheral, PeripheralToMemory, Stream2, Stream7, StreamsTuple,
|
Channel4, MemoryToPeripheral, PeripheralToMemory, Stream2, Stream7, StreamsTuple, Transfer,
|
||||||
Transfer,
|
|
||||||
};
|
};
|
||||||
use crate::hal::gpio::gpioa::{PA10, PA9};
|
use crate::hal::gpio::gpioa::{PA10, PA9};
|
||||||
use crate::hal::gpio::{Alternate, AF10, AF7, AF9};
|
use crate::hal::gpio::{Alternate, AF7};
|
||||||
use crate::hal::gpio::{Floating, Input, Output, PushPull};
|
|
||||||
use crate::hal::pac;
|
|
||||||
use crate::hal::prelude::*;
|
use crate::hal::prelude::*;
|
||||||
use crate::hal::rcc::Clocks;
|
use crate::hal::rcc::Clocks;
|
||||||
use crate::hal::serial::config::{
|
use crate::hal::serial::config::{
|
||||||
@ -42,8 +31,6 @@ use crate::interrupt;
|
|||||||
use crate::pac::Interrupt;
|
use crate::pac::Interrupt;
|
||||||
use crate::pac::{DMA2, USART1};
|
use crate::pac::{DMA2, USART1};
|
||||||
|
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
|
||||||
|
|
||||||
/// 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]>,
|
// tx_transfer: Transfer<Stream7<DMA2>, Channel4, USART1, MemoryToPeripheral, &mut [u8; 20]>,
|
||||||
@ -55,7 +42,7 @@ pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: St
|
|||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
tx_done: Signal<()>,
|
tx_done: Signal<()>,
|
||||||
rx_done: Signal<u32>,
|
rx_done: Signal<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static STATE: State = State {
|
static STATE: State = State {
|
||||||
@ -93,6 +80,15 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
|
|||||||
|
|
||||||
// serial.listen(SerialEvent::Idle);
|
// serial.listen(SerialEvent::Idle);
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
let streams = StreamsTuple::new(dma);
|
let streams = StreamsTuple::new(dma);
|
||||||
|
|
||||||
Serial {
|
Serial {
|
||||||
@ -102,6 +98,13 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn on_tx_irq() {
|
||||||
|
STATE.tx_done.signal(());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn on_rx_irq() {
|
||||||
|
STATE.rx_done.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.
|
||||||
@ -127,6 +130,8 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
|
|||||||
.double_buffer(false),
|
.double_buffer(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
STATE.tx_done.reset();
|
||||||
|
|
||||||
SendFuture {
|
SendFuture {
|
||||||
Serial: self,
|
Serial: self,
|
||||||
tx_transfer: Some(tx_transfer),
|
tx_transfer: Some(tx_transfer),
|
||||||
@ -166,6 +171,8 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
|
|||||||
.double_buffer(false),
|
.double_buffer(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
STATE.rx_done.reset();
|
||||||
|
|
||||||
ReceiveFuture {
|
ReceiveFuture {
|
||||||
Serial: self,
|
Serial: self,
|
||||||
rx_transfer: Some(rx_transfer),
|
rx_transfer: Some(rx_transfer),
|
||||||
@ -213,11 +220,12 @@ where
|
|||||||
|
|
||||||
Poll::Ready(())
|
Poll::Ready(())
|
||||||
} else {
|
} else {
|
||||||
waker_interrupt!(DMA2_STREAM7, cx.waker().clone());
|
// waker_interrupt!(DMA2_STREAM7, cx.waker().clone());
|
||||||
taken.start(|usart| {});
|
taken.start(|_usart| {});
|
||||||
tx_transfer.replace(taken);
|
tx_transfer.replace(taken);
|
||||||
|
|
||||||
Poll::Pending
|
// Poll::Pending
|
||||||
|
STATE.tx_done.poll_wait(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,11 +271,18 @@ where
|
|||||||
|
|
||||||
Poll::Ready(buf)
|
Poll::Ready(buf)
|
||||||
} else {
|
} else {
|
||||||
waker_interrupt!(DMA2_STREAM2, cx.waker().clone());
|
// waker_interrupt!(DMA2_STREAM2, cx.waker().clone());
|
||||||
|
|
||||||
taken.start(|usart| {});
|
taken.start(|_usart| {});
|
||||||
rx_transfer.replace(taken);
|
rx_transfer.replace(taken);
|
||||||
|
|
||||||
|
STATE.rx_done.poll_wait(cx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note: we have to do this because rx_transfer owns the buffer and we can't
|
||||||
|
access it until the transfer is completed. Therefore we can't pass
|
||||||
|
the buffer to poll_wait, but we still need to be woken.
|
||||||
|
*/
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user