From 1732551db48c5788502221b96f3ec6f8fe76ada3 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Tue, 22 Jun 2021 14:53:19 -0400 Subject: [PATCH 01/12] Generate dma-related macro tables. --- stm32-data | 2 +- stm32-metapac/gen/src/lib.rs | 67 ++++++++++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/stm32-data b/stm32-data index eb76ee900..9856b1117 160000 --- a/stm32-data +++ b/stm32-data @@ -1 +1 @@ -Subproject commit eb76ee900ac67b51497196572250323e82666b4c +Subproject commit 9856b11172ae27ffa60d339ac271d2d06c190756 diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs index 9e7add452..408865e31 100644 --- a/stm32-metapac/gen/src/lib.rs +++ b/stm32-metapac/gen/src/lib.rs @@ -27,6 +27,7 @@ pub struct Core { pub name: String, pub peripherals: HashMap, pub interrupts: HashMap, + pub dma_channels: HashMap, } #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] @@ -46,6 +47,10 @@ pub struct Peripheral { pub clock: Option, #[serde(default)] pub pins: Vec, + #[serde(default)] + pub dma_channels: HashMap>, + #[serde(default)] + pub dma_requests: HashMap, } #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] @@ -55,6 +60,12 @@ pub struct Pin { pub af: Option, } +#[derive(Debug, Eq, PartialEq, Clone, Deserialize)] +pub struct DmaChannel { + pub dma: String, + pub channel: u32, +} + struct BlockInfo { /// usart_v1/USART -> usart module: String, @@ -123,7 +134,7 @@ macro_rules! {} {{ ", name, name ) - .unwrap(); + .unwrap(); for row in data { write!(out, " __{}_inner!(({}));\n", name, row.join(",")).unwrap(); @@ -134,7 +145,7 @@ macro_rules! {} {{ " }}; }}" ) - .unwrap(); + .unwrap(); } pub struct Options { @@ -220,6 +231,9 @@ pub fn gen(options: Options) { let mut peripherals_table: Vec> = Vec::new(); let mut peripheral_pins_table: Vec> = Vec::new(); let mut peripheral_rcc_table: Vec> = Vec::new(); + let mut dma_channels_table: Vec> = Vec::new(); + let mut dma_requests_table: Vec> = Vec::new(); + let mut peripheral_dma_channels_table: Vec> = Vec::new(); let dma_base = core .peripherals @@ -231,6 +245,14 @@ pub fn gen(options: Options) { let gpio_base = core.peripherals.get(&"GPIOA".to_string()).unwrap().address; let gpio_stride = 0x400; + for (id, channel_info) in &core.dma_channels { + let mut row = Vec::new(); + row.push(id.clone()); + row.push(channel_info.dma.clone() ); + row.push(channel_info.channel.to_string()); + dma_channels_table.push(row); + } + for (name, p) in &core.peripherals { let mut ir_peri = ir::Peripheral { name: name.clone(), @@ -257,13 +279,35 @@ pub fn gen(options: Options) { peripheral_pins_table.push(row); } + for dma_request in &p.dma_requests { + let mut row = Vec::new(); + row.push(name.clone()); + row.push(dma_request.0.clone()); + row.push(dma_request.1.to_string()); + dma_requests_table.push(row); + } + + for (event, dma_channels) in &p.dma_channels { + for channel in dma_channels.iter() { + let mut row = Vec::new(); + row.push(name.clone()); + row.push( bi.module.clone() ); + row.push( bi.block.clone() ); + row.push(event.clone()); + row.push( channel.clone() ); + row.push( core.dma_channels[channel].dma.clone() ); + row.push( core.dma_channels[channel].channel.to_string() ); + peripheral_dma_channels_table.push(row); + } + } + let mut peripheral_row = Vec::new(); peripheral_row.push(bi.module.clone()); peripheral_row.push(name.clone()); peripherals_table.push(peripheral_row); if let Some(old_version) = - peripheral_versions.insert(bi.module.clone(), bi.version.clone()) + peripheral_versions.insert(bi.module.clone(), bi.version.clone()) { if old_version != bi.version { panic!( @@ -402,7 +446,10 @@ pub fn gen(options: Options) { make_table(&mut extra, "peripherals", &peripherals_table); make_table(&mut extra, "peripheral_versions", &peripheral_version_table); make_table(&mut extra, "peripheral_pins", &peripheral_pins_table); + make_table(&mut extra, "peripheral_dma_channels", &peripheral_dma_channels_table); make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table); + make_table(&mut extra, "dma_channels", &dma_channels_table); + make_table(&mut extra, "dma_requests", &dma_requests_table); for (module, version) in peripheral_versions { all_peripheral_versions.insert((module.clone(), version.clone())); @@ -411,7 +458,7 @@ pub fn gen(options: Options) { "#[path=\"../../peripherals/{}_{}.rs\"] pub mod {};\n", module, version, module ) - .unwrap(); + .unwrap(); } // Cleanups! @@ -449,7 +496,7 @@ pub fn gen(options: Options) { "PROVIDE({} = DefaultHandler);\n", name.to_ascii_uppercase() ) - .unwrap(); + .unwrap(); } File::create(chip_dir.join("device.x")) @@ -477,7 +524,7 @@ pub fn gen(options: Options) { transform::NameKind::Enum => format!("vals::{}", s), _ => s.to_string(), }) - .unwrap(); + .unwrap(); transform::sort::Sort {}.run(&mut ir).unwrap(); transform::Sanitize {}.run(&mut ir).unwrap(); @@ -488,7 +535,7 @@ pub fn gen(options: Options) { .join("src/peripherals") .join(format!("{}_{}.rs", module, version)), ) - .unwrap(); + .unwrap(); let data = items.to_string().replace("] ", "]\n"); // Remove inner attributes like #![no_std] @@ -511,14 +558,14 @@ pub fn gen(options: Options) { "#[cfg_attr(feature=\"{}_{}\", path = \"chips/{}_{}/pac.rs\")]", x, c, x, c ) - .unwrap(); + .unwrap(); } else { write!( &mut paths, "#[cfg_attr(feature=\"{}\", path = \"chips/{}/pac.rs\")]", x, x ) - .unwrap(); + .unwrap(); } } let mut contents: Vec = Vec::new(); @@ -541,7 +588,7 @@ pub fn gen(options: Options) { out_dir.join("src").join("common.rs"), generate::COMMON_MODULE, ) - .unwrap(); + .unwrap(); // Generate Cargo.toml const BUILDDEP_BEGIN: &[u8] = b"# BEGIN BUILD DEPENDENCIES"; From b88fc2847a2c605ea78e18cd1c5aaf2137445926 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Fri, 25 Jun 2021 14:00:11 -0400 Subject: [PATCH 02/12] Checkpoint with lifetime issues. --- embassy-stm32/Cargo.toml | 1 + embassy-stm32/gen.py | 13 +- embassy-stm32/src/bdma/mod.rs | 69 +++++++++ embassy-stm32/src/dma/mod.rs | 65 ++------ embassy-stm32/src/dma/v2.rs | 265 +++++++++++++++++++++------------ embassy-stm32/src/lib.rs | 2 + embassy-stm32/src/usart/mod.rs | 11 +- embassy-stm32/src/usart/v1.rs | 10 +- stm32-metapac/Cargo.toml | 1 + stm32-metapac/gen/src/lib.rs | 65 ++++++-- 10 files changed, 328 insertions(+), 174 deletions(-) create mode 100644 embassy-stm32/src/bdma/mod.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 4e37c94fe..058d50124 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -28,6 +28,7 @@ stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt" vcell = { version = "0.1.3", optional = true } cfg-if = "1.0.0" +paste = "1.0.5" [build-dependencies] stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false } diff --git a/embassy-stm32/gen.py b/embassy-stm32/gen.py index 386c5ce17..01c778716 100644 --- a/embassy-stm32/gen.py +++ b/embassy-stm32/gen.py @@ -73,13 +73,16 @@ with open(output_file, 'w') as f: pins.add(pin) singletons.append(pin) - if block_mod == 'dma': - custom_singletons = True - for ch_num in range(8): - channel = f'{name}_CH{ch_num}' - singletons.append(channel) + # if block_mod == 'dma': + # custom_singletons = True + # for ch_num in range(8): + # channel = f'{name}_CH{ch_num}' + # singletons.append(channel) if not custom_singletons: singletons.append(name) + for (channel_id, defn) in core['dma_channels'].items(): + singletons.append( channel_id ) + f.write(f"embassy_extras::peripherals!({','.join(singletons)});") diff --git a/embassy-stm32/src/bdma/mod.rs b/embassy-stm32/src/bdma/mod.rs new file mode 100644 index 000000000..e85ade5df --- /dev/null +++ b/embassy-stm32/src/bdma/mod.rs @@ -0,0 +1,69 @@ +#![macro_use] + +#[cfg_attr(bdma_v1, path = "v1.rs")] +#[cfg_attr(bdma_v2, path = "v2.rs")] +mod _version; + +#[allow(unused)] +pub use _version::*; + +use crate::pac; +use crate::peripherals; + +pub(crate) mod sealed { + use super::*; + + pub trait Channel { + fn num(&self) -> u8; + + fn dma_num(&self) -> u8 { + self.num() / 8 + } + fn ch_num(&self) -> u8 { + self.num() % 8 + } + fn regs(&self) -> pac::dma::Dma { + pac::DMA(self.num() as _) + } + } +} + +pub trait Channel: sealed::Channel + Sized {} + +macro_rules! impl_dma_channel { + ($channel_peri:ident, $dma_num:expr, $ch_num:expr) => { + impl Channel for peripherals::$channel_peri {} + impl sealed::Channel for peripherals::$channel_peri { + #[inline] + fn num(&self) -> u8 { + $dma_num * 8 + $ch_num + } + } + }; +} + +/* +crate::pac::peripherals!( + (dma,DMA1) => { + impl_dma_channel!(DMA1_CH0, 0, 0); + impl_dma_channel!(DMA1_CH1, 0, 1); + impl_dma_channel!(DMA1_CH2, 0, 2); + impl_dma_channel!(DMA1_CH3, 0, 3); + impl_dma_channel!(DMA1_CH4, 0, 4); + impl_dma_channel!(DMA1_CH5, 0, 5); + impl_dma_channel!(DMA1_CH6, 0, 6); + impl_dma_channel!(DMA1_CH7, 0, 7); + }; + + (dma,DMA2) => { + impl_dma_channel!(DMA2_CH0, 1, 0); + impl_dma_channel!(DMA2_CH1, 1, 1); + impl_dma_channel!(DMA2_CH2, 1, 2); + impl_dma_channel!(DMA2_CH3, 1, 3); + impl_dma_channel!(DMA2_CH4, 1, 4); + impl_dma_channel!(DMA2_CH5, 1, 5); + impl_dma_channel!(DMA2_CH6, 1, 6); + impl_dma_channel!(DMA2_CH7, 1, 7); + }; +); + */ diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 773cdc8b8..a8a22ce89 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -1,67 +1,22 @@ #![macro_use] -#[cfg_attr(dma_v1, path = "v1.rs")] +//#[cfg_attr(dma_v1, path = "v1.rs")] #[cfg_attr(dma_v2, path = "v2.rs")] mod _version; #[allow(unused)] pub use _version::*; -use crate::pac; -use crate::peripherals; +use core::future::Future; -pub(crate) mod sealed { - use super::*; +pub trait WriteDma { + type WriteDmaFuture<'a>: Future + 'a + where + Self: 'a; - pub trait Channel { - fn num(&self) -> u8; - - fn dma_num(&self) -> u8 { - self.num() / 8 - } - fn ch_num(&self) -> u8 { - self.num() % 8 - } - fn regs(&self) -> pac::dma::Dma { - pac::DMA(self.num() as _) - } - } + fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> + where + T: 'a; } -pub trait Channel: sealed::Channel + Sized {} - -macro_rules! impl_dma_channel { - ($type:ident, $dma_num:expr, $ch_num:expr) => { - impl Channel for peripherals::$type {} - impl sealed::Channel for peripherals::$type { - #[inline] - fn num(&self) -> u8 { - $dma_num * 8 + $ch_num - } - } - }; -} - -crate::pac::peripherals!( - (dma,DMA1) => { - impl_dma_channel!(DMA1_CH0, 0, 0); - impl_dma_channel!(DMA1_CH1, 0, 1); - impl_dma_channel!(DMA1_CH2, 0, 2); - impl_dma_channel!(DMA1_CH3, 0, 3); - impl_dma_channel!(DMA1_CH4, 0, 4); - impl_dma_channel!(DMA1_CH5, 0, 5); - impl_dma_channel!(DMA1_CH6, 0, 6); - impl_dma_channel!(DMA1_CH7, 0, 7); - }; - - (dma,DMA2) => { - impl_dma_channel!(DMA2_CH0, 1, 0); - impl_dma_channel!(DMA2_CH1, 1, 1); - impl_dma_channel!(DMA2_CH2, 1, 2); - impl_dma_channel!(DMA2_CH3, 1, 3); - impl_dma_channel!(DMA2_CH4, 1, 4); - impl_dma_channel!(DMA2_CH5, 1, 5); - impl_dma_channel!(DMA2_CH6, 1, 6); - impl_dma_channel!(DMA2_CH7, 1, 7); - }; -); +pub trait ReadDma {} diff --git a/embassy-stm32/src/dma/v2.rs b/embassy-stm32/src/dma/v2.rs index e7bd69130..6c6bbde23 100644 --- a/embassy-stm32/src/dma/v2.rs +++ b/embassy-stm32/src/dma/v2.rs @@ -9,9 +9,14 @@ use crate::interrupt; use crate::pac; use crate::pac::dma::{regs, vals}; -const DMAS: [pac::dma::Dma; 2] = [pac::DMA1, pac::DMA2]; +use crate::pac::dma_channels; +use crate::pac::interrupts; +use crate::pac::peripheral_count; +use crate::pac::peripheral_dma_channels; +use crate::pac::peripherals; +use crate::peripherals; -const CH_COUNT: usize = 16; +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; @@ -41,9 +46,8 @@ pub(crate) async unsafe fn transfer_m2p( src: &[u8], dst: *mut u8, ) { - let n = ch.num() as usize; - let r = ch.regs(); - let c = r.st(ch.ch_num() as _); + let n = ch.num(); + let c = ch.regs(); // ndtr is max 16 bits. assert!(src.len() <= 0xFFFF); @@ -82,106 +86,169 @@ pub(crate) async unsafe fn transfer_m2p( } unsafe fn on_irq() { - for (dman, &dma) in DMAS.iter().enumerate() { - for isrn in 0..2 { - let isr = dma.isr(isrn).read(); - dma.ifcr(isrn).write_value(isr); + peripherals! { + (dma, $dma:ident) => { + for isrn in 0..2 { + let isr = pac::$dma.isr(isrn).read(); + pac::$dma.ifcr(isrn).write_value(isr); + let dman = ::num() as usize; - for chn in 0..4 { - let n = dman * 8 + isrn * 4 + chn; - if isr.teif(chn) { - STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed); - STATE.ch_wakers[n].wake(); - } else if isr.tcif(chn) { - STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed); - STATE.ch_wakers[n].wake(); + for chn in 0..4 { + let n = dman * 8 + isrn * 4 + chn; + if isr.teif(chn) { + STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed); + STATE.ch_wakers[n].wake(); + } else if isr.tcif(chn) { + STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed); + STATE.ch_wakers[n].wake(); + } } } - } + }; } } -#[interrupt] -unsafe fn DMA1_STREAM0() { - on_irq() -} -#[interrupt] -unsafe fn DMA1_STREAM1() { - on_irq() -} -#[interrupt] -unsafe fn DMA1_STREAM2() { - on_irq() -} -#[interrupt] -unsafe fn DMA1_STREAM3() { - on_irq() -} -#[interrupt] -unsafe fn DMA1_STREAM4() { - on_irq() -} -#[interrupt] -unsafe fn DMA1_STREAM5() { - on_irq() -} -#[interrupt] -unsafe fn DMA1_STREAM6() { - on_irq() -} -#[interrupt] -unsafe fn DMA1_STREAM7() { - on_irq() -} -#[interrupt] -unsafe fn DMA2_STREAM0() { - on_irq() -} -#[interrupt] -unsafe fn DMA2_STREAM1() { - on_irq() -} -#[interrupt] -unsafe fn DMA2_STREAM2() { - on_irq() -} -#[interrupt] -unsafe fn DMA2_STREAM3() { - on_irq() -} -#[interrupt] -unsafe fn DMA2_STREAM4() { - on_irq() -} -#[interrupt] -unsafe fn DMA2_STREAM5() { - on_irq() -} -#[interrupt] -unsafe fn DMA2_STREAM6() { - on_irq() -} -#[interrupt] -unsafe fn DMA2_STREAM7() { - on_irq() -} - /// safety: must be called only once pub(crate) unsafe fn init() { - interrupt::DMA1_STREAM0::steal().enable(); - interrupt::DMA1_STREAM1::steal().enable(); - interrupt::DMA1_STREAM2::steal().enable(); - interrupt::DMA1_STREAM3::steal().enable(); - interrupt::DMA1_STREAM4::steal().enable(); - interrupt::DMA1_STREAM5::steal().enable(); - interrupt::DMA1_STREAM6::steal().enable(); - interrupt::DMA1_STREAM7::steal().enable(); - interrupt::DMA2_STREAM0::steal().enable(); - interrupt::DMA2_STREAM1::steal().enable(); - interrupt::DMA2_STREAM2::steal().enable(); - interrupt::DMA2_STREAM3::steal().enable(); - interrupt::DMA2_STREAM4::steal().enable(); - interrupt::DMA2_STREAM5::steal().enable(); - interrupt::DMA2_STREAM6::steal().enable(); - interrupt::DMA2_STREAM7::steal().enable(); + interrupts! { + (DMA, $irq:ident) => { + interrupt::$irq::steal().enable(); + }; + } +} + +pub(crate) mod sealed { + use super::*; + + pub trait Dma { + fn num() -> u8; + fn regs() -> &'static pac::dma::Dma; + } + + pub trait Channel { + fn dma_regs() -> &'static pac::dma::Dma; + + fn num(&self) -> usize; + + fn ch_num(&self) -> u8; + + fn regs(&self) -> pac::dma::St { + Self::dma_regs().st(self.ch_num() as _) + } + } + + pub trait PeripheralChannel: Channel { + fn request(&self) -> u8; + } +} + +pub trait Dma: sealed::Dma + Sized {} +pub trait Channel: sealed::Channel + Sized {} +pub trait PeripheralChannel: sealed::PeripheralChannel + Sized {} + +macro_rules! impl_dma { + ($peri:ident, $num:expr) => { + impl Dma for peripherals::$peri {} + impl sealed::Dma for peripherals::$peri { + fn num() -> u8 { + $num + } + fn regs() -> &'static pac::dma::Dma { + &pac::$peri + } + } + }; +} + +macro_rules! impl_dma_channel { + ($channel_peri:ident, $dma_peri:ident, $dma_num:expr, $ch_num:expr) => { + impl Channel for peripherals::$channel_peri {} + impl sealed::Channel for peripherals::$channel_peri { + #[inline] + fn dma_regs() -> &'static pac::dma::Dma { + &crate::pac::$dma_peri + } + + fn num(&self) -> usize { + ($dma_num * 8) + $ch_num + } + + fn ch_num(&self) -> u8 { + $ch_num + } + } + + impl WriteDma for peripherals::$channel_peri + where + Self: sealed::PeripheralChannel, + T: 'static, + { + type WriteDmaFuture<'a> = impl Future; + + fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> + where + T: 'a, + { + let request = sealed::PeripheralChannel::::request(self); + unsafe { transfer_m2p(self, request, buf, dst) } + } + } + }; +} + +peripherals! { + (dma, DMA1) => { + impl_dma!(DMA1, 0); + dma_channels! { + ($channel_peri:ident, DMA1, $channel_num:expr) => { + impl_dma_channel!($channel_peri, DMA1, 0, $channel_num); + }; + } + }; + (dma, DMA2) => { + impl_dma!(DMA2, 1); + dma_channels! { + ($channel_peri:ident, DMA2, $channel_num:expr) => { + impl_dma_channel!($channel_peri, DMA2, 1, $channel_num); + }; + } + }; +} + +interrupts! { + (DMA, $irq:ident) => { + unsafe fn $irq () { + on_irq() + } + }; +} + +#[cfg(usart)] +use crate::usart; +peripheral_dma_channels! { + ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => { + impl usart::RxDma for peripherals::$channel_peri { } + impl usart::sealed::RxDma for peripherals::$channel_peri { } + + impl sealed::PeripheralChannel for peripherals::$channel_peri { + fn request(&self) -> u8 { + $event_num + } + } + + impl PeripheralChannel for peripherals::$channel_peri { } + }; + + ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => { + impl usart::TxDma for peripherals::$channel_peri { } + impl usart::sealed::TxDma for peripherals::$channel_peri { } + + impl sealed::PeripheralChannel for peripherals::$channel_peri { + fn request(&self) -> u8 { + $event_num + } + } + + impl PeripheralChannel for peripherals::$channel_peri { } + }; } diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 9ba7bbe4c..813c58cd7 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -22,6 +22,8 @@ pub mod rcc; // Sometimes-present hardware #[cfg(adc)] pub mod adc; +#[cfg(bdma)] +pub mod bdma; #[cfg(timer)] pub mod clock; #[cfg(dac)] diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index adf48c326..24793b6b1 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -1,7 +1,7 @@ #![macro_use] #[cfg_attr(usart_v1, path = "v1.rs")] -#[cfg_attr(usart_v2, path = "v2.rs")] +//#[cfg_attr(usart_v2, path = "v2.rs")] mod _version; use crate::peripherals; pub use _version::*; @@ -25,6 +25,7 @@ pub enum Error { pub(crate) mod sealed { use super::*; + use crate::dma::WriteDma; pub trait Instance { fn regs(&self) -> Usart; @@ -44,7 +45,12 @@ pub(crate) mod sealed { pub trait CkPin: Pin { fn af_num(&self) -> u8; } + + pub trait RxDma {} + + pub trait TxDma: WriteDma {} } + pub trait Instance: sealed::Instance {} pub trait RxPin: sealed::RxPin {} pub trait TxPin: sealed::TxPin {} @@ -52,6 +58,9 @@ pub trait CtsPin: sealed::CtsPin {} pub trait RtsPin: sealed::RtsPin {} pub trait CkPin: sealed::CkPin {} +pub trait RxDma: sealed::RxDma {} +pub trait TxDma: sealed::TxDma {} + crate::pac::peripherals!( (usart, $inst:ident) => { impl sealed::Instance for peripherals::$inst { diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs index 1ec1f5b30..a721e89a6 100644 --- a/embassy-stm32/src/usart/v1.rs +++ b/embassy-stm32/src/usart/v1.rs @@ -104,11 +104,16 @@ impl<'d, T: Instance> Uart<'d, T> { #[cfg(dma_v2)] pub async fn write_dma( &mut self, - ch: &mut impl crate::dma::Channel, + //ch: &mut impl crate::dma::Channel, + ch: &mut impl TxDma, buffer: &[u8], ) -> Result<(), Error> { - let ch_func = 4; // USART3_TX let r = self.inner.regs(); + let dst = r.dr().ptr() as *mut u8; + ch.transfer(buffer, dst).await; + Ok(()) + /* + let ch_func = 4; // USART3_TX unsafe { r.cr3().write(|w| { @@ -121,6 +126,7 @@ impl<'d, T: Instance> Uart<'d, T> { } Ok(()) + */ } pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { diff --git a/stm32-metapac/Cargo.toml b/stm32-metapac/Cargo.toml index bed772c81..79f1c3746 100644 --- a/stm32-metapac/Cargo.toml +++ b/stm32-metapac/Cargo.toml @@ -12,6 +12,7 @@ cortex-m-rt = { version = "0.6.8", optional = true } # These are removed when generating the pre-generated crate using the tool at gen/. [build-dependencies] stm32-metapac-gen = { path = "./gen" } +regex = "1.5.4" # END BUILD DEPENDENCIES [features] diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs index 408865e31..00e122e90 100644 --- a/stm32-metapac/gen/src/lib.rs +++ b/stm32-metapac/gen/src/lib.rs @@ -48,7 +48,7 @@ pub struct Peripheral { #[serde(default)] pub pins: Vec, #[serde(default)] - pub dma_channels: HashMap>, + pub dma_channels: HashMap>, #[serde(default)] pub dma_requests: HashMap, } @@ -66,6 +66,12 @@ pub struct DmaChannel { pub channel: u32, } +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Hash)] +pub struct PeripheralDmaChannel { + pub channel: String, + pub request: Option, +} + struct BlockInfo { /// usart_v1/USART -> usart module: String, @@ -121,6 +127,21 @@ fn find_reg_for_field<'c>( }) } +fn make_peripheral_counts(out: &mut String, data: &HashMap) { + write!(out, + "#[macro_export] +macro_rules! peripheral_count {{ + ").unwrap(); + for (name, count) in data { + write!(out, + "({}) => ({});\n", + name, count, + ).unwrap(); + } + write!(out, + " }}\n").unwrap(); +} + fn make_table(out: &mut String, name: &str, data: &Vec>) { write!( out, @@ -234,6 +255,7 @@ pub fn gen(options: Options) { let mut dma_channels_table: Vec> = Vec::new(); let mut dma_requests_table: Vec> = Vec::new(); let mut peripheral_dma_channels_table: Vec> = Vec::new(); + let mut peripheral_counts: HashMap = HashMap::new(); let dma_base = core .peripherals @@ -248,12 +270,20 @@ pub fn gen(options: Options) { for (id, channel_info) in &core.dma_channels { let mut row = Vec::new(); row.push(id.clone()); - row.push(channel_info.dma.clone() ); + row.push(channel_info.dma.clone()); row.push(channel_info.channel.to_string()); dma_channels_table.push(row); } + let number_suffix_re = Regex::new("^(.*?)[0-9]*$").unwrap(); + for (name, p) in &core.peripherals { + let captures = number_suffix_re.captures(&name).unwrap(); + let root_peri_name = captures.get(1).unwrap().as_str().to_string(); + peripheral_counts.insert( + root_peri_name.clone(), + peripheral_counts.get(&root_peri_name).map_or(1, |v| v + 1), + ); let mut ir_peri = ir::Peripheral { name: name.clone(), array: None, @@ -291,12 +321,15 @@ pub fn gen(options: Options) { for channel in dma_channels.iter() { let mut row = Vec::new(); row.push(name.clone()); - row.push( bi.module.clone() ); - row.push( bi.block.clone() ); + row.push(bi.module.clone()); + row.push(bi.block.clone()); row.push(event.clone()); - row.push( channel.clone() ); - row.push( core.dma_channels[channel].dma.clone() ); - row.push( core.dma_channels[channel].channel.to_string() ); + row.push(channel.channel.clone()); + row.push(core.dma_channels[&channel.channel].dma.clone()); + row.push(core.dma_channels[&channel.channel].channel.to_string()); + if let Some(request) = channel.request { + row.push(request.to_string()); + } peripheral_dma_channels_table.push(row); } } @@ -421,7 +454,17 @@ pub fn gen(options: Options) { value: num, }); - interrupt_table.push(vec![name.to_ascii_uppercase()]); + let name = name.to_ascii_uppercase(); + + interrupt_table.push(vec![name.clone()]); + + if name.starts_with("DMA") || name.contains("_DMA") { + interrupt_table.push(vec!["DMA".to_string(), name.clone()]); + } + + if name.contains("EXTI") { + interrupt_table.push(vec!["EXTI".to_string(), name.clone()]); + } } ir.devices.insert("".to_string(), dev); @@ -429,11 +472,8 @@ pub fn gen(options: Options) { let mut extra = format!( "pub fn GPIO(n: usize) -> gpio::Gpio {{ gpio::Gpio(({} + {}*n) as _) - }} - pub fn DMA(n: usize) -> dma::Dma {{ - dma::Dma(({} + {}*n) as _) }}", - gpio_base, gpio_stride, dma_base, dma_stride, + gpio_base, gpio_stride, ); let peripheral_version_table = peripheral_versions @@ -450,6 +490,7 @@ pub fn gen(options: Options) { make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table); make_table(&mut extra, "dma_channels", &dma_channels_table); make_table(&mut extra, "dma_requests", &dma_requests_table); + make_peripheral_counts(&mut extra, &peripheral_counts); for (module, version) in peripheral_versions { all_peripheral_versions.insert((module.clone(), version.clone())); From c53ab325c1943ef4f2f4890734444930a585531d Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Tue, 29 Jun 2021 10:59:22 -0400 Subject: [PATCH 03/12] Wire up DMA with USART v1. --- embassy-stm32/src/dma/mod.rs | 12 ++++- embassy-stm32/src/dma/v2.rs | 91 +++++++++++++++++++++++++++++---- embassy-stm32/src/rcc/f4/mod.rs | 4 +- embassy-stm32/src/usart/mod.rs | 5 +- embassy-stm32/src/usart/v1.rs | 27 ++++------ 5 files changed, 107 insertions(+), 32 deletions(-) diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index a8a22ce89..371741ffd 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -1,6 +1,6 @@ #![macro_use] -//#[cfg_attr(dma_v1, path = "v1.rs")] +#[cfg_attr(dma_v1, path = "v1.rs")] #[cfg_attr(dma_v2, path = "v2.rs")] mod _version; @@ -19,4 +19,12 @@ pub trait WriteDma { T: 'a; } -pub trait ReadDma {} +pub trait ReadDma { + type ReadDmaFuture<'a>: Future + 'a + where + Self: 'a; + + fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a> + where + T: 'a; +} diff --git a/embassy-stm32/src/dma/v2.rs b/embassy-stm32/src/dma/v2.rs index 6c6bbde23..4cce1adfc 100644 --- a/embassy-stm32/src/dma/v2.rs +++ b/embassy-stm32/src/dma/v2.rs @@ -39,6 +39,52 @@ impl State { static STATE: State = State::new(); +#[allow(unused)] // Used by usart/v1.rs which may or may not be enabled +pub(crate) async unsafe fn transfer_p2m( + ch: &mut impl Channel, + ch_func: u8, + src: *const u8, + dst: &mut [u8], +) { + let n = ch.num(); + let c = ch.regs(); + + // ndtr is max 16 bits. + assert!(dst.len() <= 0xFFFF); + + // Reset status + STATE.ch_status[n].store(CH_STATUS_NONE, Ordering::Relaxed); + + unsafe { + c.par().write_value(src as _); + c.m0ar().write_value(dst.as_ptr() as _); + c.ndtr().write_value(regs::Ndtr(dst.len() as _)); + c.cr().write(|w| { + w.set_dir(vals::Dir::PERIPHERALTOMEMORY); + w.set_msize(vals::Size::BITS8); + w.set_psize(vals::Size::BITS8); + w.set_minc(vals::Inc::INCREMENTED); + w.set_pinc(vals::Inc::FIXED); + w.set_chsel(ch_func); + w.set_teie(true); + w.set_tcie(true); + w.set_en(true); + }); + } + + let res = poll_fn(|cx| { + STATE.ch_wakers[n].register(cx.waker()); + match STATE.ch_status[n].load(Ordering::Relaxed) { + CH_STATUS_NONE => Poll::Pending, + x => Poll::Ready(x), + } + }) + .await; + + // TODO handle error + assert!(res == CH_STATUS_COMPLETED); +} + #[allow(unused)] // Used by usart/v1.rs which may or may not be enabled pub(crate) async unsafe fn transfer_m2p( ch: &mut impl Channel, @@ -75,7 +121,10 @@ pub(crate) async unsafe fn transfer_m2p( let res = poll_fn(|cx| { STATE.ch_wakers[n].register(cx.waker()); match STATE.ch_status[n].load(Ordering::Relaxed) { - CH_STATUS_NONE => Poll::Pending, + CH_STATUS_NONE => { + let left = c.ndtr().read().ndt(); + Poll::Pending + } x => Poll::Ready(x), } }) @@ -137,14 +186,14 @@ pub(crate) mod sealed { } } - pub trait PeripheralChannel: Channel { + pub trait PeripheralChannel: Channel { fn request(&self) -> u8; } } pub trait Dma: sealed::Dma + Sized {} pub trait Channel: sealed::Channel + Sized {} -pub trait PeripheralChannel: sealed::PeripheralChannel + Sized {} +pub trait PeripheralChannel: sealed::PeripheralChannel + Sized {} macro_rules! impl_dma { ($peri:ident, $num:expr) => { @@ -180,7 +229,7 @@ macro_rules! impl_dma_channel { impl WriteDma for peripherals::$channel_peri where - Self: sealed::PeripheralChannel, + Self: sealed::PeripheralChannel, T: 'static, { type WriteDmaFuture<'a> = impl Future; @@ -189,10 +238,30 @@ macro_rules! impl_dma_channel { where T: 'a, { - let request = sealed::PeripheralChannel::::request(self); + let request = sealed::PeripheralChannel::::request(self); unsafe { transfer_m2p(self, request, buf, dst) } } } + + impl ReadDma for peripherals::$channel_peri + where + Self: sealed::PeripheralChannel, + T: 'static, + { + type ReadDmaFuture<'a> = impl Future; + + fn transfer<'a>( + &'a mut self, + src: *const u8, + buf: &'a mut [u8], + ) -> Self::ReadDmaFuture<'a> + where + T: 'a, + { + let request = sealed::PeripheralChannel::::request(self); + unsafe { transfer_p2m(self, request, src, buf) } + } + } }; } @@ -217,12 +286,16 @@ peripherals! { interrupts! { (DMA, $irq:ident) => { + #[crate::interrupt] unsafe fn $irq () { on_irq() } }; } +pub struct P2M; +pub struct M2P; + #[cfg(usart)] use crate::usart; peripheral_dma_channels! { @@ -230,25 +303,25 @@ peripheral_dma_channels! { impl usart::RxDma for peripherals::$channel_peri { } impl usart::sealed::RxDma for peripherals::$channel_peri { } - impl sealed::PeripheralChannel for peripherals::$channel_peri { + impl sealed::PeripheralChannel for peripherals::$channel_peri { fn request(&self) -> u8 { $event_num } } - impl PeripheralChannel for peripherals::$channel_peri { } + impl PeripheralChannel for peripherals::$channel_peri { } }; ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => { impl usart::TxDma for peripherals::$channel_peri { } impl usart::sealed::TxDma for peripherals::$channel_peri { } - impl sealed::PeripheralChannel for peripherals::$channel_peri { + impl sealed::PeripheralChannel for peripherals::$channel_peri { fn request(&self) -> u8 { $event_num } } - impl PeripheralChannel for peripherals::$channel_peri { } + impl PeripheralChannel for peripherals::$channel_peri { } }; } diff --git a/embassy-stm32/src/rcc/f4/mod.rs b/embassy-stm32/src/rcc/f4/mod.rs index 4b17bdf40..6000192b9 100644 --- a/embassy-stm32/src/rcc/f4/mod.rs +++ b/embassy-stm32/src/rcc/f4/mod.rs @@ -132,7 +132,7 @@ impl RccExt for RCC { ClockSrc::HSI16 => { // Enable HSI16 unsafe { - rcc.cr().write(|w| w.set_hsion(true)); + rcc.cr().modify(|w| w.set_hsion(true)); while !rcc.cr().read().hsirdy() {} } @@ -141,7 +141,7 @@ impl RccExt for RCC { ClockSrc::HSE(freq) => { // Enable HSE unsafe { - rcc.cr().write(|w| w.set_hseon(true)); + rcc.cr().modify(|w| w.set_hseon(true)); while !rcc.cr().read().hserdy() {} } diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 24793b6b1..08be583c7 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -1,13 +1,14 @@ #![macro_use] #[cfg_attr(usart_v1, path = "v1.rs")] -//#[cfg_attr(usart_v2, path = "v2.rs")] +#[cfg_attr(usart_v2, path = "v2.rs")] mod _version; use crate::peripherals; pub use _version::*; use crate::gpio::Pin; use crate::pac::usart::Usart; +use crate::rcc::RccPeripheral; /// Serial error #[derive(Debug, Eq, PartialEq, Copy, Clone)] @@ -51,7 +52,7 @@ pub(crate) mod sealed { pub trait TxDma: WriteDma {} } -pub trait Instance: sealed::Instance {} +pub trait Instance: sealed::Instance + RccPeripheral {} pub trait RxPin: sealed::RxPin {} pub trait TxPin: sealed::TxPin {} pub trait CtsPin: sealed::CtsPin {} diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs index a721e89a6..1f05dc9a2 100644 --- a/embassy-stm32/src/usart/v1.rs +++ b/embassy-stm32/src/usart/v1.rs @@ -63,14 +63,17 @@ impl<'d, T: Instance> Uart<'d, T> { rx: impl Unborrow>, tx: impl Unborrow>, config: Config, - pclk_freq: u32, + //pclk_freq: u32, ) -> Self { unborrow!(inner, rx, tx); + let pclk_freq = T::frequency(); + //let pclk_freq = 16_000_000; + // TODO: enable in RCC // TODO: better calculation, including error checking and OVER8 if possible. - let div = (pclk_freq + (config.baudrate / 2)) / config.baudrate; + let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate; let r = inner.regs(); @@ -108,25 +111,15 @@ impl<'d, T: Instance> Uart<'d, T> { ch: &mut impl TxDma, buffer: &[u8], ) -> Result<(), Error> { + unsafe { + self.inner.regs().cr3().modify(|reg| { + reg.set_dmat(true); + }); + } let r = self.inner.regs(); let dst = r.dr().ptr() as *mut u8; ch.transfer(buffer, dst).await; Ok(()) - /* - let ch_func = 4; // USART3_TX - - unsafe { - r.cr3().write(|w| { - w.set_dmat(true); - }); - - let dst = r.dr().ptr() as *mut u8; - - crate::dma::transfer_m2p(ch, ch_func, buffer, dst).await; - } - - Ok(()) - */ } pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { From 24f18819c879488e2a33f3c9ebbf24979b3e9612 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Tue, 29 Jun 2021 11:00:23 -0400 Subject: [PATCH 04/12] Adjust example for RCC and DMA. --- examples/stm32f4/src/bin/usart_dma.rs | 4 ++-- stm32-metapac/gen/src/lib.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs index fae05b607..66ca6242b 100644 --- a/examples/stm32f4/src/bin/usart_dma.rs +++ b/examples/stm32f4/src/bin/usart_dma.rs @@ -23,14 +23,14 @@ async fn main_task() { let mut p = embassy_stm32::init(Default::default()); let config = Config::default(); - let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); + let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, 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_CH3, s.as_bytes()) + .write_dma(&mut p.DMA1_3, s.as_bytes()) .await .unwrap(); info!("wrote DMA"); diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs index 00e122e90..1f969b3cd 100644 --- a/stm32-metapac/gen/src/lib.rs +++ b/stm32-metapac/gen/src/lib.rs @@ -431,13 +431,13 @@ pub fn gen(options: Options) { ]); } (None, Some(_)) => { - println!("Unable to find enable register for {}", name) + panic!("Unable to find enable register for {}", name) } (Some(_), None) => { - println!("Unable to find reset register for {}", name) + panic!("Unable to find reset register for {}", name) } (None, None) => { - println!("Unable to find enable and reset register for {}", name) + panic!("Unable to find enable and reset register for {}", name) } } } From 6b78d56cebb79f53aecde1d4911779da35eeb864 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Tue, 29 Jun 2021 12:48:58 -0400 Subject: [PATCH 05/12] Formatting. --- embassy-stm32/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 813c58cd7..9ba7bbe4c 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -22,8 +22,6 @@ pub mod rcc; // Sometimes-present hardware #[cfg(adc)] pub mod adc; -#[cfg(bdma)] -pub mod bdma; #[cfg(timer)] pub mod clock; #[cfg(dac)] From 2a25de3d3e16ebf8f21323ce016fe2ecf4d21629 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Tue, 29 Jun 2021 12:55:15 -0400 Subject: [PATCH 06/12] Make the metapac gen enr/rst missing regs non-fatal to the build. Should be solved in a separate effort. --- stm32-metapac/gen/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs index 1f969b3cd..a552c8cea 100644 --- a/stm32-metapac/gen/src/lib.rs +++ b/stm32-metapac/gen/src/lib.rs @@ -431,13 +431,13 @@ pub fn gen(options: Options) { ]); } (None, Some(_)) => { - panic!("Unable to find enable register for {}", name) + print!("Unable to find enable register for {}", name) } (Some(_), None) => { - panic!("Unable to find reset register for {}", name) + print!("Unable to find reset register for {}", name) } (None, None) => { - panic!("Unable to find enable and reset register for {}", name) + print!("Unable to find enable and reset register for {}", name) } } } From 07a668687929b4145e95132f2ac0e5cc8dd542f6 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Tue, 29 Jun 2021 13:00:52 -0400 Subject: [PATCH 07/12] Protect DMA-related things with cfg. --- embassy-stm32/src/usart/mod.rs | 6 ++++++ embassy-stm32/src/usart/v1.rs | 9 ++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 08be583c7..a75793f84 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -26,6 +26,8 @@ pub enum Error { pub(crate) mod sealed { use super::*; + + #[cfg(dma)] use crate::dma::WriteDma; pub trait Instance { @@ -47,8 +49,10 @@ pub(crate) mod sealed { fn af_num(&self) -> u8; } + #[cfg(dma)] pub trait RxDma {} + #[cfg(dma)] pub trait TxDma: WriteDma {} } @@ -59,7 +63,9 @@ pub trait CtsPin: sealed::CtsPin {} pub trait RtsPin: sealed::RtsPin {} pub trait CkPin: sealed::CkPin {} +#[cfg(dma)] pub trait RxDma: sealed::RxDma {} +#[cfg(dma)] pub trait TxDma: sealed::TxDma {} crate::pac::peripherals!( diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs index 1f05dc9a2..37b325d8f 100644 --- a/embassy-stm32/src/usart/v1.rs +++ b/embassy-stm32/src/usart/v1.rs @@ -104,13 +104,8 @@ impl<'d, T: Instance> Uart<'d, T> { } } - #[cfg(dma_v2)] - pub async fn write_dma( - &mut self, - //ch: &mut impl crate::dma::Channel, - ch: &mut impl TxDma, - buffer: &[u8], - ) -> Result<(), Error> { + #[cfg(dma)] + pub async fn write_dma(&mut self, ch: &mut impl TxDma, buffer: &[u8]) -> Result<(), Error> { unsafe { self.inner.regs().cr3().modify(|reg| { reg.set_dmat(true); From d5fb558005c560d7cbc9c1276e65d7d6a64452f9 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Tue, 29 Jun 2021 13:08:18 -0400 Subject: [PATCH 08/12] Fix non-DMA USART example. --- examples/stm32f4/src/bin/usart.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs index f7b66f86b..42f154b05 100644 --- a/examples/stm32f4/src/bin/usart.rs +++ b/examples/stm32f4/src/bin/usart.rs @@ -23,7 +23,7 @@ async fn main_task() { let p = embassy_stm32::init(Default::default()); let config = Config::default(); - let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); + let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config); usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap(); info!("wrote Hello, starting echo"); From e1736114d4862eba626d2fb5e5b89d0d9bd54752 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 30 Jun 2021 09:44:28 -0400 Subject: [PATCH 09/12] Remove paste. --- embassy-stm32/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 058d50124..4e37c94fe 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -28,7 +28,6 @@ stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt" vcell = { version = "0.1.3", optional = true } cfg-if = "1.0.0" -paste = "1.0.5" [build-dependencies] stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false } From 6a0b0f31621d9a494665de88f102566cd606c8ff Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 30 Jun 2021 09:57:27 -0400 Subject: [PATCH 10/12] Enable RCC within the USART itself. --- embassy-stm32/src/usart/mod.rs | 2 +- embassy-stm32/src/usart/v1.rs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index a75793f84..e486a5d4a 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -1,7 +1,7 @@ #![macro_use] #[cfg_attr(usart_v1, path = "v1.rs")] -#[cfg_attr(usart_v2, path = "v2.rs")] +//#[cfg_attr(usart_v2, path = "v2.rs")] mod _version; use crate::peripherals; pub use _version::*; diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs index 37b325d8f..6c5a12441 100644 --- a/embassy-stm32/src/usart/v1.rs +++ b/embassy-stm32/src/usart/v1.rs @@ -63,14 +63,11 @@ impl<'d, T: Instance> Uart<'d, T> { rx: impl Unborrow>, tx: impl Unborrow>, config: Config, - //pclk_freq: u32, ) -> Self { unborrow!(inner, rx, tx); + T::enable(); let pclk_freq = T::frequency(); - //let pclk_freq = 16_000_000; - - // TODO: enable in RCC // TODO: better calculation, including error checking and OVER8 if possible. let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate; From cf5b7dc9432ac2f9a31a071ac1bd8c6034583411 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 30 Jun 2021 10:03:18 -0400 Subject: [PATCH 11/12] Because IntelliJ makes life hard. --- embassy-stm32/src/usart/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index e486a5d4a..a75793f84 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -1,7 +1,7 @@ #![macro_use] #[cfg_attr(usart_v1, path = "v1.rs")] -//#[cfg_attr(usart_v2, path = "v2.rs")] +#[cfg_attr(usart_v2, path = "v2.rs")] mod _version; use crate::peripherals; pub use _version::*; From f3b9c977630a0a91eb80e730643760db50d22189 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Wed, 30 Jun 2021 10:17:25 -0400 Subject: [PATCH 12/12] Change atomics and add a fence. --- embassy-stm32/src/dma/v2.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/dma/v2.rs b/embassy-stm32/src/dma/v2.rs index 4cce1adfc..93b3cb869 100644 --- a/embassy-stm32/src/dma/v2.rs +++ b/embassy-stm32/src/dma/v2.rs @@ -74,7 +74,7 @@ pub(crate) async unsafe fn transfer_p2m( let res = poll_fn(|cx| { STATE.ch_wakers[n].register(cx.waker()); - match STATE.ch_status[n].load(Ordering::Relaxed) { + match STATE.ch_status[n].load(Ordering::Acquire) { CH_STATUS_NONE => Poll::Pending, x => Poll::Ready(x), } @@ -105,6 +105,7 @@ pub(crate) async unsafe fn transfer_m2p( c.par().write_value(dst as _); c.m0ar().write_value(src.as_ptr() as _); c.ndtr().write_value(regs::Ndtr(src.len() as _)); + compiler_fence(Ordering::AcqRel); c.cr().write(|w| { w.set_dir(vals::Dir::MEMORYTOPERIPHERAL); w.set_msize(vals::Size::BITS8); @@ -120,7 +121,7 @@ pub(crate) async unsafe fn transfer_m2p( let res = poll_fn(|cx| { STATE.ch_wakers[n].register(cx.waker()); - match STATE.ch_status[n].load(Ordering::Relaxed) { + match STATE.ch_status[n].load(Ordering::Acquire) { CH_STATUS_NONE => { let left = c.ndtr().read().ndt(); Poll::Pending @@ -130,6 +131,8 @@ pub(crate) async unsafe fn transfer_m2p( }) .await; + compiler_fence(Ordering::AcqRel); + // TODO handle error assert!(res == CH_STATUS_COMPLETED); } @@ -145,10 +148,10 @@ unsafe fn on_irq() { for chn in 0..4 { let n = dman * 8 + isrn * 4 + chn; if isr.teif(chn) { - STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed); + STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Release); STATE.ch_wakers[n].wake(); } else if isr.tcif(chn) { - STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed); + STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Release); STATE.ch_wakers[n].wake(); } } @@ -298,6 +301,7 @@ pub struct M2P; #[cfg(usart)] use crate::usart; +use atomic_polyfill::compiler_fence; peripheral_dma_channels! { ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => { impl usart::RxDma for peripherals::$channel_peri { }