Skip to content

Commit 9114dd2

Browse files
committed
Same code as stm32-rs/stm32g4xx-hal#146 commit 'Bump pac' 558969 , wich updates the pac to 0.19.0
1 parent 70edc92 commit 9114dd2

13 files changed

+3754
-0
lines changed

src/adc_trigger.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use core::marker::PhantomData;
2+
3+
pub trait Adc13Trigger {
4+
const BITS: u32;
5+
}
6+
7+
pub trait Adc24Trigger {
8+
const BITS: u32;
9+
}
10+
11+
pub trait Adc579Trigger {
12+
const BITS: u32;
13+
}
14+
15+
pub trait Adc6810Trigger {
16+
const BITS: u32;
17+
}
18+
19+
/// Handle to timers reset/roll-over event
20+
pub struct TimerReset<T>(pub(crate) PhantomData<T>);
21+
22+
/// Handle to timers period event
23+
pub struct TimerPeriod<T>(pub(crate) PhantomData<T>);

src/capture.rs

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
use super::timer;
2+
use crate::dma::mux::DmaMuxResources;
3+
use crate::dma::traits::TargetAddress;
4+
use crate::dma::PeripheralToMemory;
5+
use crate::stm32::{HRTIM_TIMA, HRTIM_TIMB, HRTIM_TIMC, HRTIM_TIMD, HRTIM_TIME, HRTIM_TIMF};
6+
use core::marker::PhantomData;
7+
8+
pub struct Ch1;
9+
pub struct Ch2;
10+
11+
pub struct Dma;
12+
pub struct NoDma;
13+
14+
/// Type alias for the default capture for channel 1
15+
pub type HrCaptCh1<TIM, PSCL> = HrCapt<TIM, PSCL, Ch1, NoDma>;
16+
17+
/// Type alias for the default capture for channel 2
18+
pub type HrCaptCh2<TIM, PSCL> = HrCapt<TIM, PSCL, Ch2, NoDma>;
19+
20+
pub struct HrCapt<TIM, PSCL, CH, DMA> {
21+
_x: PhantomData<(TIM, PSCL, CH, DMA)>,
22+
}
23+
24+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25+
#[derive(Copy, Clone, Debug)]
26+
pub enum CountingDirection {
27+
Up = 0,
28+
Down = 1,
29+
}
30+
31+
/// Implemented for
32+
/// * TIM's update event
33+
/// * EEVT1-10
34+
///
35+
/// TODO:
36+
/// * All neighbor timers CMP1, CPM2, OUT1_RST and OUT1_SET events
37+
pub trait CaptureEvent<TIM, PSCL> {
38+
const BITS: u32;
39+
}
40+
41+
/// Trait for capture channels used for capturing edges
42+
///
43+
/// ```
44+
/// let capture: HrCapt<_, _, _> = todo!();
45+
/// if capture.is_pending() {
46+
/// let (value, dir) = capture.get_last();
47+
/// capture.clear_interrupt();
48+
/// defmt::info!("Edge captured at counter value: {}, with: {}", value, dir);
49+
/// }
50+
/// ```
51+
///
52+
/// or alternatively
53+
///
54+
/// ```
55+
/// let capture: HrCapt<_, _, _> = todo!();
56+
/// if let Some((value, dir)) = capture.get() {
57+
/// defmt::info!("Edge captured at counter value: {}, with: {}", value, dir);
58+
/// }
59+
/// ```
60+
pub trait HrCapture {
61+
/// Try to get the capture value
62+
///
63+
/// Returns none if edge has been captured since last time
64+
///
65+
/// NOTE: This function will use [`Self::is_pending`] to chech if there is a value available and
66+
/// [`Self::clear_interrupt`] to clear it.
67+
fn get(&mut self) -> Option<(u16, CountingDirection)> {
68+
if self.is_pending() {
69+
let value = self.get_last();
70+
self.clear_interrupt();
71+
Some(value)
72+
} else {
73+
None
74+
}
75+
}
76+
77+
/// Get number of ticks relative to beginning of upcounting
78+
///
79+
/// where captures during down counting count as negative (before the upcount)
80+
///
81+
/// ```txt
82+
/// Counter
83+
/// ---------------------------------- <--- period
84+
/// \ ^ /
85+
/// \ | /
86+
/// \ | /
87+
/// \ | /
88+
/// Down count \ | / Up count
89+
/// \|/
90+
/// <-------------- 0 --------------> t
91+
/// Negative result | positive result
92+
/// ```
93+
///
94+
/// NOTE: This function will use [`Self::is_pending`] to chech if there is a value available and
95+
/// [`Self::clear_interrupt`] to clear it.
96+
fn get_signed(&mut self, period: u16) -> Option<i32> {
97+
if self.is_pending() {
98+
let value = self.get_last_signed(period);
99+
self.clear_interrupt();
100+
Some(value)
101+
} else {
102+
None
103+
}
104+
}
105+
106+
fn get_last(&self) -> (u16, CountingDirection);
107+
108+
/// Get number of ticks relative to beginning of upcounting
109+
///
110+
/// where captures during down counting count as negative (before the upcount)
111+
///
112+
/// ```
113+
/// Counter
114+
/// ---------------------------------- <--- period
115+
/// \ ^ /
116+
/// \ | /
117+
/// \ | /
118+
/// \ | /
119+
/// Down count \ | / Up count
120+
/// \|/
121+
/// <-------------- 0 --------------> t
122+
/// Negative result | positive result
123+
/// ```
124+
fn get_last_signed(&self, period: u16) -> i32 {
125+
let (value, dir) = self.get_last();
126+
127+
// The capture counter always counts up and restarts at period
128+
match dir {
129+
CountingDirection::Up => i32::from(value),
130+
CountingDirection::Down => i32::from(value) - i32::from(period),
131+
}
132+
}
133+
134+
fn clear_interrupt(&mut self);
135+
136+
fn is_pending(&self) -> bool;
137+
}
138+
139+
pub fn dma_value_to_dir_and_value(x: u32) -> (u16, CountingDirection) {
140+
let value = (x & 0xFFFF) as u16;
141+
match x & (1 << 16) != 0 {
142+
true => (value, CountingDirection::Down),
143+
false => (value, CountingDirection::Up),
144+
}
145+
}
146+
147+
pub fn dma_value_to_signed(x: u32, period: u16) -> i32 {
148+
let (value, dir) = dma_value_to_dir_and_value(x);
149+
150+
// The capture counter always counts up and restarts at period
151+
match dir {
152+
CountingDirection::Up => i32::from(value),
153+
CountingDirection::Down => i32::from(value) - i32::from(period),
154+
}
155+
}
156+
157+
macro_rules! impl_capture {
158+
($($TIMX:ident),+) => {$(
159+
impl_capture!($TIMX: Ch1, cpt1r, cpt1cr, cpt1, cpt1ie, cpt1de, cpt1c);
160+
impl_capture!($TIMX: Ch2, cpt2r, cpt2cr, cpt2, cpt2ie, cpt2de, cpt2c);
161+
)+};
162+
163+
($TIMX:ident: $CH:ident, $cptXr:ident, $cptXcr:ident, $cptX:ident, $cptXie:ident, $cptXde:ident, $cptXc:ident) => {
164+
impl<PSCL> HrCapt<$TIMX, PSCL, $CH, NoDma> {
165+
/// Add event to capture
166+
///
167+
/// If multiple events are added, they will be ORed together meaning
168+
/// that a capture will be trigger if any one of the events triggers
169+
pub fn add_event<E: CaptureEvent<$TIMX, PSCL>>(&mut self, _event: &E) {
170+
let tim = unsafe { &*$TIMX::ptr() };
171+
172+
// SAFETY: We are the only one with access to cptXYcr
173+
unsafe {
174+
tim.$cptXcr().modify(|r, w| w.bits(r.bits() | E::BITS));
175+
}
176+
}
177+
178+
/// Remove event to capture
179+
pub fn remove_event<E: CaptureEvent<$TIMX, PSCL>>(&mut self, _event: &E) {
180+
let tim = unsafe { &*$TIMX::ptr() };
181+
182+
// SAFETY: We are the only one with access to cptXYcr
183+
unsafe {
184+
tim.$cptXcr().modify(|r, w| w.bits(r.bits() & !E::BITS));
185+
}
186+
}
187+
188+
/// Force capture trigger now
189+
pub fn trigger_now(&mut self) {
190+
// SAFETY: We are the only one with access to cptXYcr
191+
let tim = unsafe { &*$TIMX::ptr() };
192+
193+
tim.$cptXcr().modify(|_, w| w.swcpt().set_bit());
194+
}
195+
196+
// TODO: It would be sufficient to instead of hr_control only require exclusive access to the owning timer
197+
// however that would be hard to do since typically the capture device is a field of that same timer.
198+
// Would it make more sense to have this method direcly on HrTim instead?
199+
pub fn enable_interrupt(&mut self, enable: bool, _hr_control: &mut super::HrPwmControl) {
200+
let tim = unsafe { &*$TIMX::ptr() };
201+
202+
tim.dier().modify(|_r, w| w.$cptXie().bit(enable));
203+
}
204+
205+
pub fn enable_dma(self, _ch: timer::DmaChannel<$TIMX>) -> HrCapt<$TIMX, PSCL, $CH, Dma> {
206+
// SAFETY: We own the only insance of this timers dma channel, no one else can do this
207+
let tim = unsafe { &*$TIMX::ptr() };
208+
tim.dier().modify(|_r, w| w.$cptXde().set_bit());
209+
HrCapt {
210+
_x: PhantomData
211+
}
212+
}
213+
}
214+
215+
impl<PSCL, DMA> HrCapture for HrCapt<$TIMX, PSCL, $CH, DMA> {
216+
fn get_last(&self) -> (u16, CountingDirection) {
217+
let tim = unsafe { &*$TIMX::ptr() };
218+
let data = tim.$cptXr().read();
219+
220+
let dir = match data.dir().bit() {
221+
true => CountingDirection::Down,
222+
false => CountingDirection::Up,
223+
};
224+
let value = data.cpt().bits();
225+
226+
(value, dir)
227+
}
228+
229+
fn clear_interrupt(&mut self) {
230+
let tim = unsafe { &*$TIMX::ptr() };
231+
232+
// No need for exclusive access since this is a write only register
233+
tim.icr().write(|w| w.$cptXc().clear());
234+
}
235+
236+
fn is_pending(&self) -> bool {
237+
let tim = unsafe { &*$TIMX::ptr() };
238+
239+
// No need for exclusive access since this is a read only register
240+
tim.isr().read().$cptX().bit()
241+
}
242+
}
243+
244+
unsafe impl<PSCL> TargetAddress<PeripheralToMemory> for HrCapt<$TIMX, PSCL, $CH, Dma> {
245+
#[inline(always)]
246+
fn address(&self) -> u32 {
247+
let tim = unsafe { &*$TIMX::ptr() };
248+
&tim.$cptXr() as *const _ as u32
249+
}
250+
251+
type MemSize = u32;
252+
253+
const REQUEST_LINE: Option<u8> = Some(DmaMuxResources::$TIMX as u8);
254+
}
255+
};
256+
}
257+
258+
impl_capture! {
259+
HRTIM_TIMA,
260+
HRTIM_TIMB,
261+
HRTIM_TIMC,
262+
HRTIM_TIMD,
263+
HRTIM_TIME,
264+
HRTIM_TIMF
265+
}

0 commit comments

Comments
 (0)