Skip to content

Commit 4f41e48

Browse files
Merge pull request #214 from nrf-rs/demacro-timer
Remove the use of macros by the Timer, and change trait usage
2 parents fbdb4d0 + 91caaa4 commit 4f41e48

File tree

1 file changed

+161
-112
lines changed

1 file changed

+161
-112
lines changed

nrf-hal-common/src/timer.rs

Lines changed: 161 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
//! See product specification, chapter 24.
44
55
#[cfg(feature = "9160")]
6-
use crate::pac::{Interrupt, TIMER0_NS as TIMER0, TIMER1_NS as TIMER1, TIMER2_NS as TIMER2};
6+
use crate::pac::{
7+
timer0_ns::RegisterBlock as RegBlock0, Interrupt, TIMER0_NS as TIMER0, TIMER1_NS as TIMER1,
8+
TIMER2_NS as TIMER2,
9+
};
710

811
#[cfg(not(feature = "9160"))]
9-
use crate::pac::{Interrupt, TIMER0, TIMER1, TIMER2};
12+
use crate::pac::{timer0::RegisterBlock as RegBlock0, Interrupt, TIMER0, TIMER1, TIMER2};
1013

1114
use cast::u32;
1215
use embedded_hal::{
@@ -20,6 +23,15 @@ use void::{unreachable, Void};
2023
#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))]
2124
use crate::pac::{TIMER3, TIMER4};
2225

26+
// The 832 and 840 expose TIMER3 and TIMER for as timer3::RegisterBlock...
27+
#[cfg(any(feature = "52832", feature = "52840"))]
28+
use crate::pac::timer3::RegisterBlock as RegBlock3;
29+
30+
// ...but the 833 exposes them as timer0::RegisterBlock. This might be a bug
31+
// in the PAC, and could be fixed later. For now, it is equivalent anyway.
32+
#[cfg(feature = "52833")]
33+
use crate::pac::timer0::RegisterBlock as RegBlock3;
34+
2335
use core::marker::PhantomData;
2436

2537
pub struct OneShot;
@@ -231,135 +243,172 @@ where
231243
}
232244
}
233245

234-
/// Implemented by all `timer0::TIMER` instances.
235-
pub trait Instance {
246+
/// Implemented by all TIMER* instances.
247+
pub trait Instance: sealed::Sealed {
236248
/// This interrupt associated with this RTC instance.
237249
const INTERRUPT: Interrupt;
238250

251+
fn as_timer0(&self) -> &RegBlock0;
252+
239253
fn timer_start<Time>(&self, cycles: Time)
240254
where
241-
Time: Into<u32>;
255+
Time: Into<u32>,
256+
{
257+
// If the following sequence of events occurs, the COMPARE event will be
258+
// set here:
259+
// 1. `start` is called.
260+
// 2. The timer runs out but `wait` is _not_ called.
261+
// 3. `start` is called again
262+
//
263+
// If that happens, then we need to reset the event here explicitly, as
264+
// nothing else this method does will reset the event, and if it's still
265+
// active after this method exits, then the next call to `wait` will
266+
// return immediately, no matter how much time has actually passed.
267+
self.as_timer0().events_compare[0].reset();
268+
269+
// Configure timer to trigger EVENTS_COMPARE when given number of cycles
270+
// is reached.
271+
#[cfg(not(feature = "51"))]
272+
self.as_timer0().cc[0].write(|w|
273+
// The timer mode was set to 32 bits above, so all possible values
274+
// of `cycles` are valid.
275+
unsafe { w.cc().bits(cycles.into()) });
276+
277+
#[cfg(feature = "51")]
278+
self.as_timer0().cc[0].write(|w| unsafe { w.bits(cycles.into()) });
279+
280+
// Clear the counter value.
281+
self.as_timer0().tasks_clear.write(|w| unsafe { w.bits(1) });
282+
283+
// Start the timer.
284+
self.as_timer0().tasks_start.write(|w| unsafe { w.bits(1) });
285+
}
242286

243-
fn timer_reset_event(&self);
287+
fn timer_reset_event(&self) {
288+
self.as_timer0().events_compare[0].write(|w| w);
289+
}
244290

245-
fn timer_cancel(&self);
291+
fn timer_cancel(&self) {
292+
self.as_timer0().tasks_stop.write(|w| unsafe { w.bits(1) });
293+
self.timer_reset_event();
294+
}
246295

247-
fn timer_running(&self) -> bool;
296+
fn timer_running(&self) -> bool {
297+
self.as_timer0().events_compare[0].read().bits() == 0
298+
}
299+
300+
fn read_counter(&self) -> u32 {
301+
self.as_timer0().tasks_capture[1].write(|w| unsafe { w.bits(1) });
302+
self.as_timer0().cc[1].read().bits()
303+
}
304+
305+
fn disable_interrupt(&self) {
306+
self.as_timer0()
307+
.intenclr
308+
.modify(|_, w| w.compare0().clear());
309+
}
310+
311+
fn enable_interrupt(&self) {
312+
self.as_timer0().intenset.modify(|_, w| w.compare0().set());
313+
}
314+
315+
fn set_shorts_periodic(&self) {
316+
self.as_timer0()
317+
.shorts
318+
.write(|w| w.compare0_clear().enabled().compare0_stop().disabled());
319+
}
248320

249-
fn read_counter(&self) -> u32;
321+
fn set_shorts_oneshot(&self) {
322+
self.as_timer0()
323+
.shorts
324+
.write(|w| w.compare0_clear().enabled().compare0_stop().enabled());
325+
}
250326

251-
fn disable_interrupt(&self);
327+
fn set_periodic(&self) {
328+
self.set_shorts_periodic();
329+
self.as_timer0().prescaler.write(
330+
|w| unsafe { w.prescaler().bits(4) }, // 1 MHz
331+
);
332+
self.as_timer0().bitmode.write(|w| w.bitmode()._32bit());
333+
}
252334

253-
fn enable_interrupt(&self);
335+
fn set_oneshot(&self) {
336+
self.set_shorts_oneshot();
337+
self.as_timer0().prescaler.write(
338+
|w| unsafe { w.prescaler().bits(4) }, // 1 MHz
339+
);
340+
self.as_timer0().bitmode.write(|w| w.bitmode()._32bit());
341+
}
342+
}
254343

255-
fn set_shorts_periodic(&self);
344+
impl Instance for TIMER0 {
345+
const INTERRUPT: Interrupt = Interrupt::TIMER0;
256346

257-
fn set_shorts_oneshot(&self);
347+
#[inline(always)]
348+
fn as_timer0(&self) -> &RegBlock0 {
349+
self
350+
}
351+
}
258352

259-
fn set_periodic(&self);
353+
impl Instance for TIMER1 {
354+
const INTERRUPT: Interrupt = Interrupt::TIMER1;
260355

261-
fn set_oneshot(&self);
356+
#[inline(always)]
357+
fn as_timer0(&self) -> &RegBlock0 {
358+
self
359+
}
262360
}
263361

264-
macro_rules! impl_instance {
265-
($($name:ident,)*) => {
266-
$(
267-
impl Instance for $name {
268-
const INTERRUPT: Interrupt = Interrupt::$name;
269-
270-
fn timer_start<Time>(&self, cycles: Time)
271-
where
272-
Time: Into<u32>,
273-
{
274-
// If the following sequence of events occurs, the COMPARE event will be
275-
// set here:
276-
// 1. `start` is called.
277-
// 2. The timer runs out but `wait` is _not_ called.
278-
// 3. `start` is called again
279-
//
280-
// If that happens, then we need to reset the event here explicitly, as
281-
// nothing else this method does will reset the event, and if it's still
282-
// active after this method exits, then the next call to `wait` will
283-
// return immediately, no matter how much time has actually passed.
284-
self.events_compare[0].reset();
285-
286-
// Configure timer to trigger EVENTS_COMPARE when given number of cycles
287-
// is reached.
288-
#[cfg(not(feature = "51"))]
289-
self.cc[0].write(|w|
290-
// The timer mode was set to 32 bits above, so all possible values
291-
// of `cycles` are valid.
292-
unsafe { w.cc().bits(cycles.into()) });
293-
294-
#[cfg(feature = "51")]
295-
self.cc[0].write(|w| unsafe { w.bits(cycles.into())} );
296-
297-
// Clear the counter value.
298-
self.tasks_clear.write(|w| unsafe { w.bits(1) });
299-
300-
// Start the timer.
301-
self.tasks_start.write(|w| unsafe { w.bits(1) });
302-
}
303-
304-
fn timer_reset_event(&self) {
305-
self.events_compare[0].write(|w| w);
306-
}
307-
308-
fn timer_cancel(&self) {
309-
self.tasks_stop.write(|w| unsafe { w.bits(1) });
310-
self.timer_reset_event();
311-
}
312-
313-
fn timer_running(&self) -> bool {
314-
self.events_compare[0].read().bits() == 0
315-
}
316-
317-
fn read_counter(&self) -> u32 {
318-
self.tasks_capture[1].write(|w| unsafe { w.bits(1) });
319-
self.cc[1].read().bits()
320-
}
321-
322-
fn disable_interrupt(&self) {
323-
self.intenclr.modify(|_, w| w.compare0().clear());
324-
}
325-
326-
fn enable_interrupt(&self) {
327-
self.intenset.modify(|_, w| w.compare0().set());
328-
}
329-
330-
fn set_shorts_periodic(&self) {
331-
self
332-
.shorts
333-
.write(|w| w.compare0_clear().enabled().compare0_stop().disabled());
334-
}
335-
336-
fn set_shorts_oneshot(&self) {
337-
self
338-
.shorts
339-
.write(|w| w.compare0_clear().enabled().compare0_stop().enabled());
340-
}
341-
342-
fn set_periodic(&self) {
343-
self.set_shorts_periodic();
344-
self.prescaler.write(
345-
|w| unsafe { w.prescaler().bits(4) }, // 1 MHz
346-
);
347-
self.bitmode.write(|w| w.bitmode()._32bit());
348-
}
349-
350-
fn set_oneshot(&self) {
351-
self.set_shorts_oneshot();
352-
self.prescaler.write(
353-
|w| unsafe { w.prescaler().bits(4) }, // 1 MHz
354-
);
355-
self.bitmode.write(|w| w.bitmode()._32bit());
356-
}
357-
}
358-
)*
362+
impl Instance for TIMER2 {
363+
const INTERRUPT: Interrupt = Interrupt::TIMER2;
364+
365+
#[inline(always)]
366+
fn as_timer0(&self) -> &RegBlock0 {
367+
self
359368
}
360369
}
361370

362-
impl_instance!(TIMER0, TIMER1, TIMER2,);
371+
#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))]
372+
impl Instance for TIMER3 {
373+
const INTERRUPT: Interrupt = Interrupt::TIMER3;
374+
375+
#[inline(always)]
376+
fn as_timer0(&self) -> &RegBlock0 {
377+
let rb: &RegBlock3 = self;
378+
let rb_ptr: *const RegBlock3 = rb;
379+
380+
// SAFETY: TIMER0 and TIMER3 register layouts are identical, except
381+
// that TIMER3 has 6 CC registers, while TIMER0 has 4. There is
382+
// appropriate padding to allow other operations to work correctly
383+
unsafe { &*rb_ptr.cast() }
384+
}
385+
}
363386

364387
#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))]
365-
impl_instance!(TIMER3, TIMER4,);
388+
impl Instance for TIMER4 {
389+
const INTERRUPT: Interrupt = Interrupt::TIMER4;
390+
391+
#[inline(always)]
392+
fn as_timer0(&self) -> &RegBlock0 {
393+
let rb: &RegBlock3 = self;
394+
let rb_ptr: *const RegBlock3 = rb;
395+
396+
// SAFETY: TIMER0 and TIMER3 register layouts are identical, except
397+
// that TIMER3 has 6 CC registers, while TIMER0 has 4. There is
398+
// appropriate padding to allow other operations to work correctly
399+
unsafe { &*rb_ptr.cast() }
400+
}
401+
}
402+
403+
mod sealed {
404+
pub trait Sealed {}
405+
impl Sealed for super::TIMER0 {}
406+
impl Sealed for super::TIMER1 {}
407+
impl Sealed for super::TIMER2 {}
408+
409+
#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))]
410+
impl Sealed for super::TIMER3 {}
411+
412+
#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))]
413+
impl Sealed for super::TIMER4 {}
414+
}

0 commit comments

Comments
 (0)