Mix dmamux into bdma_v1.
This commit is contained in:
parent
6ec7253095
commit
f01ddd5f5c
@ -6,25 +6,3 @@ mod _version;
|
||||
|
||||
#[allow(unused)]
|
||||
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 futures::future::poll_fn;
|
||||
|
||||
use super::{ReadDma, WriteDma};
|
||||
use crate::dma_traits::{ReadDma, WriteDma};
|
||||
use crate::interrupt;
|
||||
use crate::pac;
|
||||
use crate::pac::bdma::vals;
|
||||
use crate::rcc::sealed::RccPeripheral;
|
||||
|
||||
const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8;
|
||||
const CH_STATUS_NONE: u8 = 0;
|
||||
@ -57,6 +58,9 @@ pub(crate) async unsafe fn transfer_p2m(
|
||||
while regs.cr().read().en() {}
|
||||
});
|
||||
|
||||
#[cfg(dmamux)]
|
||||
crate::dmamux::configure_channel(1, 2);
|
||||
|
||||
regs.par().write_value(src as u32);
|
||||
regs.mar().write_value(dst.as_mut_ptr() as u32);
|
||||
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,
|
||||
src: &[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.
|
||||
assert!(src.len() <= 0xFFFF);
|
||||
@ -105,6 +112,9 @@ pub(crate) async unsafe fn transfer_m2p(
|
||||
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.mar().write_value(src.as_ptr() as u32);
|
||||
regs.ndtr().write(|w| w.set_ndt(src.len() as u16));
|
||||
@ -161,9 +171,10 @@ pub(crate) unsafe fn init() {
|
||||
}
|
||||
pac::peripherals! {
|
||||
(bdma, DMA1) => {
|
||||
critical_section::with(|_| {
|
||||
pac::RCC.ahbenr().modify(|w| w.set_dmaen(true));
|
||||
});
|
||||
//critical_section::with(|_| {
|
||||
//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
|
||||
where
|
||||
Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>,
|
||||
T: 'static,
|
||||
{
|
||||
type WriteDmaFuture<'a> = impl Future<Output = ()>;
|
||||
@ -234,10 +247,47 @@ macro_rules! impl_dma_channel {
|
||||
|
||||
let state_num = self.state_num();
|
||||
let regs = self.regs();
|
||||
|
||||
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
|
||||
where
|
||||
T: 'static,
|
||||
@ -292,6 +342,8 @@ pac::interrupts! {
|
||||
|
||||
#[cfg(usart)]
|
||||
use crate::usart;
|
||||
|
||||
#[cfg(not(dmamux))]
|
||||
pac::peripheral_dma_channels! {
|
||||
($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 { }
|
||||
@ -302,4 +354,34 @@ pac::peripheral_dma_channels! {
|
||||
impl usart::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]
|
||||
|
||||
#[cfg(dma)]
|
||||
#[cfg_attr(dma_v1, path = "v1.rs")]
|
||||
#[cfg_attr(dma_v2, path = "v2.rs")]
|
||||
mod _version;
|
||||
@ -8,25 +7,3 @@ mod _version;
|
||||
#[cfg(dma)]
|
||||
#[allow(unused)]
|
||||
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 crate::dma_traits::{ReadDma, WriteDma};
|
||||
use atomic_polyfill::{AtomicU8, Ordering};
|
||||
use embassy::interrupt::{Interrupt, InterruptExt};
|
||||
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 crate::dma::{ReadDma, WriteDma};
|
||||
use crate::dma_traits::{ReadDma, WriteDma};
|
||||
|
||||
const CH_COUNT: usize = peripheral_count!(DMA) * 8;
|
||||
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!()
|
||||
}
|
||||
pub(crate) fn configure_channel(ch_num: u8, request_num: u8) {}
|
||||
|
||||
/*
|
||||
#[allow(unused)]
|
||||
pub(crate) async unsafe fn transfer_m2p(
|
||||
ch: &mut impl Channel,
|
||||
@ -128,22 +98,36 @@ pub(crate) async unsafe fn transfer_m2p(
|
||||
// TODO handle error
|
||||
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 {
|
||||
use super::*;
|
||||
|
||||
pub trait Bdma {
|
||||
fn regs() -> &'static pac::bdma::Dma;
|
||||
fn num() -> u8;
|
||||
}
|
||||
|
||||
pub trait DmaMux {
|
||||
fn regs() -> &'static pac::dmamux::Dmamux;
|
||||
}
|
||||
|
||||
pub trait Channel {
|
||||
fn num(&self) -> usize;
|
||||
fn regs(&self) -> pac::bdma::Ch;
|
||||
fn dma_regs() -> &'static pac::bdma::Dma;
|
||||
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 Channel: sealed::Channel {}
|
||||
pub trait PeripheralChannel<PERI, OP>: sealed::Channel {}
|
||||
@ -172,10 +155,6 @@ macro_rules! impl_dma_channel {
|
||||
($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 {
|
||||
&crate::pac::$dma_peri
|
||||
}
|
||||
@ -192,42 +171,6 @@ macro_rules! impl_dma_channel {
|
||||
($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! {
|
||||
(bdma, DMA1) => {
|
||||
impl_bdma!(DMA1, 0);
|
||||
dma_channels! {
|
||||
($channel_peri:ident, DMA1, $channel_num:expr) => {
|
||||
impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA1, 0);
|
||||
@ -268,7 +194,6 @@ peripherals! {
|
||||
}
|
||||
};
|
||||
(bdma, DMA2) => {
|
||||
impl_bdma!(DMA2, 1);
|
||||
dma_channels! {
|
||||
($channel_peri:ident, DMA2, $channel_num:expr) => {
|
||||
impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA2, 1);
|
||||
@ -285,9 +210,6 @@ macro_rules! impl_usart_dma_requests {
|
||||
dma_requests! {
|
||||
// TODO: DRY this up.
|
||||
(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 {
|
||||
fn request(&self) -> u8 {
|
||||
$request
|
||||
@ -299,9 +221,6 @@ macro_rules! impl_usart_dma_requests {
|
||||
};
|
||||
|
||||
(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 {
|
||||
fn request(&self) -> u8 {
|
||||
$request
|
||||
@ -313,9 +232,6 @@ macro_rules! impl_usart_dma_requests {
|
||||
};
|
||||
|
||||
(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 {
|
||||
fn request(&self) -> u8 {
|
||||
$request
|
||||
@ -326,9 +242,6 @@ macro_rules! impl_usart_dma_requests {
|
||||
};
|
||||
|
||||
(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 {
|
||||
fn request(&self) -> u8 {
|
||||
$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
|
||||
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()
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) unsafe fn init() {}
|
||||
|
@ -20,6 +20,9 @@ pub mod gpio;
|
||||
pub mod rcc;
|
||||
|
||||
// Sometimes-present hardware
|
||||
#[cfg(any(dma, bdma, dmamux))]
|
||||
pub mod dma_traits;
|
||||
|
||||
#[cfg(adc)]
|
||||
pub mod adc;
|
||||
#[cfg(bdma)]
|
||||
@ -28,7 +31,7 @@ pub mod bdma;
|
||||
pub mod clock;
|
||||
#[cfg(dac)]
|
||||
pub mod dac;
|
||||
#[cfg(any(dma, dmamux))]
|
||||
#[cfg(dma)]
|
||||
pub mod dma;
|
||||
#[cfg(dmamux)]
|
||||
pub mod dmamux;
|
||||
|
@ -73,11 +73,8 @@ pub enum Error {
|
||||
pub(crate) mod sealed {
|
||||
use super::*;
|
||||
|
||||
#[cfg(any(dma, dmamux))]
|
||||
use crate::dma::WriteDma;
|
||||
|
||||
#[cfg(bdma)]
|
||||
use crate::bdma::WriteDma;
|
||||
#[cfg(any(dma, bdma, dmamux))]
|
||||
use crate::dma_traits::WriteDma;
|
||||
|
||||
pub trait Instance {
|
||||
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,14 +421,16 @@ pub fn gen(options: Options) {
|
||||
clock.to_ascii_lowercase()
|
||||
};
|
||||
|
||||
peripheral_rcc_table.push(vec![
|
||||
name.clone(),
|
||||
clock,
|
||||
enable_reg.to_ascii_lowercase(),
|
||||
reset_reg.to_ascii_lowercase(),
|
||||
format!("set_{}", enable_field.to_ascii_lowercase()),
|
||||
format!("set_{}", reset_field.to_ascii_lowercase()),
|
||||
]);
|
||||
if !name.starts_with("GPIO") {
|
||||
peripheral_rcc_table.push(vec![
|
||||
name.clone(),
|
||||
clock,
|
||||
enable_reg.to_ascii_lowercase(),
|
||||
reset_reg.to_ascii_lowercase(),
|
||||
format!("set_{}", enable_field.to_ascii_lowercase()),
|
||||
format!("set_{}", reset_field.to_ascii_lowercase()),
|
||||
]);
|
||||
}
|
||||
}
|
||||
(None, Some(_)) => {
|
||||
print!("Unable to find enable register for {}", name)
|
||||
|
Loading…
Reference in New Issue
Block a user