From da52bb341a7b3ad19deffcadda6528db1c5be1ff Mon Sep 17 00:00:00 2001 From: RaulIQ Date: Tue, 30 Sep 2025 17:11:52 +0300 Subject: add DMA-based input capture for timer channels --- embassy-stm32/src/timer/input_capture.rs | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 7a25e6c21..cbb4bb1d4 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -155,6 +155,44 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate) .await } + + /// Capture a sequence of timer input edges into a buffer using DMA + pub async fn receive_waveform(&mut self, dma: Peri<'_, impl super::Dma>, buf: &mut [u16]) + where + M: TimerChannel, + { + #[allow(clippy::let_unit_value)] // eg. stm32f334 + let req = dma.request(); + + let original_enable_state = self.is_enabled(M::CHANNEL); + let original_update_dma_state = self.inner.get_update_dma_state(); + + if !original_update_dma_state { + self.inner.enable_update_dma(true); + } + + if !original_enable_state { + self.enable(M::CHANNEL); + } + + unsafe { + use crate::dma::{Transfer, TransferOptions}; + + Transfer::new_read( + dma, + req, + self.inner.regs_1ch().ccr(M::CHANNEL.index()).as_ptr() as *mut u16, + buf, + TransferOptions::default(), + ) + .await + }; + + // restore output compare state + if !original_enable_state { + self.disable(M::CHANNEL); + } + } } #[must_use = "futures do nothing unless you `.await` or poll them"] -- cgit From f0d27bcb52a3fa93557e625831d659bc00eb8f49 Mon Sep 17 00:00:00 2001 From: RaulIQ Date: Tue, 30 Sep 2025 17:26:47 +0300 Subject: changelog: add entry for receive_waveform --- embassy-stm32/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 80261ae41..74f0ba4e0 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate - +- Add `receive_waveform` method in `InputCapture`, allowing asynchronous input capture with DMA. - fix: Fixed STM32H5 builds requiring time feature - feat: Derive Clone, Copy for QSPI Config - fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received -- cgit From 73b1d46e2b7eacda184f1d63cd0fcedf990e5fda Mon Sep 17 00:00:00 2001 From: RaulIQ Date: Thu, 2 Oct 2025 16:13:03 +0300 Subject: fix: correct DMA configuration and registers in receive_waveform --- embassy-stm32/src/timer/input_capture.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index cbb4bb1d4..d8dbdee66 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -165,10 +165,13 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { let req = dma.request(); let original_enable_state = self.is_enabled(M::CHANNEL); - let original_update_dma_state = self.inner.get_update_dma_state(); + let original_cc_dma_enable_state = self.inner.get_cc_dma_enable_state(M::CHANNEL); - if !original_update_dma_state { - self.inner.enable_update_dma(true); + self.inner.set_input_ti_selection(M::CHANNEL, InputTISelection::Normal); + self.inner.set_input_capture_mode(M::CHANNEL, InputCaptureMode::BothEdges); + + if !original_cc_dma_enable_state { + self.inner.set_cc_dma_enable_state(M::CHANNEL, true); } if !original_enable_state { @@ -181,7 +184,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { Transfer::new_read( dma, req, - self.inner.regs_1ch().ccr(M::CHANNEL.index()).as_ptr() as *mut u16, + self.inner.regs_gp16().ccr(M::CHANNEL.index()).as_ptr() as *mut u16, buf, TransferOptions::default(), ) -- cgit From cde24a3ef1117653ba5ed4184102b33f745782fb Mon Sep 17 00:00:00 2001 From: RaulIQ Date: Thu, 2 Oct 2025 16:17:05 +0300 Subject: style: cargo fmt --- embassy-stm32/src/timer/input_capture.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index d8dbdee66..e6739fbc1 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -168,7 +168,8 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { let original_cc_dma_enable_state = self.inner.get_cc_dma_enable_state(M::CHANNEL); self.inner.set_input_ti_selection(M::CHANNEL, InputTISelection::Normal); - self.inner.set_input_capture_mode(M::CHANNEL, InputCaptureMode::BothEdges); + self.inner + .set_input_capture_mode(M::CHANNEL, InputCaptureMode::BothEdges); if !original_cc_dma_enable_state { self.inner.set_cc_dma_enable_state(M::CHANNEL, true); -- cgit