Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stm32/timer: Remove generics and introduce type-safe timer taxonomy #3123

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ third_party
/Cargo.toml
out/
.zed
Session.vim
10 changes: 7 additions & 3 deletions embassy-stm32/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ rand_core = "0.6.3"
sdio-host = "0.5.0"
critical-section = "1.1"
#stm32-metapac = { version = "15" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9b7414490b10ffbd5beb1b0dcf14adb018cbe37f" }
#stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e0cfd165fd8fffaa0df66a35eeca83b228496645" }
# TODO: replace with embassy-rs/stm32-data-generated once https://github.com/embassy-rs/stm32-data/pull/495 is
# merged
stm32-metapac = { git = "https://github.com/honzasp/stm32-data-generated", features = ["metadata"] }

vcell = "0.1.3"
nb = "1.0.0"
Expand All @@ -98,8 +101,9 @@ critical-section = { version = "1.1", features = ["std"] }
proc-macro2 = "1.0.36"
quote = "1.0.15"

#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9b7414490b10ffbd5beb1b0dcf14adb018cbe37f", default-features = false, features = ["metadata"] }
#stm32-metapac = { version = "15" }
#stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e0cfd165fd8fffaa0df66a35eeca83b228496645" }
stm32-metapac = { git = "https://github.com/honzasp/stm32-data-generated", features = ["metadata"] }

[features]
default = ["rt"]
Expand Down
41 changes: 21 additions & 20 deletions embassy-stm32/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -990,21 +990,21 @@ fn main() {
(("fmc", "CLK"), quote!(crate::fmc::ClkPin)),
(("fmc", "BA0"), quote!(crate::fmc::BA0Pin)),
(("fmc", "BA1"), quote!(crate::fmc::BA1Pin)),
(("timer", "CH1"), quote!(crate::timer::Channel1Pin)),
(("timer", "CH1N"), quote!(crate::timer::Channel1ComplementaryPin)),
(("timer", "CH2"), quote!(crate::timer::Channel2Pin)),
(("timer", "CH2N"), quote!(crate::timer::Channel2ComplementaryPin)),
(("timer", "CH3"), quote!(crate::timer::Channel3Pin)),
(("timer", "CH3N"), quote!(crate::timer::Channel3ComplementaryPin)),
(("timer", "CH4"), quote!(crate::timer::Channel4Pin)),
(("timer", "CH4N"), quote!(crate::timer::Channel4ComplementaryPin)),
(("timer", "ETR"), quote!(crate::timer::ExternalTriggerPin)),
(("timer", "BKIN"), quote!(crate::timer::BreakInputPin)),
(("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)),
(("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)),
(("timer", "BKIN2"), quote!(crate::timer::BreakInput2Pin)),
(("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInput2Comparator1Pin)),
(("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInput2Comparator2Pin)),
(("timer", "CH1"), quote!(crate::timer::TimerPin<Ch1>)),
(("timer", "CH1N"), quote!(crate::timer::TimerPin<Ch1N>)),
(("timer", "CH2"), quote!(crate::timer::TimerPin<Ch2>)),
(("timer", "CH2N"), quote!(crate::timer::TimerPin<Ch2N>)),
(("timer", "CH3"), quote!(crate::timer::TimerPin<Ch3>)),
(("timer", "CH3N"), quote!(crate::timer::TimerPin<Ch3N>)),
(("timer", "CH4"), quote!(crate::timer::TimerPin<Ch4>)),
(("timer", "CH4N"), quote!(crate::timer::TimerPin<Ch4N>)),
(("timer", "ETR"), quote!(crate::timer::TimerPin<Etr>)),
(("timer", "BKIN"), quote!(crate::timer::TimerPin<Bkin>)),
(("timer", "BKIN_COMP1"), quote!(crate::timer::TimerPin<BkinComp1>)),
(("timer", "BKIN_COMP2"), quote!(crate::timer::TimerPin<BkinComp2>)),
(("timer", "BKIN2"), quote!(crate::timer::TimerPin<Bkin2>)),
(("timer", "BKIN2_COMP1"), quote!(crate::timer::TimerPin<Bkin2Comp1>)),
(("timer", "BKIN2_COMP2"), quote!(crate::timer::TimerPin<Bkin2Comp2>)),
(("hrtim", "CHA1"), quote!(crate::hrtim::ChannelAPin)),
(("hrtim", "CHA2"), quote!(crate::hrtim::ChannelAComplementaryPin)),
(("hrtim", "CHB1"), quote!(crate::hrtim::ChannelBPin)),
Expand Down Expand Up @@ -1217,14 +1217,15 @@ fn main() {
(("octospi", "OCTOSPI1"), quote!(crate::ospi::OctoDma)),
(("dac", "CH1"), quote!(crate::dac::DacDma1)),
(("dac", "CH2"), quote!(crate::dac::DacDma2)),
(("timer", "UP"), quote!(crate::timer::UpDma)),
(("hash", "IN"), quote!(crate::hash::Dma)),
(("cryp", "IN"), quote!(crate::cryp::DmaIn)),
(("cryp", "OUT"), quote!(crate::cryp::DmaOut)),
(("timer", "CH1"), quote!(crate::timer::Ch1Dma)),
(("timer", "CH2"), quote!(crate::timer::Ch2Dma)),
(("timer", "CH3"), quote!(crate::timer::Ch3Dma)),
(("timer", "CH4"), quote!(crate::timer::Ch4Dma)),
(("timer", "UP"), quote!(crate::timer::UpDma)),
(("timer", "TRIG"), quote!(crate::timer::TrigDma)),
(("timer", "CH1"), quote!(crate::timer::CcDma<Ch1>)),
(("timer", "CH2"), quote!(crate::timer::CcDma<Ch2>)),
(("timer", "CH3"), quote!(crate::timer::CcDma<Ch3>)),
(("timer", "CH4"), quote!(crate::timer::CcDma<Ch4>)),
(("cordic", "WRITE"), quote!(crate::cordic::WriteDma)), // FIXME: stm32u5a crash on Cordic driver
(("cordic", "READ"), quote!(crate::cordic::ReadDma)), // FIXME: stm32u5a crash on Cordic driver
]
Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod dmamux;
pub(crate) use dmamux::*;

mod util;
pub(crate) use util::*;
pub use util::ChannelAndRequest;

pub(crate) mod ringbuffer;
pub mod word;
Expand Down
12 changes: 9 additions & 3 deletions embassy-stm32/src/dma/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ use embassy_hal_internal::PeripheralRef;
use super::word::Word;
use super::{AnyChannel, Request, Transfer, TransferOptions};

/// Convenience wrapper, contains a channel and a request number.
/// Convenience wrapper, contains a DMA channel and a DMA request number.
///
/// Commonly used in peripheral drivers that own DMA channels.
pub(crate) struct ChannelAndRequest<'d> {
pub struct ChannelAndRequest<'d> {
/// DMA channel.
pub channel: PeripheralRef<'d, AnyChannel>,
/// DMA request.
pub request: Request,
}

impl<'d> ChannelAndRequest<'d> {
/// See [`Transfer::new_read()`].
pub unsafe fn read<'a, W: Word>(
&'a mut self,
peri_addr: *mut W,
Expand All @@ -21,6 +24,7 @@ impl<'d> ChannelAndRequest<'d> {
Transfer::new_read(&mut self.channel, self.request, peri_addr, buf, options)
}

/// See [`Transfer::new_read_raw()`].
pub unsafe fn read_raw<'a, W: Word>(
&'a mut self,
peri_addr: *mut W,
Expand All @@ -30,6 +34,7 @@ impl<'d> ChannelAndRequest<'d> {
Transfer::new_read_raw(&mut self.channel, self.request, peri_addr, buf, options)
}

/// See [`Transfer::new_write()`].
pub unsafe fn write<'a, W: Word>(
&'a mut self,
buf: &'a [W],
Expand All @@ -39,6 +44,7 @@ impl<'d> ChannelAndRequest<'d> {
Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options)
}

/// See [`Transfer::new_write_raw()`].
pub unsafe fn write_raw<'a, W: Word>(
&'a mut self,
buf: *const [W],
Expand All @@ -48,7 +54,7 @@ impl<'d> ChannelAndRequest<'d> {
Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options)
}

#[allow(dead_code)]
/// See [`Transfer::new_write_repeated()`].
pub unsafe fn write_repeated<'a, W: Word>(
&'a mut self,
repeated: &'a W,
Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ macro_rules! dma_trait {
($signal:ident, $instance:path$(, $mode:path)?) => {
#[doc = concat!(stringify!($signal), " DMA request trait")]
pub trait $signal<T: $instance $(, M: $mode)?>: crate::dma::Channel {
#[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))]
#[doc = concat!("Get the DMA request number needed to use this channel as ", stringify!($signal))]
/// Note: in some chips, ST calls this the "channel", and calls channels "streams".
/// `embassy-stm32` always uses the "channel" and "request number" names.
fn request(&self) -> crate::dma::Request;
Expand Down
1 change: 1 addition & 0 deletions embassy-stm32/src/rcc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#![macro_use]
#![allow(missing_docs)] // TODO
#![allow(static_mut_refs)] // TODO

use core::mem::MaybeUninit;

Expand Down
34 changes: 17 additions & 17 deletions embassy-stm32/src/time_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ use critical_section::CriticalSection;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embassy_time_driver::{AlarmHandle, Driver, TICK_HZ};
use stm32_metapac::timer::{regs, TimGp16};
use stm32_metapac::timer::{regs, Tim4ch};

use crate::interrupt::typelevel::Interrupt;
use crate::pac::timer::vals;
use crate::rcc::{self, SealedRccPeripheral};
#[cfg(feature = "low-power")]
use crate::rtc::Rtc;
use crate::timer::{CoreInstance, GeneralInstance1Channel};
use crate::timer::{CoreInstance, General1ChInstance};
use crate::{interrupt, peripherals};

// NOTE regarding ALARM_COUNT:
Expand Down Expand Up @@ -205,8 +205,8 @@ foreach_interrupt! {
};
}

fn regs_gp16() -> TimGp16 {
unsafe { TimGp16::from_ptr(T::regs()) }
fn regs_4ch() -> Tim4ch {
unsafe { Tim4ch::from_ptr(T::regs()) }
}

// Clock timekeeping works with something we call "periods", which are time intervals
Expand Down Expand Up @@ -274,7 +274,7 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {

impl RtcDriver {
fn init(&'static self, cs: critical_section::CriticalSection) {
let r = regs_gp16();
let r = regs_4ch();

rcc::enable_and_reset_with_cs::<T>(cs);

Expand Down Expand Up @@ -306,14 +306,14 @@ impl RtcDriver {
w.set_ccie(0, true);
});

<T as GeneralInstance1Channel>::CaptureCompareInterrupt::unpend();
unsafe { <T as GeneralInstance1Channel>::CaptureCompareInterrupt::enable() };
<T as General1ChInstance>::CaptureCompareInterrupt::unpend();
unsafe { <T as General1ChInstance>::CaptureCompareInterrupt::enable() };

r.cr1().modify(|w| w.set_cen(true));
}

fn on_interrupt(&self) {
let r = regs_gp16();
let r = regs_4ch();

// XXX: reduce the size of this critical section ?
critical_section::with(|cs| {
Expand All @@ -323,7 +323,7 @@ impl RtcDriver {
// Clear all interrupt flags. Bits in SR are "write 0 to clear", so write the bitwise NOT.
// Other approaches such as writing all zeros, or RMWing won't work, they can
// miss interrupts.
r.sr().write_value(regs::SrGp16(!sr.0));
r.sr().write_value(regs::Sr4ch(!sr.0));

// Overflow
if sr.uif() {
Expand All @@ -344,7 +344,7 @@ impl RtcDriver {
}

fn next_period(&self) {
let r = regs_gp16();
let r = regs_4ch();

// We only modify the period from the timer interrupt, so we know this can't race.
let period = self.period.load(Ordering::Relaxed) + 1;
Expand Down Expand Up @@ -408,7 +408,7 @@ impl RtcDriver {
/// Add the given offset to the current time
fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) {
let offset = offset.as_ticks();
let cnt = regs_gp16().cnt().read().cnt() as u32;
let cnt = regs_4ch().cnt().read().cnt() as u32;
let period = self.period.load(Ordering::SeqCst);

// Correct the race, if it exists
Expand All @@ -434,7 +434,7 @@ impl RtcDriver {
let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period };

self.period.store(period, Ordering::SeqCst);
regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16));
regs_4ch().cnt().write(|w| w.set_cnt(cnt as u16));

// Now, recompute all alarms
for i in 0..ALARM_COUNT {
Expand Down Expand Up @@ -491,7 +491,7 @@ impl RtcDriver {
.unwrap()
.start_wakeup_alarm(time_until_next_alarm, cs);

regs_gp16().cr1().modify(|w| w.set_cen(false));
regs_4ch().cr1().modify(|w| w.set_cen(false));

Ok(())
}
Expand All @@ -501,7 +501,7 @@ impl RtcDriver {
#[cfg(feature = "low-power")]
/// Resume the timer with the given offset
pub(crate) fn resume_time(&self) {
if regs_gp16().cr1().read().cen() {
if regs_4ch().cr1().read().cen() {
// Time isn't currently stopped

return;
Expand All @@ -510,14 +510,14 @@ impl RtcDriver {
critical_section::with(|cs| {
self.stop_wakeup_alarm(cs);

regs_gp16().cr1().modify(|w| w.set_cen(true));
regs_4ch().cr1().modify(|w| w.set_cen(true));
})
}
}

impl Driver for RtcDriver {
fn now(&self) -> u64 {
let r = regs_gp16();
let r = regs_4ch();

let period = self.period.load(Ordering::Relaxed);
compiler_fence(Ordering::Acquire);
Expand Down Expand Up @@ -548,7 +548,7 @@ impl Driver for RtcDriver {

fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
critical_section::with(|cs| {
let r = regs_gp16();
let r = regs_4ch();

let n = alarm.id() as usize;
let alarm = self.get_alarm(cs, alarm);
Expand Down
Loading