Removed global static signal and added signal to interrupt state. Nice: signaling can be done in immutable environment. Added extra pin to test to be able to measure with logic scope
This commit is contained in:
parent
1b9cbe47aa
commit
9f4af99b57
@ -2,12 +2,24 @@ pub mod complementary_pwm;
|
|||||||
pub mod qei;
|
pub mod qei;
|
||||||
pub mod simple_pwm;
|
pub mod simple_pwm;
|
||||||
|
|
||||||
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
|
use embassy_sync::signal::Signal;
|
||||||
use stm32_metapac::timer::vals;
|
use stm32_metapac::timer::vals;
|
||||||
|
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
use crate::rcc::RccPeripheral;
|
use crate::rcc::RccPeripheral;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
|
||||||
|
pub struct State {
|
||||||
|
signal: Signal<CriticalSectionRawMutex, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub(crate) const fn new() -> Self {
|
||||||
|
Self { signal: Signal::new() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable-pac")]
|
#[cfg(feature = "unstable-pac")]
|
||||||
pub mod low_level {
|
pub mod low_level {
|
||||||
pub use super::sealed::*;
|
pub use super::sealed::*;
|
||||||
@ -91,6 +103,7 @@ pub(crate) mod sealed {
|
|||||||
|
|
||||||
pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
|
pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
|
||||||
fn regs_gp16() -> crate::pac::timer::TimGp16;
|
fn regs_gp16() -> crate::pac::timer::TimGp16;
|
||||||
|
fn state() -> &'static State;
|
||||||
|
|
||||||
fn set_counting_mode(&mut self, mode: CountingMode) {
|
fn set_counting_mode(&mut self, mode: CountingMode) {
|
||||||
let (cms, dir) = mode.into();
|
let (cms, dir) = mode.into();
|
||||||
@ -510,6 +523,11 @@ foreach_interrupt! {
|
|||||||
fn regs_gp16() -> crate::pac::timer::TimGp16 {
|
fn regs_gp16() -> crate::pac::timer::TimGp16 {
|
||||||
crate::pac::$inst
|
crate::pac::$inst
|
||||||
}
|
}
|
||||||
|
fn state() -> &'static State {
|
||||||
|
static STATE: State = State::new();
|
||||||
|
&STATE
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -528,6 +546,11 @@ foreach_interrupt! {
|
|||||||
fn regs_gp16() -> crate::pac::timer::TimGp16 {
|
fn regs_gp16() -> crate::pac::timer::TimGp16 {
|
||||||
unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
|
unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
|
||||||
}
|
}
|
||||||
|
fn state() -> &'static State {
|
||||||
|
static STATE: State = State::new();
|
||||||
|
&STATE
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -551,6 +574,10 @@ foreach_interrupt! {
|
|||||||
fn regs_gp16() -> crate::pac::timer::TimGp16 {
|
fn regs_gp16() -> crate::pac::timer::TimGp16 {
|
||||||
unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
|
unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
|
||||||
}
|
}
|
||||||
|
fn state() -> &'static State {
|
||||||
|
static STATE: State = State::new();
|
||||||
|
&STATE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
|
impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
|
use core::future::Future;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
|
||||||
use embassy_sync::signal::Signal;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
@ -12,9 +11,6 @@ use crate::time::Hertz;
|
|||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
use crate::_generated::interrupt::typelevel::Interrupt;
|
use crate::_generated::interrupt::typelevel::Interrupt;
|
||||||
|
|
||||||
// Declare a signal to awake user code for signaling the update interrupt id happen
|
|
||||||
static SIGNAL_UPDATE: Signal<CriticalSectionRawMutex, usize> = Signal::new();
|
|
||||||
|
|
||||||
pub struct InterruptHandler<T: CaptureCompare16bitInstance> {
|
pub struct InterruptHandler<T: CaptureCompare16bitInstance> {
|
||||||
_phantom: PhantomData<T>,
|
_phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
@ -24,7 +20,7 @@ impl<T: CaptureCompare16bitInstance> interrupt::typelevel::Handler<T::Interrupt>
|
|||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
let sr = regs.sr().read();
|
let sr = regs.sr().read();
|
||||||
if sr.uif() {
|
if sr.uif() {
|
||||||
SIGNAL_UPDATE.signal(0);
|
T::state().signal.signal(0);
|
||||||
// clear the flag
|
// clear the flag
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
regs.sr().modify(|w| w.set_uif(false));
|
regs.sr().modify(|w| w.set_uif(false));
|
||||||
@ -137,8 +133,8 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
|
|||||||
self.inner.enable_update_interrupt(enable);
|
self.inner.enable_update_interrupt(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn wait_update_interrupt(&self) {
|
pub fn wait_update_interrupt(&self) -> impl Future<Output = usize> {
|
||||||
_ = SIGNAL_UPDATE.wait().await;
|
T::state().signal.wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
|
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::gpio::{Level, Output, OutputType, Speed};
|
use embassy_stm32::gpio::{Level, Output, OutputType, Speed};
|
||||||
use embassy_stm32::peripherals::PA5;
|
use embassy_stm32::peripherals::{PA5, PB4};
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::timer::simple_pwm::{InterruptHandler, PwmPin, SimplePwm};
|
use embassy_stm32::timer::simple_pwm::{InterruptHandler, PwmPin, SimplePwm};
|
||||||
use embassy_stm32::timer::{self, Channel};
|
use embassy_stm32::timer::{self, Channel};
|
||||||
@ -14,8 +14,10 @@ use {defmt_rtt as _, panic_probe as _};
|
|||||||
|
|
||||||
// This test is meant for the target nucleo G070 RB
|
// This test is meant for the target nucleo G070 RB
|
||||||
// On arduino pin d4 (pb5) a pwm signal of about 0.3 hz can me measured.
|
// On arduino pin d4 (pb5) a pwm signal of about 0.3 hz can me measured.
|
||||||
// Attach a led and a resistor of 330 ohm in series to watch the pwm
|
// On arduino pin d5 (pb4) a sync pulse high for 1 ms after each interrupt.
|
||||||
|
// With a logic scope one can measure the syncing
|
||||||
// The user led arduino pin d13 (pa5) will flash with exactly 1 hrz.
|
// The user led arduino pin d13 (pa5) will flash with exactly 1 hrz.
|
||||||
|
// 390 us after the pwm going up (causing the update interrupt) the task is awoken in line 67.
|
||||||
|
|
||||||
bind_interrupts!(
|
bind_interrupts!(
|
||||||
struct Irqs {
|
struct Irqs {
|
||||||
@ -31,13 +33,18 @@ async fn pwm_task(mut pwm_test: PwmTest) {
|
|||||||
pub struct PwmTest {
|
pub struct PwmTest {
|
||||||
pwm3: SimplePwm<'static, peripherals::TIM3>,
|
pwm3: SimplePwm<'static, peripherals::TIM3>,
|
||||||
led: Output<'static, PA5>,
|
led: Output<'static, PA5>,
|
||||||
|
d5_pb4: Output<'static, PB4>,
|
||||||
max3: u16,
|
max3: u16,
|
||||||
duty: u16,
|
duty: u16,
|
||||||
counter: usize,
|
counter: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PwmTest {
|
impl PwmTest {
|
||||||
fn new(mut pwm3: SimplePwm<'static, peripherals::TIM3>, led: Output<'static, PA5>) -> Self {
|
fn new(
|
||||||
|
mut pwm3: SimplePwm<'static, peripherals::TIM3>,
|
||||||
|
led: Output<'static, PA5>,
|
||||||
|
d5_pb4: Output<'static, PB4>,
|
||||||
|
) -> Self {
|
||||||
let max3 = pwm3.get_max_duty();
|
let max3 = pwm3.get_max_duty();
|
||||||
pwm3.enable(timer::Channel::Ch2);
|
pwm3.enable(timer::Channel::Ch2);
|
||||||
pwm3.enable_update_interrupt(true);
|
pwm3.enable_update_interrupt(true);
|
||||||
@ -47,6 +54,7 @@ impl PwmTest {
|
|||||||
duty: 0,
|
duty: 0,
|
||||||
counter: 0,
|
counter: 0,
|
||||||
led,
|
led,
|
||||||
|
d5_pb4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn task(&mut self) {
|
async fn task(&mut self) {
|
||||||
@ -56,11 +64,14 @@ impl PwmTest {
|
|||||||
// note that the update interrupt will be call exact 100 times per second!
|
// note that the update interrupt will be call exact 100 times per second!
|
||||||
self.pwm3.wait_update_interrupt().await;
|
self.pwm3.wait_update_interrupt().await;
|
||||||
self.counter = (self.counter + 1) % 100;
|
self.counter = (self.counter + 1) % 100;
|
||||||
|
self.d5_pb4.set_high();
|
||||||
match self.counter {
|
match self.counter {
|
||||||
10 => self.led.set_high(),
|
10 => self.led.set_high(),
|
||||||
30 => self.led.set_low(),
|
30 => self.led.set_low(),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
Timer::after_millis(1).await;
|
||||||
|
self.d5_pb4.set_low();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +91,8 @@ async fn main(spawner: Spawner) {
|
|||||||
embassy_stm32::timer::CountingMode::EdgeAlignedUp,
|
embassy_stm32::timer::CountingMode::EdgeAlignedUp,
|
||||||
);
|
);
|
||||||
let led_g = Output::new(p.PA5, Level::High, Speed::Low);
|
let led_g = Output::new(p.PA5, Level::High, Speed::Low);
|
||||||
let pwm_test = PwmTest::new(pwm3, led_g);
|
let d5_pb4 = Output::new(p.PB4, Level::High, Speed::Low);
|
||||||
|
let pwm_test = PwmTest::new(pwm3, led_g, d5_pb4);
|
||||||
// note that at the end the pwmTest task is the owner of pwmTest.
|
// note that at the end the pwmTest task is the owner of pwmTest.
|
||||||
// PwmTest is the owner of the pwm and the led.
|
// PwmTest is the owner of the pwm and the led.
|
||||||
spawner.spawn(pwm_task(pwm_test)).unwrap();
|
spawner.spawn(pwm_task(pwm_test)).unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user