stm32/dma: Store wakers in "associated statics"
This commit is contained in:
parent
a669f4cfd8
commit
fb53d74c57
@ -6,7 +6,6 @@ use core::task::Waker;
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
use super::{TransferOptions, Word, WordSize};
|
||||
use crate::_generated::BDMA_CHANNEL_COUNT;
|
||||
use crate::dma::Request;
|
||||
use crate::interrupt::{Interrupt, InterruptExt};
|
||||
use crate::pac;
|
||||
@ -22,21 +21,6 @@ impl From<WordSize> for vals::Size {
|
||||
}
|
||||
}
|
||||
|
||||
struct State {
|
||||
ch_wakers: [AtomicWaker; BDMA_CHANNEL_COUNT],
|
||||
}
|
||||
|
||||
impl State {
|
||||
const fn new() -> Self {
|
||||
const AW: AtomicWaker = AtomicWaker::new();
|
||||
Self {
|
||||
ch_wakers: [AW; BDMA_CHANNEL_COUNT],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static STATE: State = State::new();
|
||||
|
||||
/// safety: must be called only once
|
||||
pub(crate) unsafe fn init() {
|
||||
foreach_interrupt! {
|
||||
@ -52,6 +36,13 @@ foreach_dma_channel! {
|
||||
// BDMA1 in H7 doesn't use DMAMUX, which breaks
|
||||
};
|
||||
($channel_peri:ident, $dma_peri:ident, bdma, $channel_num:expr, $index:expr, $dmamux:tt) => {
|
||||
impl crate::peripherals::$channel_peri {
|
||||
fn waker() -> &'static AtomicWaker {
|
||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||
&WAKER
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
|
||||
|
||||
unsafe fn start_write<W: Word>(&mut self, _request: Request, buf: *const[W], reg_addr: *mut W, options: TransferOptions) {
|
||||
@ -153,12 +144,12 @@ foreach_dma_channel! {
|
||||
}
|
||||
|
||||
fn set_waker(&mut self, waker: &Waker) {
|
||||
unsafe { low_level_api::set_waker($index, waker) }
|
||||
Self::waker().register(waker);
|
||||
}
|
||||
|
||||
fn on_irq() {
|
||||
unsafe {
|
||||
low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index);
|
||||
low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, Self::waker());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -248,11 +239,6 @@ mod low_level_api {
|
||||
ch.ndtr().read().ndt() as u16
|
||||
}
|
||||
|
||||
/// Sets the waker for the specified DMA channel
|
||||
pub unsafe fn set_waker(state_number: usize, waker: &Waker) {
|
||||
STATE.ch_wakers[state_number].register(waker);
|
||||
}
|
||||
|
||||
pub unsafe fn reset_status(dma: pac::bdma::Dma, channel_number: u8) {
|
||||
dma.ifcr().write(|w| {
|
||||
w.set_tcif(channel_number as _, true);
|
||||
@ -261,9 +247,8 @@ mod low_level_api {
|
||||
}
|
||||
|
||||
/// Safety: Must be called with a matching set of parameters for a valid dma channel
|
||||
pub unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: u8, index: u8) {
|
||||
pub unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: u8, waker: &'static AtomicWaker) {
|
||||
let channel_num = channel_num as usize;
|
||||
let index = index as usize;
|
||||
|
||||
let isr = dma.isr().read();
|
||||
let cr = dma.ch(channel_num).cr();
|
||||
@ -273,7 +258,7 @@ mod low_level_api {
|
||||
}
|
||||
if isr.tcif(channel_num) && cr.read().tcie() {
|
||||
cr.write(|_| ()); // Disable channel interrupts with the default value.
|
||||
STATE.ch_wakers[index].wake();
|
||||
waker.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ use core::task::Waker;
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize};
|
||||
use crate::_generated::DMA_CHANNEL_COUNT;
|
||||
use crate::interrupt::{Interrupt, InterruptExt};
|
||||
use crate::pac::dma::{regs, vals};
|
||||
use crate::{interrupt, pac};
|
||||
@ -39,33 +38,6 @@ impl From<FlowControl> for vals::Pfctrl {
|
||||
}
|
||||
}
|
||||
|
||||
struct ChannelState {
|
||||
waker: AtomicWaker,
|
||||
}
|
||||
|
||||
impl ChannelState {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
waker: AtomicWaker::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct State {
|
||||
channels: [ChannelState; DMA_CHANNEL_COUNT],
|
||||
}
|
||||
|
||||
impl State {
|
||||
const fn new() -> Self {
|
||||
const CH: ChannelState = ChannelState::new();
|
||||
Self {
|
||||
channels: [CH; DMA_CHANNEL_COUNT],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static STATE: State = State::new();
|
||||
|
||||
/// safety: must be called only once
|
||||
pub(crate) unsafe fn init() {
|
||||
foreach_interrupt! {
|
||||
@ -78,6 +50,13 @@ pub(crate) unsafe fn init() {
|
||||
|
||||
foreach_dma_channel! {
|
||||
($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $index:expr, $dmamux:tt) => {
|
||||
impl crate::peripherals::$channel_peri {
|
||||
fn waker() -> &'static AtomicWaker {
|
||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||
&WAKER
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
|
||||
unsafe fn start_write<W: Word>(&mut self, request: Request, buf: *const [W], reg_addr: *mut W, options: TransferOptions) {
|
||||
let (ptr, len) = super::slice_ptr_parts(buf);
|
||||
@ -192,12 +171,12 @@ foreach_dma_channel! {
|
||||
}
|
||||
|
||||
fn set_waker(&mut self, waker: &Waker) {
|
||||
unsafe {low_level_api::set_waker($index, waker )}
|
||||
Self::waker().register(waker);
|
||||
}
|
||||
|
||||
fn on_irq() {
|
||||
unsafe {
|
||||
low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index);
|
||||
low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, Self::waker());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -381,11 +360,6 @@ mod low_level_api {
|
||||
ch.ndtr().read().ndt()
|
||||
}
|
||||
|
||||
/// Sets the waker for the specified DMA channel
|
||||
pub unsafe fn set_waker(state_number: usize, waker: &Waker) {
|
||||
STATE.channels[state_number].waker.register(waker);
|
||||
}
|
||||
|
||||
pub unsafe fn reset_status(dma: pac::dma::Dma, channel_number: u8) {
|
||||
let isrn = channel_number as usize / 4;
|
||||
let isrbit = channel_number as usize % 4;
|
||||
@ -397,9 +371,8 @@ mod low_level_api {
|
||||
}
|
||||
|
||||
/// Safety: Must be called with a matching set of parameters for a valid dma channel
|
||||
pub unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: u8, state_index: u8) {
|
||||
pub unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: u8, waker: &'static AtomicWaker) {
|
||||
let channel_num = channel_num as usize;
|
||||
let state_index = state_index as usize;
|
||||
|
||||
let cr = dma.st(channel_num).cr();
|
||||
let isr = dma.isr(channel_num / 4).read();
|
||||
@ -415,7 +388,7 @@ mod low_level_api {
|
||||
// for double buffered mode, clear TCIF flag but do not stop the transfer
|
||||
dma.ifcr(channel_num / 4).write(|w| w.set_tcif(channel_num % 4, true));
|
||||
}
|
||||
STATE.channels[state_index].waker.wake();
|
||||
waker.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ use core::task::Waker;
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
use super::{Request, TransferOptions, Word, WordSize};
|
||||
use crate::_generated::GPDMA_CHANNEL_COUNT;
|
||||
use crate::interrupt::{Interrupt, InterruptExt};
|
||||
use crate::pac::gpdma::{vals, Gpdma};
|
||||
use crate::{interrupt, pac};
|
||||
@ -19,33 +18,6 @@ impl From<WordSize> for vals::ChTr1Dw {
|
||||
}
|
||||
}
|
||||
|
||||
struct ChannelState {
|
||||
waker: AtomicWaker,
|
||||
}
|
||||
|
||||
impl ChannelState {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
waker: AtomicWaker::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct State {
|
||||
channels: [ChannelState; GPDMA_CHANNEL_COUNT],
|
||||
}
|
||||
|
||||
impl State {
|
||||
const fn new() -> Self {
|
||||
const CH: ChannelState = ChannelState::new();
|
||||
Self {
|
||||
channels: [CH; GPDMA_CHANNEL_COUNT],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static STATE: State = State::new();
|
||||
|
||||
/// safety: must be called only once
|
||||
pub(crate) unsafe fn init() {
|
||||
foreach_interrupt! {
|
||||
@ -58,6 +30,13 @@ pub(crate) unsafe fn init() {
|
||||
|
||||
foreach_dma_channel! {
|
||||
($channel_peri:ident, $dma_peri:ident, gpdma, $channel_num:expr, $index:expr, $dmamux:tt) => {
|
||||
impl crate::peripherals::$channel_peri {
|
||||
fn waker() -> &'static AtomicWaker {
|
||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||
&WAKER
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {
|
||||
unsafe fn start_write<W: Word>(&mut self, request: Request, buf: *const [W], reg_addr: *mut W, options: TransferOptions) {
|
||||
let (ptr, len) = super::slice_ptr_parts(buf);
|
||||
@ -144,12 +123,12 @@ foreach_dma_channel! {
|
||||
}
|
||||
|
||||
fn set_waker(&mut self, waker: &Waker) {
|
||||
unsafe {low_level_api::set_waker($index, waker )}
|
||||
Self::waker().register(waker);
|
||||
}
|
||||
|
||||
fn on_irq() {
|
||||
unsafe {
|
||||
low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index);
|
||||
low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, Self::waker());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -257,15 +236,9 @@ mod low_level_api {
|
||||
ch.br1().read().bndt()
|
||||
}
|
||||
|
||||
/// Sets the waker for the specified DMA channel
|
||||
pub unsafe fn set_waker(state_number: usize, waker: &Waker) {
|
||||
STATE.channels[state_number].waker.register(waker);
|
||||
}
|
||||
|
||||
/// Safety: Must be called with a matching set of parameters for a valid dma channel
|
||||
pub unsafe fn on_irq_inner(dma: Gpdma, channel_num: u8, state_index: u8) {
|
||||
pub unsafe fn on_irq_inner(dma: Gpdma, channel_num: u8, waker: &'static AtomicWaker) {
|
||||
let channel_num = channel_num as usize;
|
||||
let state_index = state_index as usize;
|
||||
|
||||
let ch = dma.ch(channel_num);
|
||||
let sr = ch.sr().read();
|
||||
@ -285,7 +258,7 @@ mod low_level_api {
|
||||
|
||||
if sr.suspf() || sr.tcf() {
|
||||
ch.cr().write(|w| w.set_reset(true));
|
||||
STATE.channels[state_index].waker.wake();
|
||||
waker.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user