Get DMA on H7 working, add usart_dma example for H7.

This commit is contained in:
Bob McWhirter 2021-07-16 14:40:25 -04:00
parent 1254e99be1
commit 0119ea809d
4 changed files with 115 additions and 45 deletions

View File

@ -139,7 +139,7 @@ unsafe fn on_irq() {
/// safety: must be called only once /// safety: must be called only once
pub(crate) unsafe fn init() { pub(crate) unsafe fn init() {
pac::interrupts! { pac::interrupts! {
(DMA, $irq:ident) => { (BDMA, $irq:ident) => {
crate::interrupt::$irq::steal().enable(); crate::interrupt::$irq::steal().enable();
}; };
} }
@ -209,52 +209,11 @@ pac::bdma_channels! {
}; };
} }
// HACK: on stm32h7 "DMA" interrupts are for DMA, not BDMA, so this
// would cause duplicate interrupt definitions. Do it manually insted
#[cfg(not(rcc_h7))]
pac::interrupts! { pac::interrupts! {
(DMA, $irq:ident) => { (BDMA, $irq:ident) => {
#[crate::interrupt] #[crate::interrupt]
unsafe fn $irq () { unsafe fn $irq () {
on_irq() on_irq()
} }
}; };
} }
#[cfg(rcc_h7)]
mod _if_h7 {
use super::*;
#[crate::interrupt]
unsafe fn BDMA_CHANNEL0() {
on_irq()
}
#[crate::interrupt]
unsafe fn BDMA_CHANNEL1() {
on_irq()
}
#[crate::interrupt]
unsafe fn BDMA_CHANNEL2() {
on_irq()
}
#[crate::interrupt]
unsafe fn BDMA_CHANNEL3() {
on_irq()
}
#[crate::interrupt]
unsafe fn BDMA_CHANNEL4() {
on_irq()
}
#[crate::interrupt]
unsafe fn BDMA_CHANNEL5() {
on_irq()
}
#[crate::interrupt]
unsafe fn BDMA_CHANNEL6() {
on_irq()
}
#[crate::interrupt]
unsafe fn BDMA_CHANNEL7() {
on_irq()
}
}

View File

@ -3,7 +3,7 @@ use core::task::Poll;
use atomic_polyfill::{AtomicU8, Ordering}; use atomic_polyfill::{AtomicU8, Ordering};
use core::future::Future; use core::future::Future;
use embassy::interrupt::{Interrupt, InterruptExt}; use embassy::interrupt::{Interrupt, InterruptExt};
use embassy::util::AtomicWaker; use embassy::util::{AtomicWaker, OnDrop};
use futures::future::poll_fn; use futures::future::poll_fn;
use crate::interrupt; use crate::interrupt;
@ -38,6 +38,7 @@ static STATE: State = State::new();
//async unsafe fn do_transfer(ch: &mut impl Channel, ch_func: u8, src: *const u8, dst: &mut [u8]) { //async unsafe fn do_transfer(ch: &mut impl Channel, ch_func: u8, src: *const u8, dst: &mut [u8]) {
#[allow(unused)]
pub(crate) async unsafe fn do_transfer( pub(crate) async unsafe fn do_transfer(
dma: pac::dma::Dma, dma: pac::dma::Dma,
channel_number: u8, channel_number: u8,
@ -59,6 +60,15 @@ pub(crate) async unsafe fn do_transfer(
let ch = dma.st(channel_number as _); let ch = dma.st(channel_number as _);
let on_drop = OnDrop::new(|| unsafe {
ch.cr().modify(|w| {
w.set_tcie(false);
w.set_teie(false);
w.set_en(false);
});
while ch.cr().read().en() {}
});
#[cfg(dmamux)] #[cfg(dmamux)]
super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request); super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
@ -74,6 +84,7 @@ pub(crate) async unsafe fn do_transfer(
w.set_pinc(vals::Inc::FIXED); w.set_pinc(vals::Inc::FIXED);
w.set_teie(true); w.set_teie(true);
w.set_tcie(true); w.set_tcie(true);
w.set_trbuff(true);
w.set_en(true); w.set_en(true);
#[cfg(dma_v2)] #[cfg(dma_v2)]

View File

@ -0,0 +1,100 @@
#![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 embassy::executor::Executor;
use embassy::time::Clock;
use embassy::util::Forever;
use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use example_common::*;
use embassy_traits::uart::Write as _Write;
use hal::prelude::*;
use stm32h7xx_hal as hal;
use cortex_m_rt::entry;
use stm32h7::stm32h743 as pac;
use heapless::String;
#[embassy::task]
async fn main_task() {
let p = embassy_stm32::init(Default::default());
let config = Config::default();
let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, p.DMA1_0, NoDma, 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(s.as_bytes()).await.ok();
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();
let pwrcfg = pp.PWR.constrain().freeze();
let rcc = pp.RCC.constrain();
rcc.sys_ck(96.mhz())
.pclk1(48.mhz())
.pclk2(48.mhz())
.pclk3(48.mhz())
.pclk4(48.mhz())
.pll1_q_ck(48.mhz())
.freeze(pwrcfg, &pp.SYSCFG);
let pp = unsafe { pac::Peripherals::steal() };
pp.DBGMCU.cr.modify(|_, w| {
w.dbgsleep_d1().set_bit();
w.dbgstby_d1().set_bit();
w.dbgstop_d1().set_bit();
w.d1dbgcken().set_bit();
w
});
pp.RCC.ahb4enr.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
});
unsafe { embassy::time::set_clock(&ZeroClock) };
let executor = EXECUTOR.put(Executor::new());
executor.run(|spawner| {
unwrap!(spawner.spawn(main_task()));
})
}

@ -1 +1 @@
Subproject commit 32ca79020ec7523fe4c3fcfc02006cb1ea637a19 Subproject commit ddd0f206e22143436230dca6d3fcfc0e02e55dfd