Skip to content

pac extension traits and unmacro #3

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

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
15 changes: 15 additions & 0 deletions .zed/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"lsp": {
"rust-analyzer": {
"initialization_options": {
"cargo": {
"features": ["stm32g474"]
},
"check": {
"allTargets": false,
"targets": "thumbv7em-none-eabihf"
}
}
}
}
}
12 changes: 7 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ stm32-hrtim = { path = "." }

[dependencies]
stm32f3 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", optional = true }
stm32h7 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", features = ["critical-section"], optional = true }
stm32h7 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies", features = [
"critical-section",
], optional = true }
stm32g4 = { version = "0.22.0", package = "stm32g4-staging", optional = true }

defmt = { version = "0.3.10", optional = true }
Expand All @@ -22,7 +24,7 @@ cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
defmt-rtt = "0.4.0"
cortex-m-rt = "0.7.2"
panic-probe = { version = "0.3.0", features = ["print-defmt"] }
stm32g4xx-hal = { git = "https://github.com/usbalbin/stm32g4xx-hal", branch = "hrtim", features = ["defmt", "hrtim"] }
#stm32g4xx-hal = { git = "https://github.com/usbalbin/stm32g4xx-hal", branch = "hrtim", features = ["defmt", "hrtim"] }

[features]
default = []
Expand All @@ -46,8 +48,8 @@ stm32h753 = ["stm32h7/stm32h753", "hrtim_v1_1"]
#stm32h755 = ["stm32h7/stm32h755", "hrtim_v1_1"]
#stm32h757 = ["stm32h7/stm32h757", "hrtim_v1_1"]

stm32g474 = ["stm32g4/stm32g474", "stm32g4xx-hal/stm32g474", "hrtim_v2"]
stm32g484 = ["stm32g4/stm32g484", "stm32g4xx-hal/stm32g484", "hrtim_v2"]
stm32g474 = ["stm32g4/stm32g474", "hrtim_v2"]
stm32g484 = ["stm32g4/stm32g484", "hrtim_v2"]
defmt = ["dep:defmt", "fugit/defmt"]

# G4
Expand Down Expand Up @@ -95,4 +97,4 @@ path = "examples/stm32g4/hrtim.rs"
[[example]]
name = "stm32g4-master"
required-features = ["stm32g4"]
path = "examples/stm32g4/master.rs"
path = "examples/stm32g4/master.rs"
2 changes: 1 addition & 1 deletion examples/stm32g4/adc-trigger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use stm32g4xx_hal::{
dma::{self, channel::DMAExt, config::DmaConfig, TransferExt},
gpio::GpioExt,
hrtim::{HrControltExt, HrPwmBuilderExt},
pac::{CorePeripherals, Peripherals},
pwr::PwrExt,
rcc::{self, RccExt},
stm32::{CorePeripherals, Peripherals},
};

#[entry]
Expand Down
2 changes: 1 addition & 1 deletion examples/stm32g4/capture-dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use stm32g4xx_hal::{
dma::{channel::DMAExt, config::DmaConfig, TransferExt},
gpio::GpioExt,
hrtim::{external_event::EevInputExt, HrControltExt, HrPwmBuilderExt},
pac::Peripherals,
pwr::PwrExt,
rcc::{self, RccExt},
stm32::Peripherals,
};

#[entry]
Expand Down
2 changes: 1 addition & 1 deletion examples/stm32g4/capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ use stm32_hrtim::{
use stm32g4xx_hal::{
gpio::GpioExt,
hrtim::{external_event::EevInputExt, HrControltExt, HrPwmBuilderExt},
pac::Peripherals,
pwr::PwrExt,
rcc::{self, RccExt},
stm32::Peripherals,
};

#[entry]
Expand Down
2 changes: 1 addition & 1 deletion examples/stm32g4/eev-comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ use stm32g4xx_hal::{
delay::SYSTDelayExt,
gpio::{GpioExt, SignalEdge},
hrtim::{external_event::EevInputExt, HrControltExt, HrPwmBuilderExt},
pac::{CorePeripherals, Peripherals},
pwr::PwrExt,
rcc::{self, RccExt},
stm32::{CorePeripherals, Peripherals},
};

#[entry]
Expand Down
2 changes: 1 addition & 1 deletion examples/stm32g4/eev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use stm32_hrtim::{
use stm32g4xx_hal::{
gpio::GpioExt,
hrtim::{external_event::EevInputExt, HrControltExt, HrPwmBuilderExt},
pac::Peripherals,
pwr::PwrExt,
rcc::{self, RccExt},
stm32::Peripherals,
};

#[entry]
Expand Down
2 changes: 1 addition & 1 deletion examples/stm32g4/flt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use stm32g4xx_hal::{
delay::{DelayExt, SYSTDelayExt},
gpio::GpioExt,
hrtim::{fault::FaultInput, HrControltExt, HrPwmBuilderExt},
pac::{CorePeripherals, Peripherals},
pwr::PwrExt,
rcc::{self, RccExt},
stm32::{CorePeripherals, Peripherals},
time::ExtU32,
};

Expand Down
8 changes: 7 additions & 1 deletion examples/stm32g4/hrtim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ use stm32_hrtim::{
Pscl4,
};
use stm32g4xx_hal::{
delay::{DelayExt, SYSTDelayExt}, gpio::GpioExt, hrtim::{HrControltExt, HrPwmBuilderExt}, pwr::PwrExt, rcc::{self, RccExt}, stm32::{CorePeripherals, Peripherals}, time::ExtU32
delay::{DelayExt, SYSTDelayExt},
gpio::GpioExt,
hrtim::{HrControltExt, HrPwmBuilderExt},
pac::{CorePeripherals, Peripherals},
pwr::PwrExt,
rcc::{self, RccExt},
time::ExtU32,
};

#[entry]
Expand Down
8 changes: 7 additions & 1 deletion examples/stm32g4/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ use stm32_hrtim::{
HrParts, HrPwmAdvExt, HrTimerMode, MasterPreloadSource, PreloadSource, Pscl4,
};
use stm32g4xx_hal::{
delay::{DelayExt, SYSTDelayExt}, gpio::GpioExt, hrtim::{HrControltExt, HrPwmBuilderExt}, pwr::PwrExt, rcc::{self, RccExt}, stm32::{CorePeripherals, Peripherals}, time::ExtU32
delay::{DelayExt, SYSTDelayExt},
gpio::GpioExt,
hrtim::{HrControltExt, HrPwmBuilderExt},
pac::{CorePeripherals, Peripherals},
pwr::PwrExt,
rcc::{self, RccExt},
time::ExtU32,
};

#[entry]
Expand Down
172 changes: 71 additions & 101 deletions src/capture.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
use super::timer;

#[cfg(feature = "hrtim_v2")]
use crate::pac::HRTIM_TIMF;
use crate::pac::{HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME};
use super::timer::{self, Ch1, Ch2, ChExt, InstanceX};
use crate::ext::{CptcrW, MasterExt, TimExt};
use core::marker::PhantomData;

pub struct Ch1;
pub struct Ch2;

pub struct Dma;
pub struct NoDma;

Expand Down Expand Up @@ -161,108 +155,84 @@ pub fn dma_value_to_signed(x: u32, #[allow(unused_variables)] period: u16) -> i3
}
}

macro_rules! impl_capture {
($($TIMX:ident),+) => {$(
impl_capture!($TIMX: Ch1, cpt1r, cpt1cr, cpt1, cpt1ie, cpt1de, cpt1c);
impl_capture!($TIMX: Ch2, cpt2r, cpt2cr, cpt2, cpt2ie, cpt2de, cpt2c);
)+};

($TIMX:ident: $CH:ident, $cptXr:ident, $cptXcr:ident, $cptX:ident, $cptXie:ident, $cptXde:ident, $cptXc:ident) => {
impl<PSCL> HrCapt<$TIMX, PSCL, $CH, NoDma> {
/// Add event to capture
///
/// If multiple events are added, they will be ORed together meaning
/// that a capture will be trigger if any one of the events triggers
pub fn add_event<E: CaptureEvent<$TIMX, PSCL>>(&mut self, _event: &E) {
let tim = unsafe { &*$TIMX::ptr() };

// SAFETY: We are the only one with access to cptXYcr
unsafe {
tim.$cptXcr().modify(|r, w| w.bits(r.bits() | E::BITS));
}
}

/// Remove event to capture
pub fn remove_event<E: CaptureEvent<$TIMX, PSCL>>(&mut self, _event: &E) {
let tim = unsafe { &*$TIMX::ptr() };

// SAFETY: We are the only one with access to cptXYcr
unsafe {
tim.$cptXcr().modify(|r, w| w.bits(r.bits() & !E::BITS));
}
}

/// Force capture trigger now
pub fn trigger_now(&mut self) {
// SAFETY: We are the only one with access to cptXYcr
let tim = unsafe { &*$TIMX::ptr() };

tim.$cptXcr().modify(|_, w| w.swcpt().set_bit());
}

// TODO: It would be sufficient to instead of hr_control only require exclusive access to the owning timer
// however that would be hard to do since typically the capture device is a field of that same timer.
// Would it make more sense to have this method direcly on HrTim instead?
pub fn enable_interrupt(&mut self, enable: bool, _hr_control: &mut super::HrPwmControl) {
let tim = unsafe { &*$TIMX::ptr() };

tim.dier().modify(|_r, w| w.$cptXie().bit(enable));
}

pub fn enable_dma(self, _ch: timer::DmaChannel<$TIMX>) -> HrCapt<$TIMX, PSCL, $CH, Dma> {
// SAFETY: We own the only insance of this timers dma channel, no one else can do this
let tim = unsafe { &*$TIMX::ptr() };
tim.dier().modify(|_r, w| w.$cptXde().set_bit());
HrCapt {
_x: PhantomData
}
}
impl<TIM: InstanceX, CH: ChExt, PSCL> HrCapt<TIM, PSCL, CH, NoDma> {
/// Add event to capture
///
/// If multiple events are added, they will be ORed together meaning
/// that a capture will be trigger if any one of the events triggers
pub fn add_event<E: CaptureEvent<TIM, PSCL>>(&mut self, _event: &E) {
let tim = unsafe { &*TIM::ptr() };

// SAFETY: We are the only one with access to cptXYcr
unsafe {
tim.cptcr(CH::CH).modify(|r, w| w.bits(r.bits() | E::BITS));
}
}

impl<PSCL, DMA> HrCapture for HrCapt<$TIMX, PSCL, $CH, DMA> {
fn get_last(&self) -> (u16, CountingDirection) {
let tim = unsafe { &*$TIMX::ptr() };
let data = tim.$cptXr().read();

#[cfg(feature = "hrtim_v2")]
let dir = match data.dir().bit() {
true => CountingDirection::Down,
false => CountingDirection::Up,
};
#[cfg(any(feature = "hrtim_v1", feature = "hrtim_v1_1"))]
let dir = CountingDirection::Up;
/// Remove event to capture
pub fn remove_event<E: CaptureEvent<TIM, PSCL>>(&mut self, _event: &E) {
let tim = unsafe { &*TIM::ptr() };

let value = data.cpt().bits();
// SAFETY: We are the only one with access to cptXYcr
unsafe {
tim.cptcr(CH::CH).modify(|r, w| w.bits(r.bits() & !E::BITS));
}
}

(value, dir)
}
/// Force capture trigger now
pub fn trigger_now(&mut self) {
// SAFETY: We are the only one with access to cptXYcr
let tim = unsafe { &*TIM::ptr() };

fn clear_interrupt(&mut self) {
let tim = unsafe { &*$TIMX::ptr() };
tim.cptcr(CH::CH).modify(|_, w| w.set_swcpt());
}

// No need for exclusive access since this is a write only register
tim.icr().write(|w| w.$cptXc().clear());
}
// TODO: It would be sufficient to instead of hr_control only require exclusive access to the owning timer
// however that would be hard to do since typically the capture device is a field of that same timer.
// Would it make more sense to have this method direcly on HrTim instead?
pub fn enable_interrupt(&mut self, enable: bool, _hr_control: &mut super::HrPwmControl) {
let tim = unsafe { &*TIM::ptr() };

fn is_pending(&self) -> bool {
let tim = unsafe { &*$TIMX::ptr() };
tim.dier().modify(|_r, w| w.cptie(CH::CH as _).bit(enable));
}

// No need for exclusive access since this is a read only register
tim.isr().read().$cptX().bit()
}
}
};
pub fn enable_dma(self, _ch: timer::DmaChannel<TIM>) -> HrCapt<TIM, PSCL, CH, Dma> {
// SAFETY: We own the only insance of this timers dma channel, no one else can do this
let tim = unsafe { &*TIM::ptr() };
tim.dier().modify(|_r, w| w.cptde(CH::CH as _).set_bit());
HrCapt { _x: PhantomData }
}
}

impl_capture! {
HRTIM_TIMA,
HRTIM_TIMB,
HRTIM_TIMC,
HRTIM_TIMD,
HRTIM_TIME
}
impl<TIM: InstanceX, CH: ChExt, PSCL, DMA> HrCapture for HrCapt<TIM, PSCL, CH, DMA> {
fn get_last(&self) -> (u16, CountingDirection) {
let tim = unsafe { &*TIM::ptr() };
let data = tim.cptr(CH::CH).read();

#[cfg(feature = "hrtim_v2")]
let dir = match data.dir().bit() {
true => CountingDirection::Down,
false => CountingDirection::Up,
};
#[cfg(any(feature = "hrtim_v1", feature = "hrtim_v1_1"))]
let dir = CountingDirection::Up;

let value = data.cpt().bits();

(value, dir)
}

#[cfg(feature = "hrtim_v2")]
impl_capture! {
HRTIM_TIMF
fn clear_interrupt(&mut self) {
let tim = unsafe { &*TIM::ptr() };

// No need for exclusive access since this is a write only register
tim.icr().write(|w| w.cptc(CH::CH as _).clear());
}

fn is_pending(&self) -> bool {
let tim = unsafe { &*TIM::ptr() };

// No need for exclusive access since this is a read only register
tim.isr().read().cpt(CH::CH as _).bit()
}
}
Loading
Loading