Mix dmamux into bdma_v1.
This commit is contained in:
parent
6ec7253095
commit
f01ddd5f5c
@ -6,25 +6,3 @@ mod _version;
|
|||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub use _version::*;
|
pub use _version::*;
|
||||||
|
|
||||||
use core::future::Future;
|
|
||||||
|
|
||||||
pub trait WriteDma<T> {
|
|
||||||
type WriteDmaFuture<'a>: Future<Output = ()> + 'a
|
|
||||||
where
|
|
||||||
Self: 'a;
|
|
||||||
|
|
||||||
fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
|
|
||||||
where
|
|
||||||
T: 'a;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ReadDma<T> {
|
|
||||||
type ReadDmaFuture<'a>: Future<Output = ()> + 'a
|
|
||||||
where
|
|
||||||
Self: 'a;
|
|
||||||
|
|
||||||
fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a>
|
|
||||||
where
|
|
||||||
T: 'a;
|
|
||||||
}
|
|
||||||
|
@ -6,10 +6,11 @@ use embassy::interrupt::{Interrupt, InterruptExt};
|
|||||||
use embassy::util::{AtomicWaker, OnDrop};
|
use embassy::util::{AtomicWaker, OnDrop};
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
|
|
||||||
use super::{ReadDma, WriteDma};
|
use crate::dma_traits::{ReadDma, WriteDma};
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::pac::bdma::vals;
|
use crate::pac::bdma::vals;
|
||||||
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
|
|
||||||
const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8;
|
const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8;
|
||||||
const CH_STATUS_NONE: u8 = 0;
|
const CH_STATUS_NONE: u8 = 0;
|
||||||
@ -57,6 +58,9 @@ pub(crate) async unsafe fn transfer_p2m(
|
|||||||
while regs.cr().read().en() {}
|
while regs.cr().read().en() {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[cfg(dmamux)]
|
||||||
|
crate::dmamux::configure_channel(1, 2);
|
||||||
|
|
||||||
regs.par().write_value(src as u32);
|
regs.par().write_value(src as u32);
|
||||||
regs.mar().write_value(dst.as_mut_ptr() as u32);
|
regs.mar().write_value(dst.as_mut_ptr() as u32);
|
||||||
regs.ndtr().write(|w| w.set_ndt(dst.len() as u16));
|
regs.ndtr().write(|w| w.set_ndt(dst.len() as u16));
|
||||||
@ -88,6 +92,9 @@ pub(crate) async unsafe fn transfer_m2p(
|
|||||||
state_number: usize,
|
state_number: usize,
|
||||||
src: &[u8],
|
src: &[u8],
|
||||||
dst: *mut u8,
|
dst: *mut u8,
|
||||||
|
#[cfg(dmamux)] dmamux_regs: &'static pac::dmamux::Dmamux,
|
||||||
|
#[cfg(dmamux)] dmamux_ch_num: u8,
|
||||||
|
#[cfg(dmamux)] request: u8,
|
||||||
) {
|
) {
|
||||||
// ndtr is max 16 bits.
|
// ndtr is max 16 bits.
|
||||||
assert!(src.len() <= 0xFFFF);
|
assert!(src.len() <= 0xFFFF);
|
||||||
@ -105,6 +112,9 @@ pub(crate) async unsafe fn transfer_m2p(
|
|||||||
while regs.cr().read().en() {}
|
while regs.cr().read().en() {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[cfg(dmamux)]
|
||||||
|
crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
|
||||||
|
|
||||||
regs.par().write_value(dst as u32);
|
regs.par().write_value(dst as u32);
|
||||||
regs.mar().write_value(src.as_ptr() as u32);
|
regs.mar().write_value(src.as_ptr() as u32);
|
||||||
regs.ndtr().write(|w| w.set_ndt(src.len() as u16));
|
regs.ndtr().write(|w| w.set_ndt(src.len() as u16));
|
||||||
@ -161,9 +171,10 @@ pub(crate) unsafe fn init() {
|
|||||||
}
|
}
|
||||||
pac::peripherals! {
|
pac::peripherals! {
|
||||||
(bdma, DMA1) => {
|
(bdma, DMA1) => {
|
||||||
critical_section::with(|_| {
|
//critical_section::with(|_| {
|
||||||
pac::RCC.ahbenr().modify(|w| w.set_dmaen(true));
|
//pac::RCC.ahbenr().modify(|w| w.set_dmaen(true));
|
||||||
});
|
//});
|
||||||
|
crate::peripherals::DMA1::enable();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,8 +231,10 @@ macro_rules! impl_dma_channel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(dmamux))]
|
||||||
impl<T> WriteDma<T> for crate::peripherals::$channel_peri
|
impl<T> WriteDma<T> for crate::peripherals::$channel_peri
|
||||||
where
|
where
|
||||||
|
Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>,
|
||||||
T: 'static,
|
T: 'static,
|
||||||
{
|
{
|
||||||
type WriteDmaFuture<'a> = impl Future<Output = ()>;
|
type WriteDmaFuture<'a> = impl Future<Output = ()>;
|
||||||
@ -234,10 +247,47 @@ macro_rules! impl_dma_channel {
|
|||||||
|
|
||||||
let state_num = self.state_num();
|
let state_num = self.state_num();
|
||||||
let regs = self.regs();
|
let regs = self.regs();
|
||||||
|
|
||||||
unsafe { transfer_m2p(regs, state_num, buf, dst) }
|
unsafe { transfer_m2p(regs, state_num, buf, dst) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(dmamux)]
|
||||||
|
impl<T> WriteDma<T> for crate::peripherals::$channel_peri
|
||||||
|
where
|
||||||
|
Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>,
|
||||||
|
T: 'static,
|
||||||
|
{
|
||||||
|
type WriteDmaFuture<'a> = impl Future<Output = ()>;
|
||||||
|
|
||||||
|
fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
|
||||||
|
where
|
||||||
|
T: 'a,
|
||||||
|
{
|
||||||
|
use sealed::Channel as _Channel;
|
||||||
|
|
||||||
|
let state_num = self.state_num();
|
||||||
|
let regs = self.regs();
|
||||||
|
|
||||||
|
use crate::dmamux::sealed::Channel as _MuxChannel;
|
||||||
|
use crate::dmamux::sealed::PeripheralChannel;
|
||||||
|
let dmamux_regs = self.dmamux_regs();
|
||||||
|
let dmamux_ch_num = self.dma_ch_num();
|
||||||
|
let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self);
|
||||||
|
unsafe {
|
||||||
|
transfer_m2p(
|
||||||
|
regs,
|
||||||
|
state_num,
|
||||||
|
buf,
|
||||||
|
dst,
|
||||||
|
dmamux_regs,
|
||||||
|
dmamux_ch_num,
|
||||||
|
request,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> ReadDma<T> for crate::peripherals::$channel_peri
|
impl<T> ReadDma<T> for crate::peripherals::$channel_peri
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static,
|
||||||
@ -292,6 +342,8 @@ pac::interrupts! {
|
|||||||
|
|
||||||
#[cfg(usart)]
|
#[cfg(usart)]
|
||||||
use crate::usart;
|
use crate::usart;
|
||||||
|
|
||||||
|
#[cfg(not(dmamux))]
|
||||||
pac::peripheral_dma_channels! {
|
pac::peripheral_dma_channels! {
|
||||||
($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
|
($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
|
||||||
impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
@ -302,4 +354,34 @@ pac::peripheral_dma_channels! {
|
|||||||
impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
($peri:ident, uart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
|
||||||
|
impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
|
impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
|
};
|
||||||
|
|
||||||
|
($peri:ident, uart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
|
||||||
|
impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
|
impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(dmamux)]
|
||||||
|
pac::peripherals! {
|
||||||
|
(usart, $peri:ident) => {
|
||||||
|
pac::dma_channels! {
|
||||||
|
($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
|
||||||
|
impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
|
impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(uart, $peri:ident) => {
|
||||||
|
pac::dma_channels! {
|
||||||
|
($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
|
||||||
|
impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
|
impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
#[cfg(dma)]
|
|
||||||
#[cfg_attr(dma_v1, path = "v1.rs")]
|
#[cfg_attr(dma_v1, path = "v1.rs")]
|
||||||
#[cfg_attr(dma_v2, path = "v2.rs")]
|
#[cfg_attr(dma_v2, path = "v2.rs")]
|
||||||
mod _version;
|
mod _version;
|
||||||
@ -8,25 +7,3 @@ mod _version;
|
|||||||
#[cfg(dma)]
|
#[cfg(dma)]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub use _version::*;
|
pub use _version::*;
|
||||||
|
|
||||||
use core::future::Future;
|
|
||||||
|
|
||||||
pub trait WriteDma<T> {
|
|
||||||
type WriteDmaFuture<'a>: Future<Output = ()> + 'a
|
|
||||||
where
|
|
||||||
Self: 'a;
|
|
||||||
|
|
||||||
fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
|
|
||||||
where
|
|
||||||
T: 'a;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ReadDma<T> {
|
|
||||||
type ReadDmaFuture<'a>: Future<Output = ()> + 'a
|
|
||||||
where
|
|
||||||
Self: 'a;
|
|
||||||
|
|
||||||
fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a>
|
|
||||||
where
|
|
||||||
T: 'a;
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
|
use crate::dma_traits::{ReadDma, WriteDma};
|
||||||
use atomic_polyfill::{AtomicU8, Ordering};
|
use atomic_polyfill::{AtomicU8, Ordering};
|
||||||
use embassy::interrupt::{Interrupt, InterruptExt};
|
use embassy::interrupt::{Interrupt, InterruptExt};
|
||||||
use embassy::util::AtomicWaker;
|
use embassy::util::AtomicWaker;
|
||||||
|
21
embassy-stm32/src/dma_traits.rs
Normal file
21
embassy-stm32/src/dma_traits.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use core::future::Future;
|
||||||
|
|
||||||
|
pub trait WriteDma<T> {
|
||||||
|
type WriteDmaFuture<'a>: Future<Output = ()> + 'a
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
|
||||||
|
where
|
||||||
|
T: 'a;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ReadDma<T> {
|
||||||
|
type ReadDmaFuture<'a>: Future<Output = ()> + 'a
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a>
|
||||||
|
where
|
||||||
|
T: 'a;
|
||||||
|
}
|
@ -20,41 +20,11 @@ use crate::peripherals;
|
|||||||
|
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
|
|
||||||
use crate::dma::{ReadDma, WriteDma};
|
use crate::dma_traits::{ReadDma, WriteDma};
|
||||||
|
|
||||||
const CH_COUNT: usize = peripheral_count!(DMA) * 8;
|
pub(crate) fn configure_channel(ch_num: u8, request_num: u8) {}
|
||||||
const CH_STATUS_NONE: u8 = 0;
|
|
||||||
const CH_STATUS_COMPLETED: u8 = 1;
|
|
||||||
const CH_STATUS_ERROR: u8 = 2;
|
|
||||||
|
|
||||||
struct State {
|
|
||||||
ch_wakers: [AtomicWaker; CH_COUNT],
|
|
||||||
ch_status: [AtomicU8; CH_COUNT],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl State {
|
|
||||||
const fn new() -> Self {
|
|
||||||
const AW: AtomicWaker = AtomicWaker::new();
|
|
||||||
const AU: AtomicU8 = AtomicU8::new(CH_STATUS_NONE);
|
|
||||||
Self {
|
|
||||||
ch_wakers: [AW; CH_COUNT],
|
|
||||||
ch_status: [AU; CH_COUNT],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static STATE: State = State::new();
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) async unsafe fn transfer_p2m(
|
|
||||||
ch: &mut impl Channel,
|
|
||||||
ch_func: u8,
|
|
||||||
src: *const u8,
|
|
||||||
dst: &mut [u8],
|
|
||||||
) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/*
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub(crate) async unsafe fn transfer_m2p(
|
pub(crate) async unsafe fn transfer_m2p(
|
||||||
ch: &mut impl Channel,
|
ch: &mut impl Channel,
|
||||||
@ -128,22 +98,36 @@ pub(crate) async unsafe fn transfer_m2p(
|
|||||||
// TODO handle error
|
// TODO handle error
|
||||||
assert!(res == CH_STATUS_COMPLETED);
|
assert!(res == CH_STATUS_COMPLETED);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub(crate) unsafe fn configure_dmamux(
|
||||||
|
dmamux_regs: &pac::dmamux::Dmamux,
|
||||||
|
dmamux_ch_num: u8,
|
||||||
|
request: u8,
|
||||||
|
) {
|
||||||
|
let ch_mux_regs = dmamux_regs.ccr(dmamux_ch_num as _);
|
||||||
|
ch_mux_regs.write(|reg| {
|
||||||
|
// one request?
|
||||||
|
reg.set_nbreq(0);
|
||||||
|
reg.set_dmareq_id(request);
|
||||||
|
});
|
||||||
|
|
||||||
|
ch_mux_regs.modify(|reg| {
|
||||||
|
reg.set_ege(true);
|
||||||
|
//reg.set_se(true);
|
||||||
|
//reg.set_soie(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub trait Bdma {
|
|
||||||
fn regs() -> &'static pac::bdma::Dma;
|
|
||||||
fn num() -> u8;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DmaMux {
|
pub trait DmaMux {
|
||||||
fn regs() -> &'static pac::dmamux::Dmamux;
|
fn regs() -> &'static pac::dmamux::Dmamux;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Channel {
|
pub trait Channel {
|
||||||
fn num(&self) -> usize;
|
fn num(&self) -> usize;
|
||||||
fn regs(&self) -> pac::bdma::Ch;
|
|
||||||
fn dma_regs() -> &'static pac::bdma::Dma;
|
fn dma_regs() -> &'static pac::bdma::Dma;
|
||||||
fn dma_ch_num(&self) -> u8;
|
fn dma_ch_num(&self) -> u8;
|
||||||
|
|
||||||
@ -156,7 +140,6 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Bdma: sealed::Bdma {}
|
|
||||||
pub trait DmaMux: sealed::DmaMux {}
|
pub trait DmaMux: sealed::DmaMux {}
|
||||||
pub trait Channel: sealed::Channel {}
|
pub trait Channel: sealed::Channel {}
|
||||||
pub trait PeripheralChannel<PERI, OP>: sealed::Channel {}
|
pub trait PeripheralChannel<PERI, OP>: sealed::Channel {}
|
||||||
@ -172,10 +155,6 @@ macro_rules! impl_dma_channel {
|
|||||||
($dma_num * 8) + $channel_num
|
($dma_num * 8) + $channel_num
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regs(&self) -> pac::bdma::Ch {
|
|
||||||
Self::dma_regs().ch(self.dma_ch_num() as _)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dma_regs() -> &'static pac::bdma::Dma {
|
fn dma_regs() -> &'static pac::bdma::Dma {
|
||||||
&crate::pac::$dma_peri
|
&crate::pac::$dma_peri
|
||||||
}
|
}
|
||||||
@ -192,42 +171,6 @@ macro_rules! impl_dma_channel {
|
|||||||
($dma_num * 8) + $channel_num
|
($dma_num * 8) + $channel_num
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> WriteDma<T> for peripherals::$channel_peri
|
|
||||||
where
|
|
||||||
Self: sealed::PeripheralChannel<T, M2P>,
|
|
||||||
T: 'static,
|
|
||||||
{
|
|
||||||
type WriteDmaFuture<'a> = impl Future<Output = ()>;
|
|
||||||
|
|
||||||
fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
|
|
||||||
where
|
|
||||||
T: 'a,
|
|
||||||
{
|
|
||||||
let request = sealed::PeripheralChannel::<T, M2P>::request(self);
|
|
||||||
unsafe { transfer_m2p(self, request, buf, dst) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ReadDma<T> for peripherals::$channel_peri
|
|
||||||
where
|
|
||||||
Self: sealed::PeripheralChannel<T, P2M>,
|
|
||||||
T: 'static,
|
|
||||||
{
|
|
||||||
type ReadDmaFuture<'a> = impl Future<Output = ()>;
|
|
||||||
|
|
||||||
fn transfer<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
src: *const u8,
|
|
||||||
buf: &'a mut [u8],
|
|
||||||
) -> Self::ReadDmaFuture<'a>
|
|
||||||
where
|
|
||||||
T: 'a,
|
|
||||||
{
|
|
||||||
let request = sealed::PeripheralChannel::<T, P2M>::request(self);
|
|
||||||
unsafe { transfer_p2m(self, request, src, buf) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,25 +185,8 @@ macro_rules! impl_dmamux {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_bdma {
|
|
||||||
($peri:ident, $dma_num:expr) => {
|
|
||||||
impl sealed::Bdma for peripherals::$peri {
|
|
||||||
fn num() -> u8 {
|
|
||||||
$dma_num
|
|
||||||
}
|
|
||||||
|
|
||||||
fn regs() -> &'static pac::bdma::Dma {
|
|
||||||
&pac::$peri
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bdma for peripherals::$peri {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
peripherals! {
|
peripherals! {
|
||||||
(bdma, DMA1) => {
|
(bdma, DMA1) => {
|
||||||
impl_bdma!(DMA1, 0);
|
|
||||||
dma_channels! {
|
dma_channels! {
|
||||||
($channel_peri:ident, DMA1, $channel_num:expr) => {
|
($channel_peri:ident, DMA1, $channel_num:expr) => {
|
||||||
impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA1, 0);
|
impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA1, 0);
|
||||||
@ -268,7 +194,6 @@ peripherals! {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
(bdma, DMA2) => {
|
(bdma, DMA2) => {
|
||||||
impl_bdma!(DMA2, 1);
|
|
||||||
dma_channels! {
|
dma_channels! {
|
||||||
($channel_peri:ident, DMA2, $channel_num:expr) => {
|
($channel_peri:ident, DMA2, $channel_num:expr) => {
|
||||||
impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA2, 1);
|
impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA2, 1);
|
||||||
@ -285,9 +210,6 @@ macro_rules! impl_usart_dma_requests {
|
|||||||
dma_requests! {
|
dma_requests! {
|
||||||
// TODO: DRY this up.
|
// TODO: DRY this up.
|
||||||
(usart, $peri:ident, RX, $request:expr) => {
|
(usart, $peri:ident, RX, $request:expr) => {
|
||||||
impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
|
|
||||||
impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
|
|
||||||
|
|
||||||
impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri {
|
impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri {
|
||||||
fn request(&self) -> u8 {
|
fn request(&self) -> u8 {
|
||||||
$request
|
$request
|
||||||
@ -299,9 +221,6 @@ macro_rules! impl_usart_dma_requests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
(usart, $peri:ident, TX, $request:expr) => {
|
(usart, $peri:ident, TX, $request:expr) => {
|
||||||
impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
|
|
||||||
impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
|
|
||||||
|
|
||||||
impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri {
|
impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri {
|
||||||
fn request(&self) -> u8 {
|
fn request(&self) -> u8 {
|
||||||
$request
|
$request
|
||||||
@ -313,9 +232,6 @@ macro_rules! impl_usart_dma_requests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
(uart, $peri:ident, TX, $request:expr) => {
|
(uart, $peri:ident, TX, $request:expr) => {
|
||||||
impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
|
|
||||||
impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
|
|
||||||
|
|
||||||
impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri {
|
impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri {
|
||||||
fn request(&self) -> u8 {
|
fn request(&self) -> u8 {
|
||||||
$request
|
$request
|
||||||
@ -326,9 +242,6 @@ macro_rules! impl_usart_dma_requests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
(uart, $peri:ident, RX, $request:expr) => {
|
(uart, $peri:ident, RX, $request:expr) => {
|
||||||
impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
|
|
||||||
impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
|
|
||||||
|
|
||||||
impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri {
|
impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri {
|
||||||
fn request(&self) -> u8 {
|
fn request(&self) -> u8 {
|
||||||
$request
|
$request
|
||||||
@ -351,86 +264,5 @@ dma_channels! {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn on_irq() {
|
|
||||||
defmt::info!("irq fire");
|
|
||||||
peripherals! {
|
|
||||||
//(bdma, $dma:ident) => {
|
|
||||||
(bdma, DMA1) => {
|
|
||||||
defmt::info!("---> dma DMA1");
|
|
||||||
//for isrn in 0..2 {
|
|
||||||
//let isr = pac::$dma.isr(isrn).read();
|
|
||||||
let isr = pac::DMA1.isr().read();
|
|
||||||
pac::DMA1.ifcr().write_value(isr);
|
|
||||||
let dman = <peripherals::DMA1 as sealed::Bdma>::num() as usize;
|
|
||||||
|
|
||||||
for chn in 0..8 {
|
|
||||||
let n = dman * 8 + chn;
|
|
||||||
defmt::info!("n={}", n);
|
|
||||||
if isr.teif(chn) {
|
|
||||||
defmt::info!("transfer error");
|
|
||||||
STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Release);
|
|
||||||
STATE.ch_wakers[n].wake();
|
|
||||||
} else if isr.tcif(chn) {
|
|
||||||
defmt::info!("transfer complete");
|
|
||||||
STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Release);
|
|
||||||
STATE.ch_wakers[n].wake();
|
|
||||||
} else if isr.htif(chn) {
|
|
||||||
defmt::info!("half transfer");
|
|
||||||
} else if isr.gif(chn) {
|
|
||||||
defmt::info!("half transfer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
};
|
|
||||||
|
|
||||||
(bdma, DMA2) => {
|
|
||||||
defmt::info!("---> dma DMA2");
|
|
||||||
//for isrn in 0..2 {
|
|
||||||
//let isr = pac::$dma.isr(isrn).read();
|
|
||||||
let isr = pac::DMA2.isr().read();
|
|
||||||
pac::DMA2.ifcr().write_value(isr);
|
|
||||||
let dman = <peripherals::DMA2 as sealed::Bdma>::num() as usize;
|
|
||||||
|
|
||||||
for chn in 0..8 {
|
|
||||||
let n = dman * 8 + chn;
|
|
||||||
defmt::info!("n={}", n);
|
|
||||||
if isr.teif(chn) {
|
|
||||||
defmt::info!("transfer error");
|
|
||||||
STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Release);
|
|
||||||
STATE.ch_wakers[n].wake();
|
|
||||||
} else if isr.tcif(chn) {
|
|
||||||
defmt::info!("transfer complete");
|
|
||||||
STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Release);
|
|
||||||
STATE.ch_wakers[n].wake();
|
|
||||||
} else if isr.htif(chn) {
|
|
||||||
defmt::info!("half transfer");
|
|
||||||
} else if isr.gif(chn) {
|
|
||||||
defmt::info!("half transfer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
defmt::info!("irq fire complete");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// safety: must be called only once
|
/// safety: must be called only once
|
||||||
pub(crate) unsafe fn init() {
|
pub(crate) unsafe fn init() {}
|
||||||
interrupts! {
|
|
||||||
(DMA, $irq:ident) => {
|
|
||||||
defmt::info!("enable irq {}", stringify!($irq));
|
|
||||||
interrupt::$irq::steal().enable();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interrupts! {
|
|
||||||
(DMA, $irq:ident) => {
|
|
||||||
#[crate::interrupt]
|
|
||||||
unsafe fn $irq () {
|
|
||||||
defmt::info!("irq firing {}", stringify!($irq));
|
|
||||||
on_irq()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@ -20,6 +20,9 @@ pub mod gpio;
|
|||||||
pub mod rcc;
|
pub mod rcc;
|
||||||
|
|
||||||
// Sometimes-present hardware
|
// Sometimes-present hardware
|
||||||
|
#[cfg(any(dma, bdma, dmamux))]
|
||||||
|
pub mod dma_traits;
|
||||||
|
|
||||||
#[cfg(adc)]
|
#[cfg(adc)]
|
||||||
pub mod adc;
|
pub mod adc;
|
||||||
#[cfg(bdma)]
|
#[cfg(bdma)]
|
||||||
@ -28,7 +31,7 @@ pub mod bdma;
|
|||||||
pub mod clock;
|
pub mod clock;
|
||||||
#[cfg(dac)]
|
#[cfg(dac)]
|
||||||
pub mod dac;
|
pub mod dac;
|
||||||
#[cfg(any(dma, dmamux))]
|
#[cfg(dma)]
|
||||||
pub mod dma;
|
pub mod dma;
|
||||||
#[cfg(dmamux)]
|
#[cfg(dmamux)]
|
||||||
pub mod dmamux;
|
pub mod dmamux;
|
||||||
|
@ -73,11 +73,8 @@ pub enum Error {
|
|||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[cfg(any(dma, dmamux))]
|
#[cfg(any(dma, bdma, dmamux))]
|
||||||
use crate::dma::WriteDma;
|
use crate::dma_traits::WriteDma;
|
||||||
|
|
||||||
#[cfg(bdma)]
|
|
||||||
use crate::bdma::WriteDma;
|
|
||||||
|
|
||||||
pub trait Instance {
|
pub trait Instance {
|
||||||
fn regs(&self) -> crate::pac::usart::Usart;
|
fn regs(&self) -> crate::pac::usart::Usart;
|
||||||
|
96
examples/stm32l4/src/bin/usart_dma.rs
Normal file
96
examples/stm32l4/src/bin/usart_dma.rs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(trait_alias)]
|
||||||
|
#![feature(min_type_alias_impl_trait)]
|
||||||
|
#![feature(impl_trait_in_bindings)]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
#[path = "../example_common.rs"]
|
||||||
|
mod example_common;
|
||||||
|
use core::fmt::Write;
|
||||||
|
use cortex_m_rt::entry;
|
||||||
|
use embassy::executor::Executor;
|
||||||
|
use embassy::time::Clock;
|
||||||
|
use embassy::util::Forever;
|
||||||
|
use embassy_stm32::usart::{Config, Uart};
|
||||||
|
use example_common::*;
|
||||||
|
use heapless::String;
|
||||||
|
use stm32l4::stm32l4x5 as pac;
|
||||||
|
|
||||||
|
#[embassy::task]
|
||||||
|
async fn main_task() {
|
||||||
|
let mut p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
let config = Config::default();
|
||||||
|
let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, config);
|
||||||
|
|
||||||
|
for n in 0u32.. {
|
||||||
|
let mut s: String<128> = String::new();
|
||||||
|
core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap();
|
||||||
|
|
||||||
|
usart
|
||||||
|
.write_dma(&mut p.DMA1_3, s.as_bytes())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!("wrote DMA");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ZeroClock;
|
||||||
|
|
||||||
|
impl Clock for ZeroClock {
|
||||||
|
fn now(&self) -> u64 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static EXECUTOR: Forever<Executor> = Forever::new();
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let pp = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
pp.DBGMCU.cr.modify(|_, w| {
|
||||||
|
w.dbg_sleep().set_bit();
|
||||||
|
w.dbg_standby().set_bit();
|
||||||
|
w.dbg_stop().set_bit()
|
||||||
|
});
|
||||||
|
|
||||||
|
pp.RCC.ahb1enr.modify(|_, w| {
|
||||||
|
unsafe {
|
||||||
|
w.bits( 0x07 );
|
||||||
|
}
|
||||||
|
w
|
||||||
|
//w.dmamuxen().set_bit();
|
||||||
|
//w.dma1en().set_bit();
|
||||||
|
//w.dma2en().set_bit();
|
||||||
|
//w
|
||||||
|
});
|
||||||
|
|
||||||
|
pp.RCC.ahb2enr.modify(|_, w| {
|
||||||
|
w.gpioaen().set_bit();
|
||||||
|
w.gpioben().set_bit();
|
||||||
|
w.gpiocen().set_bit();
|
||||||
|
w.gpioden().set_bit();
|
||||||
|
w.gpioeen().set_bit();
|
||||||
|
w.gpiofen().set_bit();
|
||||||
|
w
|
||||||
|
});
|
||||||
|
|
||||||
|
pp.RCC.apb2enr.modify(|_, w| {
|
||||||
|
w.syscfgen().set_bit();
|
||||||
|
w
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
unsafe { embassy::time::set_clock(&ZeroClock) };
|
||||||
|
|
||||||
|
let executor = EXECUTOR.put(Executor::new());
|
||||||
|
|
||||||
|
executor.run(|spawner| {
|
||||||
|
unwrap!(spawner.spawn(main_task()));
|
||||||
|
})
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
Subproject commit 409ed5502c254e462f3e31b0ea5ddee95f818a70
|
Subproject commit a2167373ee8fd0e75dce003bfdbadda8b32ff77c
|
@ -421,6 +421,7 @@ pub fn gen(options: Options) {
|
|||||||
clock.to_ascii_lowercase()
|
clock.to_ascii_lowercase()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !name.starts_with("GPIO") {
|
||||||
peripheral_rcc_table.push(vec![
|
peripheral_rcc_table.push(vec![
|
||||||
name.clone(),
|
name.clone(),
|
||||||
clock,
|
clock,
|
||||||
@ -430,6 +431,7 @@ pub fn gen(options: Options) {
|
|||||||
format!("set_{}", reset_field.to_ascii_lowercase()),
|
format!("set_{}", reset_field.to_ascii_lowercase()),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
(None, Some(_)) => {
|
(None, Some(_)) => {
|
||||||
print!("Unable to find enable register for {}", name)
|
print!("Unable to find enable register for {}", name)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user