From 642465a7da64333b9339283f3b3a14cb04bd349e Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Tue, 28 May 2024 20:20:15 -0400 Subject: [PATCH 01/19] add stm32f446 files --- examples/stm32f4/.cargo/config.toml | 6 +++-- examples/stm32f4/.vscode/launch.json | 33 +++++++++++++++++++++++ examples/stm32f4/.vscode/tasks.json | 21 +++++++++++++++ examples/stm32f4/Cargo.toml | 2 +- examples/stm32f4/openocd.cfg | 5 ++++ examples/stm32f4/openocd.gdb | 40 ++++++++++++++++++++++++++++ 6 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 examples/stm32f4/.vscode/launch.json create mode 100644 examples/stm32f4/.vscode/tasks.json create mode 100644 examples/stm32f4/openocd.cfg create mode 100644 examples/stm32f4/openocd.gdb diff --git a/examples/stm32f4/.cargo/config.toml b/examples/stm32f4/.cargo/config.toml index 16efa8e6f..f5a4af51a 100644 --- a/examples/stm32f4/.cargo/config.toml +++ b/examples/stm32f4/.cargo/config.toml @@ -1,9 +1,11 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] # replace STM32F429ZITx with your chip as listed in `probe-rs chip list` -runner = "probe-rs run --chip STM32F429ZITx" +# runner = "probe-rs run --chip STM32F429ZITx" +runner = "arm-none-eabi-gdb -q -x openocd.gdb" [build] -target = "thumbv7em-none-eabi" +# target = "thumbv7em-none-eabi" +target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) [env] DEFMT_LOG = "trace" diff --git a/examples/stm32f4/.vscode/launch.json b/examples/stm32f4/.vscode/launch.json new file mode 100644 index 000000000..59f98070d --- /dev/null +++ b/examples/stm32f4/.vscode/launch.json @@ -0,0 +1,33 @@ +{ + /* + * Requires the Rust Language Server (rust-analyzer) and Cortex-Debug extensions + * https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer + * https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug + */ + "version": "0.2.0", + "configurations": [ + { + /* Configuration for the STM32F446 Discovery board */ + "type": "cortex-debug", + "request": "launch", + "name": "Debug (OpenOCD)", + "servertype": "openocd", + "cwd": "${workspaceRoot}", + "preLaunchTask": "Cargo Build (debug)", + "runToEntryPoint": "main", + "executable": "./target/thumbv7em-none-eabihf/debug/multiprio", + /* Run `cargo build --example itm` and uncomment this line to run itm example */ + // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", + "device": "STM32F446RET6", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32f4x.cfg" + ], + "postLaunchCommands": [ + "monitor arm semihosting enable" + ], + "postRestartCommands": [], + "postResetCommands": [], + } + ] +} \ No newline at end of file diff --git a/examples/stm32f4/.vscode/tasks.json b/examples/stm32f4/.vscode/tasks.json new file mode 100644 index 000000000..3cbed84b4 --- /dev/null +++ b/examples/stm32f4/.vscode/tasks.json @@ -0,0 +1,21 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "cargo", + "command": "build", + "problemMatcher": [ + "$rustc" + ], + "args": [ + "--bin", + "multiprio" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "label": "Cargo Build (debug)", + } + ] +} \ No newline at end of file diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 1eb1ae6db..ee7594c95 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f429zi to your chip name, if necessary. -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f446re", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f4/openocd.cfg b/examples/stm32f4/openocd.cfg new file mode 100644 index 000000000..e41d52b1a --- /dev/null +++ b/examples/stm32f4/openocd.cfg @@ -0,0 +1,5 @@ +# Sample OpenOCD configuration for the STM32F3DISCOVERY development board + +source [find interface/stlink.cfg] + +source [find target/stm32f4x.cfg] diff --git a/examples/stm32f4/openocd.gdb b/examples/stm32f4/openocd.gdb new file mode 100644 index 000000000..7795319fb --- /dev/null +++ b/examples/stm32f4/openocd.gdb @@ -0,0 +1,40 @@ +target extended-remote :3333 + +# print demangled symbols +set print asm-demangle on + +# set backtrace limit to not have infinite backtrace loops +set backtrace limit 32 + +# detect unhandled exceptions, hard faults and panics +break DefaultHandler +break HardFault +break rust_begin_unwind +# # run the next few lines so the panic message is printed immediately +# # the number needs to be adjusted for your panic handler +# commands $bpnum +# next 4 +# end + +# *try* to stop at the user entry point (it might be gone due to inlining) +break main + +monitor arm semihosting enable + +# # send captured ITM to the file itm.fifo +# # (the microcontroller SWO pin must be connected to the programmer SWO pin) +# # 8000000 must match the core clock frequency +# monitor tpiu config internal itm.txt uart off 8000000 + +# # OR: make the microcontroller SWO pin output compatible with UART (8N1) +# # 8000000 must match the core clock frequency +# # 2000000 is the frequency of the SWO pin +# monitor tpiu config external uart off 8000000 2000000 + +# # enable ITM port 0 +# monitor itm port 0 on + +load + +# start the process but immediately halt the processor +stepi From 41b9a12574f9ad992ca986b87926838fbe1f1775 Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Tue, 28 May 2024 20:36:23 -0400 Subject: [PATCH 02/19] compile pwm_input example --- examples/stm32f4/.vscode/launch.json | 2 +- examples/stm32f4/.vscode/tasks.json | 2 +- examples/stm32f4/src/bin/pwm_input.rs | 52 +++++++++++++++++++++++++++ rust-toolchain.toml | 2 +- 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 examples/stm32f4/src/bin/pwm_input.rs diff --git a/examples/stm32f4/.vscode/launch.json b/examples/stm32f4/.vscode/launch.json index 59f98070d..a9849e0da 100644 --- a/examples/stm32f4/.vscode/launch.json +++ b/examples/stm32f4/.vscode/launch.json @@ -15,7 +15,7 @@ "cwd": "${workspaceRoot}", "preLaunchTask": "Cargo Build (debug)", "runToEntryPoint": "main", - "executable": "./target/thumbv7em-none-eabihf/debug/multiprio", + "executable": "./target/thumbv7em-none-eabihf/debug/pwm_input", /* Run `cargo build --example itm` and uncomment this line to run itm example */ // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", "device": "STM32F446RET6", diff --git a/examples/stm32f4/.vscode/tasks.json b/examples/stm32f4/.vscode/tasks.json index 3cbed84b4..de7013b12 100644 --- a/examples/stm32f4/.vscode/tasks.json +++ b/examples/stm32f4/.vscode/tasks.json @@ -9,7 +9,7 @@ ], "args": [ "--bin", - "multiprio" + "pwm_input" ], "group": { "kind": "build", diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs new file mode 100644 index 000000000..49de33d2b --- /dev/null +++ b/examples/stm32f4/src/bin/pwm_input.rs @@ -0,0 +1,52 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::gpio::{Level, Output, Pull, Speed}; +use embassy_stm32::time::khz; +use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; +use embassy_stm32::timer::{self, Channel}; +use embassy_stm32::{bind_interrupts, peripherals}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +/// Connect PB2 and PB10 with a 1k Ohm resistor + +#[embassy_executor::task] +async fn blinky(led: peripherals::PB2) { + let mut led = Output::new(led, Level::High, Speed::Low); + + loop { + info!("high"); + led.set_high(); + Timer::after_millis(300).await; + + info!("low"); + led.set_low(); + Timer::after_millis(300).await; + } +} + +bind_interrupts!(struct Irqs { + TIM2 => timer::CaptureCompareInterruptHandler; +}); + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + unwrap!(spawner.spawn(blinky(p.PB2))); + + let ch3 = CapturePin::new_ch3(p.PB10, Pull::None); + let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); + + loop { + info!("wait for risign edge"); + ic.wait_for_rising_edge(Channel::Ch3).await; + + let capture_value = ic.get_capture_value(Channel::Ch3); + info!("new capture! {}", capture_value); + } +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 57185e217..2f5d17069 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.78" +channel = "1.77" components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "thumbv7em-none-eabi", From 7c1e1ee288bc46dbf030749c242d60e222d1fbe5 Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Tue, 28 May 2024 22:30:10 -0400 Subject: [PATCH 03/19] example is working now --- embassy-stm32/src/timer/input_capture.rs | 63 +++++++++++++++++++----- examples/stm32f4/.vscode/launch.json | 2 +- examples/stm32f4/.vscode/tasks.json | 2 +- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index a1c1486f9..ab6f10a1d 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -26,6 +26,10 @@ pub enum Ch3 {} /// Channel 4 marker type. pub enum Ch4 {} +fn regs_gp16(ptr: *mut ()) -> crate::pac::timer::TimGp16 { + unsafe { crate::pac::timer::TimGp16::from_ptr(ptr) } +} + /// Capture pin wrapper. /// /// This wraps a pin to make it usable with capture. @@ -76,10 +80,6 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { freq: Hertz, counting_mode: CountingMode, ) -> Self { - Self::new_inner(tim, freq, counting_mode) - } - - fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, counting_mode: CountingMode) -> Self { let mut this = Self { inner: Timer::new(tim) }; this.inner.set_counting_mode(counting_mode); @@ -148,11 +148,52 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture { - self.inner.enable_channel(channel, true); - self.inner.set_input_capture_mode(channel, mode); - self.inner.set_input_ti_selection(channel, tisel); - self.inner.clear_input_interrupt(channel); - self.inner.enable_input_interrupt(channel, true); + use stm32_metapac::timer::vals::*; + + let regs = regs_gp16(T::regs()); + let idx = channel.index(); + + // Select the active input: TIMx_CCR1 must be linked to the TI1 input, so write the CC1S + // bits to 01 in the TIMx_CCMR1 register. As soon as CC1S becomes different from 00, + // the channel is configured in input and the TIMx_CCR1 register becomes read-only. + regs.ccmr_input(idx / 2) + .modify(|r| r.set_ccs(idx % 2, CcmrInputCcs::from(tisel))); + + // Program the appropriate input filter duration in relation with the signal connected to the + // timer (by programming the ICxF bits in the TIMx_CCMRx register if the input is one of + // the TIx inputs). Let’s imagine that, when toggling, the input signal is not stable during at + // must 5 internal clock cycles. We must program a filter duration longer than these 5 + // clock cycles. We can validate a transition on TI1 when 8 consecutive samples with the + // new level have been detected (sampled at fDTS frequency). Then write IC1F bits to + // 0011 in the TIMx_CCMR1 register. + regs.ccmr_input(idx / 2) + .modify(|r| r.set_icf(idx % 2, FilterValue::NOFILTER)); + + // Select the edge of the active transition on the TI1 channel by writing the CC1P and + // CC1NP bits to 00 in the TIMx_CCER register (rising edge in this case). + let ccpnp = match mode { + InputCaptureMode::Rising => (false, false), + InputCaptureMode::Falling => (false, true), + InputCaptureMode::BothEdges => (true, true), + }; + regs.ccer().modify(|r| { + r.set_ccp(idx, ccpnp.0); + r.set_ccnp(idx, ccpnp.1); + }); + + // Program the input prescaler. In our example, we wish the capture to be performed at + // each valid transition, so the prescaler is disabled (write IC1PS bits to 00 in the + // TIMx_CCMR1 register). + regs.ccmr_input(idx / 2).modify(|r| r.set_icpsc(idx % 2, 0)); + + // Enable capture from the counter into the capture register by setting the CC1E bit in the + // TIMx_CCER register. + regs.ccer().modify(|r| r.set_cce(idx, true)); + + // If needed, enable the related interrupt request by setting the CC1IE bit in the + // TIMx_DIER register, and/or the DMA request by setting the CC1DE bit in the + // TIMx_DIER register. + regs.dier().modify(|r| r.set_ccie(idx, true)); InputCaptureFuture { channel, @@ -206,7 +247,7 @@ struct InputCaptureFuture { impl Drop for InputCaptureFuture { fn drop(&mut self) { critical_section::with(|_| { - let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) }; + let regs = regs_gp16(T::regs()); // disable interrupt enable regs.dier().modify(|w| w.set_ccie(self.channel.index(), false)); @@ -220,7 +261,7 @@ impl Future for InputCaptureFuture { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { T::state().cc_waker[self.channel.index()].register(cx.waker()); - let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) }; + let regs = regs_gp16(T::regs()); let dier = regs.dier().read(); if !dier.ccie(self.channel.index()) { diff --git a/examples/stm32f4/.vscode/launch.json b/examples/stm32f4/.vscode/launch.json index a9849e0da..20cd4d2e8 100644 --- a/examples/stm32f4/.vscode/launch.json +++ b/examples/stm32f4/.vscode/launch.json @@ -15,7 +15,7 @@ "cwd": "${workspaceRoot}", "preLaunchTask": "Cargo Build (debug)", "runToEntryPoint": "main", - "executable": "./target/thumbv7em-none-eabihf/debug/pwm_input", + "executable": "./target/thumbv7em-none-eabihf/debug/input_capture", /* Run `cargo build --example itm` and uncomment this line to run itm example */ // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", "device": "STM32F446RET6", diff --git a/examples/stm32f4/.vscode/tasks.json b/examples/stm32f4/.vscode/tasks.json index de7013b12..e153722da 100644 --- a/examples/stm32f4/.vscode/tasks.json +++ b/examples/stm32f4/.vscode/tasks.json @@ -9,7 +9,7 @@ ], "args": [ "--bin", - "pwm_input" + "input_capture" ], "group": { "kind": "build", From a52841041de7cbc6d315b3616768b531716056a0 Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Tue, 28 May 2024 22:38:08 -0400 Subject: [PATCH 04/19] use timer LL --- embassy-stm32/src/timer/input_capture.rs | 52 ++++-------------------- 1 file changed, 7 insertions(+), 45 deletions(-) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index ab6f10a1d..5dadc9131 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -148,52 +148,14 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture { - use stm32_metapac::timer::vals::*; + use stm32_metapac::timer::vals::FilterValue; - let regs = regs_gp16(T::regs()); - let idx = channel.index(); - - // Select the active input: TIMx_CCR1 must be linked to the TI1 input, so write the CC1S - // bits to 01 in the TIMx_CCMR1 register. As soon as CC1S becomes different from 00, - // the channel is configured in input and the TIMx_CCR1 register becomes read-only. - regs.ccmr_input(idx / 2) - .modify(|r| r.set_ccs(idx % 2, CcmrInputCcs::from(tisel))); - - // Program the appropriate input filter duration in relation with the signal connected to the - // timer (by programming the ICxF bits in the TIMx_CCMRx register if the input is one of - // the TIx inputs). Let’s imagine that, when toggling, the input signal is not stable during at - // must 5 internal clock cycles. We must program a filter duration longer than these 5 - // clock cycles. We can validate a transition on TI1 when 8 consecutive samples with the - // new level have been detected (sampled at fDTS frequency). Then write IC1F bits to - // 0011 in the TIMx_CCMR1 register. - regs.ccmr_input(idx / 2) - .modify(|r| r.set_icf(idx % 2, FilterValue::NOFILTER)); - - // Select the edge of the active transition on the TI1 channel by writing the CC1P and - // CC1NP bits to 00 in the TIMx_CCER register (rising edge in this case). - let ccpnp = match mode { - InputCaptureMode::Rising => (false, false), - InputCaptureMode::Falling => (false, true), - InputCaptureMode::BothEdges => (true, true), - }; - regs.ccer().modify(|r| { - r.set_ccp(idx, ccpnp.0); - r.set_ccnp(idx, ccpnp.1); - }); - - // Program the input prescaler. In our example, we wish the capture to be performed at - // each valid transition, so the prescaler is disabled (write IC1PS bits to 00 in the - // TIMx_CCMR1 register). - regs.ccmr_input(idx / 2).modify(|r| r.set_icpsc(idx % 2, 0)); - - // Enable capture from the counter into the capture register by setting the CC1E bit in the - // TIMx_CCER register. - regs.ccer().modify(|r| r.set_cce(idx, true)); - - // If needed, enable the related interrupt request by setting the CC1IE bit in the - // TIMx_DIER register, and/or the DMA request by setting the CC1DE bit in the - // TIMx_DIER register. - regs.dier().modify(|r| r.set_ccie(idx, true)); + self.inner.set_input_ti_selection(channel, tisel); + self.inner.set_input_capture_filter(channel, FilterValue::NOFILTER); + self.inner.set_input_capture_mode(channel, mode); + self.inner.set_input_capture_prescaler(channel, 0); + self.inner.enable_channel(channel, true); + self.inner.enable_input_interrupt(channel, true); InputCaptureFuture { channel, From f1d5f4ca21629036f510e52aeee617ffb70db51b Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Tue, 28 May 2024 22:43:23 -0400 Subject: [PATCH 05/19] undo minor changes --- embassy-stm32/src/timer/input_capture.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 5dadc9131..000938a70 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -26,10 +26,6 @@ pub enum Ch3 {} /// Channel 4 marker type. pub enum Ch4 {} -fn regs_gp16(ptr: *mut ()) -> crate::pac::timer::TimGp16 { - unsafe { crate::pac::timer::TimGp16::from_ptr(ptr) } -} - /// Capture pin wrapper. /// /// This wraps a pin to make it usable with capture. @@ -80,6 +76,10 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { freq: Hertz, counting_mode: CountingMode, ) -> Self { + Self::new_inner(tim, freq, counting_mode) + } + + fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, counting_mode: CountingMode) -> Self { let mut this = Self { inner: Timer::new(tim) }; this.inner.set_counting_mode(counting_mode); @@ -150,6 +150,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture { use stm32_metapac::timer::vals::FilterValue; + // Configuration steps from ST RM0390 chapter 17.3.5 Input Capture Mode self.inner.set_input_ti_selection(channel, tisel); self.inner.set_input_capture_filter(channel, FilterValue::NOFILTER); self.inner.set_input_capture_mode(channel, mode); @@ -200,6 +201,11 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } } +/// Convert pointer to TIM instance to TimGp16 object +fn regs_gp16(ptr: *mut ()) -> crate::pac::timer::TimGp16 { + unsafe { crate::pac::timer::TimGp16::from_ptr(ptr) } +} + #[must_use = "futures do nothing unless you `.await` or poll them"] struct InputCaptureFuture { channel: Channel, From a6c419d096bf2a4d14243fe90a7e2c1881b33fdf Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Tue, 28 May 2024 23:12:08 -0400 Subject: [PATCH 06/19] add f103 example for input_capture --- examples/stm32f1/.vscode/launch.json | 33 +++++++++++++++ examples/stm32f1/.vscode/tasks.json | 21 ++++++++++ examples/stm32f1/openocd.cfg | 5 +++ examples/stm32f1/openocd.gdb | 40 +++++++++++++++++++ .../src/bin/input_capture.rs} | 8 ++-- 5 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 examples/stm32f1/.vscode/launch.json create mode 100644 examples/stm32f1/.vscode/tasks.json create mode 100644 examples/stm32f1/openocd.cfg create mode 100644 examples/stm32f1/openocd.gdb rename examples/{stm32f4/src/bin/pwm_input.rs => stm32f1/src/bin/input_capture.rs} (86%) diff --git a/examples/stm32f1/.vscode/launch.json b/examples/stm32f1/.vscode/launch.json new file mode 100644 index 000000000..7d1504a39 --- /dev/null +++ b/examples/stm32f1/.vscode/launch.json @@ -0,0 +1,33 @@ +{ + /* + * Requires the Rust Language Server (rust-analyzer) and Cortex-Debug extensions + * https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer + * https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug + */ + "version": "0.2.0", + "configurations": [ + { + /* Configuration for the STM32F446 Discovery board */ + "type": "cortex-debug", + "request": "launch", + "name": "Debug (OpenOCD)", + "servertype": "openocd", + "cwd": "${workspaceRoot}", + "preLaunchTask": "Cargo Build (debug)", + "runToEntryPoint": "main", + "executable": "./target/thumbv7m-none-eabi/debug/input_capture", + /* Run `cargo build --example itm` and uncomment this line to run itm example */ + // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", + "device": "STM32F103TB", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32f1x.cfg" + ], + "postLaunchCommands": [ + "monitor arm semihosting enable" + ], + "postRestartCommands": [], + "postResetCommands": [], + } + ] +} \ No newline at end of file diff --git a/examples/stm32f1/.vscode/tasks.json b/examples/stm32f1/.vscode/tasks.json new file mode 100644 index 000000000..e153722da --- /dev/null +++ b/examples/stm32f1/.vscode/tasks.json @@ -0,0 +1,21 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "cargo", + "command": "build", + "problemMatcher": [ + "$rustc" + ], + "args": [ + "--bin", + "input_capture" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "label": "Cargo Build (debug)", + } + ] +} \ No newline at end of file diff --git a/examples/stm32f1/openocd.cfg b/examples/stm32f1/openocd.cfg new file mode 100644 index 000000000..0325cd651 --- /dev/null +++ b/examples/stm32f1/openocd.cfg @@ -0,0 +1,5 @@ +# Sample OpenOCD configuration for the STM32F3DISCOVERY development board + +source [find interface/stlink.cfg] + +source [find target/stm32f1x.cfg] diff --git a/examples/stm32f1/openocd.gdb b/examples/stm32f1/openocd.gdb new file mode 100644 index 000000000..7795319fb --- /dev/null +++ b/examples/stm32f1/openocd.gdb @@ -0,0 +1,40 @@ +target extended-remote :3333 + +# print demangled symbols +set print asm-demangle on + +# set backtrace limit to not have infinite backtrace loops +set backtrace limit 32 + +# detect unhandled exceptions, hard faults and panics +break DefaultHandler +break HardFault +break rust_begin_unwind +# # run the next few lines so the panic message is printed immediately +# # the number needs to be adjusted for your panic handler +# commands $bpnum +# next 4 +# end + +# *try* to stop at the user entry point (it might be gone due to inlining) +break main + +monitor arm semihosting enable + +# # send captured ITM to the file itm.fifo +# # (the microcontroller SWO pin must be connected to the programmer SWO pin) +# # 8000000 must match the core clock frequency +# monitor tpiu config internal itm.txt uart off 8000000 + +# # OR: make the microcontroller SWO pin output compatible with UART (8N1) +# # 8000000 must match the core clock frequency +# # 2000000 is the frequency of the SWO pin +# monitor tpiu config external uart off 8000000 2000000 + +# # enable ITM port 0 +# monitor itm port 0 on + +load + +# start the process but immediately halt the processor +stepi diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/input_capture.rs similarity index 86% rename from examples/stm32f4/src/bin/pwm_input.rs rename to examples/stm32f1/src/bin/input_capture.rs index 49de33d2b..417830231 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/input_capture.rs @@ -11,10 +11,10 @@ use embassy_stm32::{bind_interrupts, peripherals}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; -/// Connect PB2 and PB10 with a 1k Ohm resistor +/// Connect PA2 and PC13 with a 1k Ohm resistor #[embassy_executor::task] -async fn blinky(led: peripherals::PB2) { +async fn blinky(led: peripherals::PC13) { let mut led = Output::new(led, Level::High, Speed::Low); loop { @@ -37,9 +37,9 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - unwrap!(spawner.spawn(blinky(p.PB2))); + unwrap!(spawner.spawn(blinky(p.PC13))); - let ch3 = CapturePin::new_ch3(p.PB10, Pull::None); + let ch3 = CapturePin::new_ch3(p.PA2, Pull::None); let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); loop { From 521332bdd1d682b1d43ab7896b54e280c17b9771 Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Wed, 29 May 2024 00:28:26 -0400 Subject: [PATCH 07/19] pwm_input is working on F446 --- embassy-stm32/src/timer/input_capture.rs | 33 ++---- embassy-stm32/src/timer/low_level.rs | 16 +++ embassy-stm32/src/timer/mod.rs | 1 + embassy-stm32/src/timer/pwm_input.rs | 134 +++++++++++++++++++++++ examples/stm32f1/.vscode/launch.json | 2 +- examples/stm32f1/.vscode/tasks.json | 2 +- examples/stm32f1/src/bin/pwm_input.rs | 50 +++++++++ examples/stm32f4/.vscode/launch.json | 2 +- examples/stm32f4/.vscode/tasks.json | 2 +- examples/stm32f4/src/bin/pwm_input.rs | 52 +++++++++ 10 files changed, 265 insertions(+), 29 deletions(-) create mode 100644 embassy-stm32/src/timer/pwm_input.rs create mode 100644 examples/stm32f1/src/bin/pwm_input.rs create mode 100644 examples/stm32f4/src/bin/pwm_input.rs diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 000938a70..b3434ae63 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -80,18 +80,18 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, counting_mode: CountingMode) -> Self { - let mut this = Self { inner: Timer::new(tim) }; + let mut inner = Timer::new(tim); - this.inner.set_counting_mode(counting_mode); - this.set_tick_freq(freq); - this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details - this.inner.start(); + inner.set_counting_mode(counting_mode); + inner.set_tick_freq(freq); + inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details + inner.start(); // enable NVIC interrupt T::CaptureCompareInterrupt::unpend(); unsafe { T::CaptureCompareInterrupt::enable() }; - this + Self { inner } } /// Enable the given channel. @@ -109,24 +109,6 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { self.inner.get_channel_enable_state(channel) } - /// Set tick frequency. - /// - /// Note: when you call this, the max period value changes - pub fn set_tick_freq(&mut self, freq: Hertz) { - let f = freq; - assert!(f.0 > 0); - let timer_f = self.inner.get_clock_frequency(); - - let pclk_ticks_per_timer_period = timer_f / f; - let psc: u16 = unwrap!((pclk_ticks_per_timer_period - 1).try_into()); - - let regs = self.inner.regs_core(); - regs.psc().write_value(psc); - - // Generate an Update Request - regs.egr().write(|r| r.set_ug(true)); - } - /// Set the input capture mode for a given channel. pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { self.inner.set_input_capture_mode(channel, mode); @@ -150,7 +132,8 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture { use stm32_metapac::timer::vals::FilterValue; - // Configuration steps from ST RM0390 chapter 17.3.5 Input Capture Mode + // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5 + // or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode self.inner.set_input_ti_selection(channel, tisel); self.inner.set_input_capture_filter(channel, FilterValue::NOFILTER); self.inner.set_input_capture_mode(channel, mode); diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index 7f533b75c..141e96894 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -273,6 +273,22 @@ impl<'d, T: CoreInstance> Timer<'d, T> { } } + /// Set tick frequency. + pub fn set_tick_freq(&mut self, freq: Hertz) { + let f = freq; + assert!(f.0 > 0); + let timer_f = self.get_clock_frequency(); + + let pclk_ticks_per_timer_period = timer_f / f; + let psc: u16 = unwrap!((pclk_ticks_per_timer_period - 1).try_into()); + + let regs = self.regs_core(); + regs.psc().write_value(psc); + + // Generate an Update Request + regs.egr().write(|r| r.set_ug(true)); + } + /// Clear update interrupt. /// /// Returns whether the update interrupt flag was set. diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 314b6006b..25782ee13 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -8,6 +8,7 @@ use embassy_sync::waitqueue::AtomicWaker; pub mod complementary_pwm; pub mod input_capture; pub mod low_level; +pub mod pwm_input; pub mod qei; pub mod simple_pwm; diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs new file mode 100644 index 000000000..d34ba086f --- /dev/null +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -0,0 +1,134 @@ +//! Input capture driver. + +use embassy_hal_internal::into_ref; + +use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, Timer}; +use super::{Channel, Channel1Pin, Channel2Pin, GeneralInstance4Channel}; +use crate::gpio::{AFType, Pull}; +use crate::time::Hertz; +use crate::Peripheral; + +/// Input capture driver. +pub struct PwmInput<'d, T: GeneralInstance4Channel> { + channel: Channel, + inner: Timer<'d, T>, +} + +/// Convert pointer to TIM instance to TimGp16 object +fn regs_gp16(ptr: *mut ()) -> crate::pac::timer::TimGp16 { + unsafe { crate::pac::timer::TimGp16::from_ptr(ptr) } +} + +impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { + /// Create a new input capture driver. + pub fn new( + tim: impl Peripheral

+ 'd, + pin: impl Peripheral

> + 'd, + pull_type: Pull, + freq: Hertz, + ) -> Self { + into_ref!(pin); + critical_section::with(|_| { + pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); + #[cfg(gpio_v2)] + pin.set_speed(crate::gpio::Speed::VeryHigh); + }); + + Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) + } + + /// Create a new input capture driver. + pub fn new_alt( + tim: impl Peripheral

+ 'd, + pin: impl Peripheral

> + 'd, + pull_type: Pull, + freq: Hertz, + ) -> Self { + into_ref!(pin); + critical_section::with(|_| { + pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); + #[cfg(gpio_v2)] + pin.set_speed(crate::gpio::Speed::VeryHigh); + }); + + Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) + } + + fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, ch1: Channel, ch2: Channel) -> Self { + use stm32_metapac::timer::vals::{Sms, Ts}; + + let mut inner = Timer::new(tim); + + inner.set_counting_mode(CountingMode::EdgeAlignedUp); + inner.set_tick_freq(freq); + inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details + inner.start(); + + // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.6 + // or ST RM0008 (STM32F103) chapter 15.3.6 Input capture mode + inner.set_input_ti_selection(ch1, InputTISelection::Normal); + inner.set_input_capture_mode(ch1, InputCaptureMode::Rising); + + inner.set_input_ti_selection(ch2, InputTISelection::Alternate); + inner.set_input_capture_mode(ch2, InputCaptureMode::Falling); + + let regs = regs_gp16(T::regs()); + regs.smcr().modify(|r| { + // Select the valid trigger input: write the TS bits to 101 in the TIMx_SMCR register + // (TI1FP1 selected). + r.set_ts(match ch1 { + Channel::Ch1 => Ts::TI1FP1, + Channel::Ch2 => Ts::TI2FP2, + _ => panic!("Invalid channel for PWM input"), + }); + + // Configure the slave mode controller in reset mode: write the SMS bits to 100 in the + // TIMx_SMCR register. + r.set_sms(Sms::RESET_MODE); + }); + + // Must call the `enable` function after + + Self { channel: ch1, inner } + } + + /// Enable the given channel. + pub fn enable(&mut self) { + self.inner.enable_channel(Channel::Ch1, true); + self.inner.enable_channel(Channel::Ch2, true); + } + + /// Disable the given channel. + pub fn disable(&mut self) { + self.inner.enable_channel(Channel::Ch1, false); + self.inner.enable_channel(Channel::Ch2, false); + } + + /// Check whether given channel is enabled + pub fn is_enabled(&self) -> bool { + self.inner.get_channel_enable_state(Channel::Ch1) + } + + /// Get the period tick count + pub fn get_period_ticks(&self) -> u32 { + self.inner.get_capture_value(self.channel) + } + + /// Get the duty tick count + pub fn get_duty_ticks(&self) -> u32 { + self.inner.get_capture_value(match self.channel { + Channel::Ch1 => Channel::Ch2, + Channel::Ch2 => Channel::Ch1, + _ => panic!("Invalid channel for PWM input"), + }) + } + + /// Get the duty cycle in 100% + pub fn get_duty_cycle(&self) -> f32 { + let period = self.get_period_ticks(); + if period == 0 { + return 0.; + } + 100. * (self.get_duty_ticks() as f32) / (period as f32) + } +} diff --git a/examples/stm32f1/.vscode/launch.json b/examples/stm32f1/.vscode/launch.json index 7d1504a39..998508867 100644 --- a/examples/stm32f1/.vscode/launch.json +++ b/examples/stm32f1/.vscode/launch.json @@ -15,7 +15,7 @@ "cwd": "${workspaceRoot}", "preLaunchTask": "Cargo Build (debug)", "runToEntryPoint": "main", - "executable": "./target/thumbv7m-none-eabi/debug/input_capture", + "executable": "./target/thumbv7m-none-eabi/debug/pwm_input", /* Run `cargo build --example itm` and uncomment this line to run itm example */ // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", "device": "STM32F103TB", diff --git a/examples/stm32f1/.vscode/tasks.json b/examples/stm32f1/.vscode/tasks.json index e153722da..de7013b12 100644 --- a/examples/stm32f1/.vscode/tasks.json +++ b/examples/stm32f1/.vscode/tasks.json @@ -9,7 +9,7 @@ ], "args": [ "--bin", - "input_capture" + "pwm_input" ], "group": { "kind": "build", diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs new file mode 100644 index 000000000..14978f817 --- /dev/null +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -0,0 +1,50 @@ +#![no_std] +#![no_main] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::gpio::{Level, Output, Pull, Speed}; +use embassy_stm32::time::khz; +use embassy_stm32::timer::{self, pwm_input::PwmInput}; +use embassy_stm32::{bind_interrupts, peripherals}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +/// Connect PB2 and PB10 with a 1k Ohm resistor + +#[embassy_executor::task] +async fn blinky(led: peripherals::PC13) { + let mut led = Output::new(led, Level::High, Speed::Low); + + loop { + info!("high"); + led.set_high(); + Timer::after_millis(300).await; + + info!("low"); + led.set_low(); + Timer::after_millis(300).await; + } +} + +bind_interrupts!(struct Irqs { + TIM2 => timer::CaptureCompareInterruptHandler; +}); + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + unwrap!(spawner.spawn(blinky(p.PC13))); + + let pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(1000)); + + loop { + Timer::after_millis(500).await; + let _per = pwm_input.get_period_ticks(); + let _dc = pwm_input.get_duty_ticks(); + let _pc = pwm_input.get_duty_cycle(); + asm::nop(); + } +} diff --git a/examples/stm32f4/.vscode/launch.json b/examples/stm32f4/.vscode/launch.json index 20cd4d2e8..a9849e0da 100644 --- a/examples/stm32f4/.vscode/launch.json +++ b/examples/stm32f4/.vscode/launch.json @@ -15,7 +15,7 @@ "cwd": "${workspaceRoot}", "preLaunchTask": "Cargo Build (debug)", "runToEntryPoint": "main", - "executable": "./target/thumbv7em-none-eabihf/debug/input_capture", + "executable": "./target/thumbv7em-none-eabihf/debug/pwm_input", /* Run `cargo build --example itm` and uncomment this line to run itm example */ // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", "device": "STM32F446RET6", diff --git a/examples/stm32f4/.vscode/tasks.json b/examples/stm32f4/.vscode/tasks.json index e153722da..de7013b12 100644 --- a/examples/stm32f4/.vscode/tasks.json +++ b/examples/stm32f4/.vscode/tasks.json @@ -9,7 +9,7 @@ ], "args": [ "--bin", - "input_capture" + "pwm_input" ], "group": { "kind": "build", diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs new file mode 100644 index 000000000..e57e58c22 --- /dev/null +++ b/examples/stm32f4/src/bin/pwm_input.rs @@ -0,0 +1,52 @@ +#![no_std] +#![no_main] + +use cortex_m::asm; +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::gpio::{Level, Output, Pull, Speed}; +use embassy_stm32::time::khz; +use embassy_stm32::timer::{self, pwm_input::PwmInput}; +use embassy_stm32::{bind_interrupts, peripherals}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +/// Connect PB2 and PB10 with a 1k Ohm resistor + +#[embassy_executor::task] +async fn blinky(led: peripherals::PB2) { + let mut led = Output::new(led, Level::High, Speed::Low); + + loop { + info!("high"); + led.set_high(); + Timer::after_millis(300).await; + + info!("low"); + led.set_low(); + Timer::after_millis(300).await; + } +} + +bind_interrupts!(struct Irqs { + TIM2 => timer::CaptureCompareInterruptHandler; +}); + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + unwrap!(spawner.spawn(blinky(p.PB2))); + + let mut pwm_input = PwmInput::new(p.TIM3, p.PA6, Pull::None, khz(10)); + pwm_input.enable(); + + loop { + Timer::after_millis(500).await; + let _per = pwm_input.get_period_ticks(); + let _dc = pwm_input.get_duty_ticks(); + let _pc = pwm_input.get_duty_cycle(); + asm::nop(); + } +} From 50039b17a78bbefeca1a3dd6b689ea478079ea6b Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Wed, 29 May 2024 00:33:35 -0400 Subject: [PATCH 08/19] fix F103 example --- examples/stm32f1/.vscode/launch.json | 2 +- examples/stm32f1/src/bin/pwm_input.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/stm32f1/.vscode/launch.json b/examples/stm32f1/.vscode/launch.json index 998508867..71f203614 100644 --- a/examples/stm32f1/.vscode/launch.json +++ b/examples/stm32f1/.vscode/launch.json @@ -18,7 +18,7 @@ "executable": "./target/thumbv7m-none-eabi/debug/pwm_input", /* Run `cargo build --example itm` and uncomment this line to run itm example */ // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", - "device": "STM32F103TB", + "device": "STM32F103T8", "configFiles": [ "interface/stlink.cfg", "target/stm32f1x.cfg" diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index 14978f817..718bf0fcf 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -1,6 +1,7 @@ #![no_std] #![no_main] +use cortex_m::asm; use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; @@ -38,7 +39,8 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(blinky(p.PC13))); - let pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(1000)); + let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(10)); + pwm_input.enable(); loop { Timer::after_millis(500).await; From 69badfb845c0fb43b4e4c1c2e9f74a535fcd317a Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Wed, 29 May 2024 00:37:50 -0400 Subject: [PATCH 09/19] remove dev files --- examples/stm32f1/.vscode/launch.json | 33 ----------------------- examples/stm32f1/.vscode/tasks.json | 21 --------------- examples/stm32f1/openocd.cfg | 5 ---- examples/stm32f1/openocd.gdb | 40 ---------------------------- examples/stm32f4/.cargo/config.toml | 6 ++--- examples/stm32f4/.vscode/launch.json | 33 ----------------------- examples/stm32f4/.vscode/tasks.json | 21 --------------- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f4/openocd.cfg | 5 ---- examples/stm32f4/openocd.gdb | 40 ---------------------------- rust-toolchain.toml | 2 +- 11 files changed, 4 insertions(+), 204 deletions(-) delete mode 100644 examples/stm32f1/.vscode/launch.json delete mode 100644 examples/stm32f1/.vscode/tasks.json delete mode 100644 examples/stm32f1/openocd.cfg delete mode 100644 examples/stm32f1/openocd.gdb delete mode 100644 examples/stm32f4/.vscode/launch.json delete mode 100644 examples/stm32f4/.vscode/tasks.json delete mode 100644 examples/stm32f4/openocd.cfg delete mode 100644 examples/stm32f4/openocd.gdb diff --git a/examples/stm32f1/.vscode/launch.json b/examples/stm32f1/.vscode/launch.json deleted file mode 100644 index 71f203614..000000000 --- a/examples/stm32f1/.vscode/launch.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - /* - * Requires the Rust Language Server (rust-analyzer) and Cortex-Debug extensions - * https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer - * https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug - */ - "version": "0.2.0", - "configurations": [ - { - /* Configuration for the STM32F446 Discovery board */ - "type": "cortex-debug", - "request": "launch", - "name": "Debug (OpenOCD)", - "servertype": "openocd", - "cwd": "${workspaceRoot}", - "preLaunchTask": "Cargo Build (debug)", - "runToEntryPoint": "main", - "executable": "./target/thumbv7m-none-eabi/debug/pwm_input", - /* Run `cargo build --example itm` and uncomment this line to run itm example */ - // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", - "device": "STM32F103T8", - "configFiles": [ - "interface/stlink.cfg", - "target/stm32f1x.cfg" - ], - "postLaunchCommands": [ - "monitor arm semihosting enable" - ], - "postRestartCommands": [], - "postResetCommands": [], - } - ] -} \ No newline at end of file diff --git a/examples/stm32f1/.vscode/tasks.json b/examples/stm32f1/.vscode/tasks.json deleted file mode 100644 index de7013b12..000000000 --- a/examples/stm32f1/.vscode/tasks.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "cargo", - "command": "build", - "problemMatcher": [ - "$rustc" - ], - "args": [ - "--bin", - "pwm_input" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "label": "Cargo Build (debug)", - } - ] -} \ No newline at end of file diff --git a/examples/stm32f1/openocd.cfg b/examples/stm32f1/openocd.cfg deleted file mode 100644 index 0325cd651..000000000 --- a/examples/stm32f1/openocd.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Sample OpenOCD configuration for the STM32F3DISCOVERY development board - -source [find interface/stlink.cfg] - -source [find target/stm32f1x.cfg] diff --git a/examples/stm32f1/openocd.gdb b/examples/stm32f1/openocd.gdb deleted file mode 100644 index 7795319fb..000000000 --- a/examples/stm32f1/openocd.gdb +++ /dev/null @@ -1,40 +0,0 @@ -target extended-remote :3333 - -# print demangled symbols -set print asm-demangle on - -# set backtrace limit to not have infinite backtrace loops -set backtrace limit 32 - -# detect unhandled exceptions, hard faults and panics -break DefaultHandler -break HardFault -break rust_begin_unwind -# # run the next few lines so the panic message is printed immediately -# # the number needs to be adjusted for your panic handler -# commands $bpnum -# next 4 -# end - -# *try* to stop at the user entry point (it might be gone due to inlining) -break main - -monitor arm semihosting enable - -# # send captured ITM to the file itm.fifo -# # (the microcontroller SWO pin must be connected to the programmer SWO pin) -# # 8000000 must match the core clock frequency -# monitor tpiu config internal itm.txt uart off 8000000 - -# # OR: make the microcontroller SWO pin output compatible with UART (8N1) -# # 8000000 must match the core clock frequency -# # 2000000 is the frequency of the SWO pin -# monitor tpiu config external uart off 8000000 2000000 - -# # enable ITM port 0 -# monitor itm port 0 on - -load - -# start the process but immediately halt the processor -stepi diff --git a/examples/stm32f4/.cargo/config.toml b/examples/stm32f4/.cargo/config.toml index f5a4af51a..16efa8e6f 100644 --- a/examples/stm32f4/.cargo/config.toml +++ b/examples/stm32f4/.cargo/config.toml @@ -1,11 +1,9 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] # replace STM32F429ZITx with your chip as listed in `probe-rs chip list` -# runner = "probe-rs run --chip STM32F429ZITx" -runner = "arm-none-eabi-gdb -q -x openocd.gdb" +runner = "probe-rs run --chip STM32F429ZITx" [build] -# target = "thumbv7em-none-eabi" -target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) +target = "thumbv7em-none-eabi" [env] DEFMT_LOG = "trace" diff --git a/examples/stm32f4/.vscode/launch.json b/examples/stm32f4/.vscode/launch.json deleted file mode 100644 index a9849e0da..000000000 --- a/examples/stm32f4/.vscode/launch.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - /* - * Requires the Rust Language Server (rust-analyzer) and Cortex-Debug extensions - * https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer - * https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug - */ - "version": "0.2.0", - "configurations": [ - { - /* Configuration for the STM32F446 Discovery board */ - "type": "cortex-debug", - "request": "launch", - "name": "Debug (OpenOCD)", - "servertype": "openocd", - "cwd": "${workspaceRoot}", - "preLaunchTask": "Cargo Build (debug)", - "runToEntryPoint": "main", - "executable": "./target/thumbv7em-none-eabihf/debug/pwm_input", - /* Run `cargo build --example itm` and uncomment this line to run itm example */ - // "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm", - "device": "STM32F446RET6", - "configFiles": [ - "interface/stlink.cfg", - "target/stm32f4x.cfg" - ], - "postLaunchCommands": [ - "monitor arm semihosting enable" - ], - "postRestartCommands": [], - "postResetCommands": [], - } - ] -} \ No newline at end of file diff --git a/examples/stm32f4/.vscode/tasks.json b/examples/stm32f4/.vscode/tasks.json deleted file mode 100644 index de7013b12..000000000 --- a/examples/stm32f4/.vscode/tasks.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "cargo", - "command": "build", - "problemMatcher": [ - "$rustc" - ], - "args": [ - "--bin", - "pwm_input" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "label": "Cargo Build (debug)", - } - ] -} \ No newline at end of file diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index ee7594c95..1eb1ae6db 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f429zi to your chip name, if necessary. -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f446re", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] } embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } diff --git a/examples/stm32f4/openocd.cfg b/examples/stm32f4/openocd.cfg deleted file mode 100644 index e41d52b1a..000000000 --- a/examples/stm32f4/openocd.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# Sample OpenOCD configuration for the STM32F3DISCOVERY development board - -source [find interface/stlink.cfg] - -source [find target/stm32f4x.cfg] diff --git a/examples/stm32f4/openocd.gdb b/examples/stm32f4/openocd.gdb deleted file mode 100644 index 7795319fb..000000000 --- a/examples/stm32f4/openocd.gdb +++ /dev/null @@ -1,40 +0,0 @@ -target extended-remote :3333 - -# print demangled symbols -set print asm-demangle on - -# set backtrace limit to not have infinite backtrace loops -set backtrace limit 32 - -# detect unhandled exceptions, hard faults and panics -break DefaultHandler -break HardFault -break rust_begin_unwind -# # run the next few lines so the panic message is printed immediately -# # the number needs to be adjusted for your panic handler -# commands $bpnum -# next 4 -# end - -# *try* to stop at the user entry point (it might be gone due to inlining) -break main - -monitor arm semihosting enable - -# # send captured ITM to the file itm.fifo -# # (the microcontroller SWO pin must be connected to the programmer SWO pin) -# # 8000000 must match the core clock frequency -# monitor tpiu config internal itm.txt uart off 8000000 - -# # OR: make the microcontroller SWO pin output compatible with UART (8N1) -# # 8000000 must match the core clock frequency -# # 2000000 is the frequency of the SWO pin -# monitor tpiu config external uart off 8000000 2000000 - -# # enable ITM port 0 -# monitor itm port 0 on - -load - -# start the process but immediately halt the processor -stepi diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 2f5d17069..57185e217 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.77" +channel = "1.78" components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "thumbv7em-none-eabi", From 61f1f80e90c3fd8ec505936f3bab0a50d2ba9b79 Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Wed, 29 May 2024 00:52:55 -0400 Subject: [PATCH 10/19] fix fmt --- examples/stm32f1/src/bin/pwm_input.rs | 3 ++- examples/stm32f4/src/bin/pwm_input.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index 718bf0fcf..9ca44d048 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -6,7 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; use embassy_stm32::time::khz; -use embassy_stm32::timer::{self, pwm_input::PwmInput}; +use embassy_stm32::timer; +use embassy_stm32::timer::pwm_input::PwmInput; use embassy_stm32::{bind_interrupts, peripherals}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs index e57e58c22..98ea50df4 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f4/src/bin/pwm_input.rs @@ -6,7 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; use embassy_stm32::time::khz; -use embassy_stm32::timer::{self, pwm_input::PwmInput}; +use embassy_stm32::timer; +use embassy_stm32::timer::pwm_input::PwmInput; use embassy_stm32::{bind_interrupts, peripherals}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; From 7f4803ddaf8f6eeeec45418f23b092bff95222d2 Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Wed, 29 May 2024 00:55:49 -0400 Subject: [PATCH 11/19] fix fmt again --- examples/stm32f1/src/bin/pwm_input.rs | 3 +-- examples/stm32f4/src/bin/pwm_input.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index 9ca44d048..c051d1328 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -6,9 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; use embassy_stm32::time::khz; -use embassy_stm32::timer; use embassy_stm32::timer::pwm_input::PwmInput; -use embassy_stm32::{bind_interrupts, peripherals}; +use embassy_stm32::{bind_interrupts, peripherals, timer}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs index 98ea50df4..eb1e7cb87 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f4/src/bin/pwm_input.rs @@ -6,9 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; use embassy_stm32::time::khz; -use embassy_stm32::timer; use embassy_stm32::timer::pwm_input::PwmInput; -use embassy_stm32::{bind_interrupts, peripherals}; +use embassy_stm32::{bind_interrupts, peripherals, timer}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; From a23fa8dcb2e22ed2d8bac15fd875dfe53af43eda Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Wed, 29 May 2024 09:14:05 -0400 Subject: [PATCH 12/19] Apply suggestions from code review Co-authored-by: Romain Reignier --- embassy-stm32/src/timer/pwm_input.rs | 8 ++++---- examples/stm32f1/src/bin/input_capture.rs | 2 +- examples/stm32f1/src/bin/pwm_input.rs | 2 +- examples/stm32f4/src/bin/pwm_input.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index d34ba086f..d3fe7632a 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -1,4 +1,4 @@ -//! Input capture driver. +//! PWM Input driver. use embassy_hal_internal::into_ref; @@ -8,7 +8,7 @@ use crate::gpio::{AFType, Pull}; use crate::time::Hertz; use crate::Peripheral; -/// Input capture driver. +/// PWM Input driver. pub struct PwmInput<'d, T: GeneralInstance4Channel> { channel: Channel, inner: Timer<'d, T>, @@ -20,7 +20,7 @@ fn regs_gp16(ptr: *mut ()) -> crate::pac::timer::TimGp16 { } impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { - /// Create a new input capture driver. + /// Create a new PWM input driver. pub fn new( tim: impl Peripheral

+ 'd, pin: impl Peripheral

> + 'd, @@ -37,7 +37,7 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) } - /// Create a new input capture driver. + /// Create a new PWM input driver. pub fn new_alt( tim: impl Peripheral

+ 'd, pin: impl Peripheral

> + 'd, diff --git a/examples/stm32f1/src/bin/input_capture.rs b/examples/stm32f1/src/bin/input_capture.rs index 417830231..5e2dab9e6 100644 --- a/examples/stm32f1/src/bin/input_capture.rs +++ b/examples/stm32f1/src/bin/input_capture.rs @@ -43,7 +43,7 @@ async fn main(spawner: Spawner) { let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); loop { - info!("wait for risign edge"); + info!("wait for rising edge"); ic.wait_for_rising_edge(Channel::Ch3).await; let capture_value = ic.get_capture_value(Channel::Ch3); diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index c051d1328..de6949eb4 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -11,7 +11,7 @@ use embassy_stm32::{bind_interrupts, peripherals, timer}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; -/// Connect PB2 and PB10 with a 1k Ohm resistor +/// Connect PA0 and PC13 with a 1k Ohm resistor #[embassy_executor::task] async fn blinky(led: peripherals::PC13) { diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs index eb1e7cb87..30cefac3a 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f4/src/bin/pwm_input.rs @@ -11,7 +11,7 @@ use embassy_stm32::{bind_interrupts, peripherals, timer}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; -/// Connect PB2 and PB10 with a 1k Ohm resistor +/// Connect PB2 and PA6 with a 1k Ohm resistor #[embassy_executor::task] async fn blinky(led: peripherals::PB2) { From 292c1dd0b858fe8dde74edd2f60a96f4c9e588da Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Wed, 29 May 2024 09:58:46 -0400 Subject: [PATCH 13/19] rename get_width_ticks and add info!() in examples --- embassy-stm32/src/timer/pwm_input.rs | 6 +++--- examples/stm32f1/src/bin/pwm_input.rs | 9 ++++----- examples/stm32f4/src/bin/pwm_input.rs | 9 ++++----- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index d3fe7632a..7bcb7802a 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -114,8 +114,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { self.inner.get_capture_value(self.channel) } - /// Get the duty tick count - pub fn get_duty_ticks(&self) -> u32 { + /// Get the pulse width tick count + pub fn get_width_ticks(&self) -> u32 { self.inner.get_capture_value(match self.channel { Channel::Ch1 => Channel::Ch2, Channel::Ch2 => Channel::Ch1, @@ -129,6 +129,6 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { if period == 0 { return 0.; } - 100. * (self.get_duty_ticks() as f32) / (period as f32) + 100. * (self.get_width_ticks() as f32) / (period as f32) } } diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index de6949eb4..9883280cf 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -1,7 +1,6 @@ #![no_std] #![no_main] -use cortex_m::asm; use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; @@ -44,9 +43,9 @@ async fn main(spawner: Spawner) { loop { Timer::after_millis(500).await; - let _per = pwm_input.get_period_ticks(); - let _dc = pwm_input.get_duty_ticks(); - let _pc = pwm_input.get_duty_cycle(); - asm::nop(); + let period = pwm_input.get_period_ticks(); + let width = pwm_input.get_width_ticks(); + let duty_cycle = pwm_input.get_duty_cycle(); + info!("period ticks: {} width ticks: {} duty cycle: {}", period, width, duty_cycle); } } diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs index 30cefac3a..8fe1fdb5b 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f4/src/bin/pwm_input.rs @@ -1,7 +1,6 @@ #![no_std] #![no_main] -use cortex_m::asm; use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Pull, Speed}; @@ -44,9 +43,9 @@ async fn main(spawner: Spawner) { loop { Timer::after_millis(500).await; - let _per = pwm_input.get_period_ticks(); - let _dc = pwm_input.get_duty_ticks(); - let _pc = pwm_input.get_duty_cycle(); - asm::nop(); + let period = pwm_input.get_period_ticks(); + let width = pwm_input.get_width_ticks(); + let duty_cycle = pwm_input.get_duty_cycle(); + info!("period ticks: {} width ticks: {} duty cycle: {}", period, width, duty_cycle); } } From a87b33303403ba3601d0c631b9efe1cb3853c73b Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Wed, 29 May 2024 10:02:54 -0400 Subject: [PATCH 14/19] fix fmt --- examples/stm32f1/src/bin/pwm_input.rs | 5 ++++- examples/stm32f4/src/bin/pwm_input.rs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs index 9883280cf..f74853d4e 100644 --- a/examples/stm32f1/src/bin/pwm_input.rs +++ b/examples/stm32f1/src/bin/pwm_input.rs @@ -46,6 +46,9 @@ async fn main(spawner: Spawner) { let period = pwm_input.get_period_ticks(); let width = pwm_input.get_width_ticks(); let duty_cycle = pwm_input.get_duty_cycle(); - info!("period ticks: {} width ticks: {} duty cycle: {}", period, width, duty_cycle); + info!( + "period ticks: {} width ticks: {} duty cycle: {}", + period, width, duty_cycle + ); } } diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs index 8fe1fdb5b..ce200549d 100644 --- a/examples/stm32f4/src/bin/pwm_input.rs +++ b/examples/stm32f4/src/bin/pwm_input.rs @@ -46,6 +46,9 @@ async fn main(spawner: Spawner) { let period = pwm_input.get_period_ticks(); let width = pwm_input.get_width_ticks(); let duty_cycle = pwm_input.get_duty_cycle(); - info!("period ticks: {} width ticks: {} duty cycle: {}", period, width, duty_cycle); + info!( + "period ticks: {} width ticks: {} duty cycle: {}", + period, width, duty_cycle + ); } } From 84707af5d7f3e62caafed06c416cf12fa82e4664 Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Thu, 30 May 2024 17:43:38 -0400 Subject: [PATCH 15/19] create functions in inner to handle register modification --- embassy-stm32/src/timer/input_capture.rs | 21 ++++-------- embassy-stm32/src/timer/low_level.rs | 14 ++++++++ embassy-stm32/src/timer/pwm_input.rs | 42 +++++++----------------- 3 files changed, 31 insertions(+), 46 deletions(-) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index b3434ae63..8d1a77867 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -7,7 +7,7 @@ use core::task::{Context, Poll}; use embassy_hal_internal::{into_ref, PeripheralRef}; -use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, Timer}; +use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer}; use super::{ CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel, @@ -40,11 +40,9 @@ macro_rules! channel_impl { #[doc = concat!("Create a new ", stringify!($channel), " capture pin instance.")] pub fn $new_chx(pin: impl Peripheral

> + 'd, pull_type: Pull) -> Self { into_ref!(pin); - critical_section::with(|_| { - pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); - #[cfg(gpio_v2)] - pin.set_speed(crate::gpio::Speed::VeryHigh); - }); + + pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); + CapturePin { _pin: pin.map_into(), phantom: PhantomData, @@ -130,8 +128,6 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture { - use stm32_metapac::timer::vals::FilterValue; - // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5 // or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode self.inner.set_input_ti_selection(channel, tisel); @@ -184,11 +180,6 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } } -/// Convert pointer to TIM instance to TimGp16 object -fn regs_gp16(ptr: *mut ()) -> crate::pac::timer::TimGp16 { - unsafe { crate::pac::timer::TimGp16::from_ptr(ptr) } -} - #[must_use = "futures do nothing unless you `.await` or poll them"] struct InputCaptureFuture { channel: Channel, @@ -198,7 +189,7 @@ struct InputCaptureFuture { impl Drop for InputCaptureFuture { fn drop(&mut self) { critical_section::with(|_| { - let regs = regs_gp16(T::regs()); + let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) }; // disable interrupt enable regs.dier().modify(|w| w.set_ccie(self.channel.index(), false)); @@ -212,7 +203,7 @@ impl Future for InputCaptureFuture { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { T::state().cc_waker[self.channel.index()].register(cx.waker()); - let regs = regs_gp16(T::regs()); + let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) }; let dier = regs.dier().read(); if !dier.ccie(self.channel.index()) { diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index 141e96894..8482fad7b 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -12,6 +12,10 @@ use super::*; use crate::pac::timer::vals; use crate::time::Hertz; +pub use stm32_metapac::timer::vals::FilterValue; +pub use stm32_metapac::timer::vals::Sms as SlaveMode; +pub use stm32_metapac::timer::vals::Ts as TriggerSource; + /// Input capture mode. #[derive(Clone, Copy)] pub enum InputCaptureMode { @@ -588,6 +592,16 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) } + + /// Set Timer Slave Mode + pub fn set_slave_mode(&self, sms: SlaveMode) { + self.regs_gp16().smcr().modify(|r| r.set_sms(sms)); + } + + /// Set Timer Trigger Source + pub fn set_trigger_source(&self, ts: TriggerSource) { + self.regs_gp16().smcr().modify(|r| r.set_ts(ts)); + } } #[cfg(not(stm32l0))] diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 7bcb7802a..dcf098a78 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -2,7 +2,7 @@ use embassy_hal_internal::into_ref; -use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, Timer}; +use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource}; use super::{Channel, Channel1Pin, Channel2Pin, GeneralInstance4Channel}; use crate::gpio::{AFType, Pull}; use crate::time::Hertz; @@ -14,11 +14,6 @@ pub struct PwmInput<'d, T: GeneralInstance4Channel> { inner: Timer<'d, T>, } -/// Convert pointer to TIM instance to TimGp16 object -fn regs_gp16(ptr: *mut ()) -> crate::pac::timer::TimGp16 { - unsafe { crate::pac::timer::TimGp16::from_ptr(ptr) } -} - impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Create a new PWM input driver. pub fn new( @@ -28,11 +23,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { freq: Hertz, ) -> Self { into_ref!(pin); - critical_section::with(|_| { - pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); - #[cfg(gpio_v2)] - pin.set_speed(crate::gpio::Speed::VeryHigh); - }); + + pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) } @@ -45,18 +37,13 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { freq: Hertz, ) -> Self { into_ref!(pin); - critical_section::with(|_| { - pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); - #[cfg(gpio_v2)] - pin.set_speed(crate::gpio::Speed::VeryHigh); - }); + + pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) } fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, ch1: Channel, ch2: Channel) -> Self { - use stm32_metapac::timer::vals::{Sms, Ts}; - let mut inner = Timer::new(tim); inner.set_counting_mode(CountingMode::EdgeAlignedUp); @@ -72,21 +59,14 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { inner.set_input_ti_selection(ch2, InputTISelection::Alternate); inner.set_input_capture_mode(ch2, InputCaptureMode::Falling); - let regs = regs_gp16(T::regs()); - regs.smcr().modify(|r| { - // Select the valid trigger input: write the TS bits to 101 in the TIMx_SMCR register - // (TI1FP1 selected). - r.set_ts(match ch1 { - Channel::Ch1 => Ts::TI1FP1, - Channel::Ch2 => Ts::TI2FP2, - _ => panic!("Invalid channel for PWM input"), - }); - - // Configure the slave mode controller in reset mode: write the SMS bits to 100 in the - // TIMx_SMCR register. - r.set_sms(Sms::RESET_MODE); + inner.set_trigger_source(match ch1 { + Channel::Ch1 => TriggerSource::TI1FP1, + Channel::Ch2 => TriggerSource::TI2FP2, + _ => panic!("Invalid channel for PWM input"), }); + inner.set_slave_mode(SlaveMode::RESET_MODE); + // Must call the `enable` function after Self { channel: ch1, inner } From 4d307b5a7763a2d38de201bdef787bee07afe022 Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Thu, 30 May 2024 17:49:20 -0400 Subject: [PATCH 16/19] undo changes in input_capture --- embassy-stm32/src/timer/input_capture.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 8d1a77867..0258d4077 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -78,18 +78,18 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, counting_mode: CountingMode) -> Self { - let mut inner = Timer::new(tim); + let mut this = Self { inner: Timer::new(tim) }; - inner.set_counting_mode(counting_mode); - inner.set_tick_freq(freq); - inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details - inner.start(); + this.inner.set_counting_mode(counting_mode); + this.inner.set_tick_freq(freq); + this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details + this.inner.start(); // enable NVIC interrupt T::CaptureCompareInterrupt::unpend(); unsafe { T::CaptureCompareInterrupt::enable() }; - Self { inner } + this } /// Enable the given channel. From 713d84f7789570c069c4880c1225bed4dc2bc3ae Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Thu, 30 May 2024 17:51:48 -0400 Subject: [PATCH 17/19] fix fmt --- embassy-stm32/src/timer/low_level.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index 8482fad7b..a53acc1d5 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -12,9 +12,7 @@ use super::*; use crate::pac::timer::vals; use crate::time::Hertz; -pub use stm32_metapac::timer::vals::FilterValue; -pub use stm32_metapac::timer::vals::Sms as SlaveMode; -pub use stm32_metapac::timer::vals::Ts as TriggerSource; +pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource}; /// Input capture mode. #[derive(Clone, Copy)] From 83b5797b8da1433568f0a584c7e5eb15ed25785e Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Thu, 30 May 2024 17:53:38 -0400 Subject: [PATCH 18/19] fix fmt (again) --- embassy-stm32/src/timer/low_level.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index a53acc1d5..be1692fc2 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -8,12 +8,13 @@ use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; +// Re-export useful enums +pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource}; + use super::*; use crate::pac::timer::vals; use crate::time::Hertz; -pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource}; - /// Input capture mode. #[derive(Clone, Copy)] pub enum InputCaptureMode { From 7d869192571c0e49da425afbdc37433b8a820786 Mon Sep 17 00:00:00 2001 From: Bruno Bousquet <21108660+brunob45@users.noreply.github.com> Date: Thu, 30 May 2024 17:54:49 -0400 Subject: [PATCH 19/19] rust fmt really does not want blank space there --- embassy-stm32/src/timer/low_level.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index be1692fc2..300ea812c 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -7,7 +7,6 @@ //! The available functionality depends on the timer type. use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; - // Re-export useful enums pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource};