Skip to content

Commit

Permalink
stm32/timer: Remove generics and introduce type-safe timer taxonomy
Browse files Browse the repository at this point in the history
  • Loading branch information
honzasp committed Aug 4, 2024
1 parent 03b8e36 commit 16c82c4
Show file tree
Hide file tree
Showing 15 changed files with 2,554 additions and 984 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Cargo.lock
third_party
/Cargo.toml
out/
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-e0cfd165fd8fffaa0df66a35eeca83b228496645" }
#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 @@ -96,8 +99,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-e0cfd165fd8fffaa0df66a35eeca83b228496645", 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 @@ -987,21 +987,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 @@ -1211,14 +1211,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
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

0 comments on commit 16c82c4

Please sign in to comment.