Skip to content

Commit 18dc489

Browse files
authored
Merge pull request #264 from Sh3Rm4n/timer-interrupt
Timer interrupt
2 parents bac4ab0 + be70b89 commit 18dc489

File tree

2 files changed

+90
-15
lines changed

2 files changed

+90
-15
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
9797
Change `make_interrupt_source()` to `SysCfg::select_exti_interrupt_source()`.
9898
- Change dma interrupt API to be more in line with the new serial interrupt
9999
API. ([#263])
100+
- Change timer interrupt API to the same of the serial interface. ([#264])
101+
- Make timer Events `#[non_exhaustive]`. ([#264])
102+
- Renames timers `release()` function to `free()` to be more in line with the
103+
rest of this crate. ([#264])
100104

101105
## [v0.7.0] - 2021-06-18
102106

@@ -422,6 +426,7 @@ let clocks = rcc
422426
[defmt]: https://github.com/knurling-rs/defmt
423427
[filter]: https://defmt.ferrous-systems.com/filtering.html
424428

429+
[#264]: https://github.com/stm32-rs/stm32f3xx-hal/pull/264
425430
[#263]: https://github.com/stm32-rs/stm32f3xx-hal/pull/263
426431
[#262]: https://github.com/stm32-rs/stm32f3xx-hal/pull/262
427432
[#260]: https://github.com/stm32-rs/stm32f3xx-hal/pull/260

src/timer.rs

Lines changed: 85 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use core::convert::{From, TryFrom};
1010

1111
use cortex_m::peripheral::DWT;
12+
#[cfg(feature = "enumset")]
13+
use enumset::{EnumSet, EnumSetType};
1214
use void::Void;
1315

1416
use crate::hal::timer::{CountDown, Periodic};
@@ -120,6 +122,11 @@ pub struct Timer<TIM> {
120122
}
121123

122124
/// Interrupt events
125+
#[derive(Debug)]
126+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
127+
#[cfg_attr(feature = "enumset", derive(EnumSetType))]
128+
#[cfg_attr(not(feature = "enumset"), derive(Copy, Clone, PartialEq, Eq))]
129+
#[non_exhaustive]
123130
pub enum Event {
124131
/// Timer timed out / count down ended
125132
Update,
@@ -169,7 +176,7 @@ macro_rules! hal {
169176
// The above line raises an update event which will indicate
170177
// that the timer is already finished. Since this is not the case,
171178
// it should be cleared
172-
self.clear_update_interrupt_flag();
179+
self.clear_event(Event::Update);
173180

174181
// start counter
175182
self.tim.cr1.modify(|_, w| w.cen().enabled());
@@ -179,7 +186,7 @@ macro_rules! hal {
179186
if self.tim.sr.read().uif().is_clear() {
180187
Err(nb::Error::WouldBlock)
181188
} else {
182-
self.clear_update_interrupt_flag();
189+
self.clear_event(Event::Update);
183190
Ok(())
184191
}
185192
}
@@ -202,32 +209,95 @@ macro_rules! hal {
202209
timer
203210
}
204211

205-
/// Starts listening for an `event`
206-
pub fn listen(&mut self, event: Event) {
212+
/// Stops the timer
213+
#[inline]
214+
pub fn stop(&mut self) {
215+
self.tim.cr1.modify(|_, w| w.cen().disabled());
216+
}
217+
218+
/// Enable or disable the interrupt for the specified [`Event`].
219+
#[inline]
220+
pub fn enable_interrupt(&mut self, event: Event) {
221+
self.configure_interrupt(event, true);
222+
}
223+
224+
/// Enable or disable the interrupt for the specified [`Event`].
225+
#[inline]
226+
pub fn disable_interrupt(&mut self, event: Event) {
227+
self.configure_interrupt(event, false);
228+
}
229+
230+
231+
// TODO(Sh3Rm4n): After macro -> Instance refactor introduce associated const INTERRUPT.
232+
// /// Get the correspoing Interrupt number
233+
// // pub fn nvic() -> Interrupt { }
234+
235+
/// Enable or disable the interrupt for the specified [`Event`].
236+
#[inline]
237+
pub fn configure_interrupt(&mut self, event: Event, enable: bool) {
207238
match event {
208-
Event::Update => self.tim.dier.write(|w| w.uie().enabled()),
239+
Event::Update => self.tim.dier.write(|w| w.uie().bit(enable)),
240+
}
241+
}
242+
243+
/// Enable or disable interrupt for the specified [`Event`]s.
244+
///
245+
/// Like [`Timer::configure_interrupt`], but instead using an enumset. The corresponding
246+
/// interrupt for every [`Event`] in the set will be enabled, every other interrupt will be
247+
/// **disabled**.
248+
#[cfg(feature = "enumset")]
249+
#[cfg_attr(docsrs, doc(cfg(feature = "enumset")))]
250+
pub fn configure_interrupts(&mut self, events: EnumSet<Event>) -> &mut Self {
251+
for event in events.complement().iter() {
252+
self.configure_interrupt(event, false);
253+
}
254+
for event in events.iter() {
255+
self.configure_interrupt(event, true);
209256
}
257+
258+
self
210259
}
211260

212-
/// Stops listening for an `event`
213-
pub fn unlisten(&mut self, event: Event) {
261+
/// Check if an interrupt event happend.
262+
pub fn is_event_triggered(&self, event: Event) -> bool {
214263
match event {
215-
Event::Update => self.tim.dier.write(|w| w.uie().disabled()),
264+
Event::Update => self.tim.sr.read().uif().bit(),
216265
}
217266
}
218267

219-
/// Stops the timer
220-
pub fn stop(&mut self) {
221-
self.tim.cr1.modify(|_, w| w.cen().disabled());
268+
/// Get an [`EnumSet`] of all fired interrupt events.
269+
#[cfg(feature = "enumset")]
270+
#[cfg_attr(docsrs, doc(cfg(feature = "enumset")))]
271+
pub fn triggered_events(&self) -> EnumSet<Event> {
272+
let mut events = EnumSet::new();
273+
274+
for event in EnumSet::<Event>::all().iter() {
275+
if self.is_event_triggered(event) {
276+
events |= event;
277+
}
278+
}
279+
280+
events
281+
}
282+
283+
/// Clear the given interrupt event flag.
284+
#[inline]
285+
pub fn clear_event(&mut self, event: Event) {
286+
match event {
287+
Event::Update => self.tim.sr.modify(|_, w| w.uif().clear()),
288+
}
222289
}
223290

224-
/// Clears Update Interrupt Flag
225-
pub fn clear_update_interrupt_flag(&mut self) {
226-
self.tim.sr.modify(|_, w| w.uif().clear());
291+
/// Clear **all** interrupt events.
292+
#[inline]
293+
pub fn clear_events(&mut self) {
294+
// SAFETY: This atomic write clears all flags and ignores the reserverd bit fields.
295+
self.tim.sr.write(|w| unsafe { w.bits(0) });
227296
}
228297

229298
/// Releases the TIM peripheral
230-
pub fn release(mut self) -> $TIMX {
299+
#[inline]
300+
pub fn free(mut self) -> $TIMX {
231301
self.stop();
232302
self.tim
233303
}

0 commit comments

Comments
 (0)