Skip to content

Commit 1774286

Browse files
authored
Use enums in timers to avoid some unreachable panics (#4299)
* Use an enum to avoid timer bounds checks * Outline debug assert
1 parent 7cd7186 commit 1774286

File tree

3 files changed

+55
-27
lines changed

3 files changed

+55
-27
lines changed

esp-hal/src/timer/systimer.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ impl<'d> SystemTimer<'d> {
104104
etm::enable_etm();
105105

106106
Self {
107-
alarm0: Alarm::new(0),
108-
alarm1: Alarm::new(1),
109-
alarm2: Alarm::new(2),
107+
alarm0: Alarm::new(Comparator::Comparator0),
108+
alarm1: Alarm::new(Comparator::Comparator1),
109+
alarm2: Alarm::new(Comparator::Comparator2),
110110
}
111111
}
112112

@@ -263,17 +263,25 @@ impl Unit {
263263
}
264264
}
265265

266+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
267+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
268+
enum Comparator {
269+
Comparator0,
270+
Comparator1,
271+
Comparator2,
272+
}
273+
266274
/// An alarm unit
267275
#[derive(Debug)]
268276
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
269277
pub struct Alarm<'d> {
270-
comp: u8,
278+
comp: Comparator,
271279
unit: Unit,
272280
_lifetime: PhantomData<&'d mut ()>,
273281
}
274282

275283
impl Alarm<'_> {
276-
const fn new(comp: u8) -> Self {
284+
const fn new(comp: Comparator) -> Self {
277285
Alarm {
278286
comp,
279287
unit: Unit::Unit0,
@@ -310,7 +318,7 @@ impl Alarm<'_> {
310318
/// Returns the comparator's number.
311319
#[inline]
312320
fn channel(&self) -> u8 {
313-
self.comp
321+
self.comp as u8
314322
}
315323

316324
/// Enables/disables the comparator. If enabled, this means
@@ -639,30 +647,30 @@ mod asynch {
639647
}
640648

641649
#[inline]
642-
fn handle_alarm(alarm: u8) {
650+
fn handle_alarm(comp: Comparator) {
643651
Alarm {
644-
comp: alarm,
652+
comp,
645653
unit: Unit::Unit0,
646654
_lifetime: PhantomData,
647655
}
648656
.enable_interrupt(false);
649657

650-
WAKERS[alarm as usize].wake();
658+
WAKERS[comp as usize].wake();
651659
}
652660

653661
#[handler]
654662
pub(crate) fn target0_handler() {
655-
handle_alarm(0);
663+
handle_alarm(Comparator::Comparator0);
656664
}
657665

658666
#[handler]
659667
pub(crate) fn target1_handler() {
660-
handle_alarm(1);
668+
handle_alarm(Comparator::Comparator1);
661669
}
662670

663671
#[handler]
664672
pub(crate) fn target2_handler() {
665-
handle_alarm(2);
673+
handle_alarm(Comparator::Comparator2);
666674
}
667675
}
668676

esp-hal/src/timer/timg.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,14 @@ where
274274
Self {
275275
_timer_group: PhantomData,
276276
timer0: Timer {
277-
timer: 0,
277+
timer: TimerId::Timer0,
278278
tg: T::id(),
279279
register_block: T::register_block(),
280280
_lifetime: PhantomData,
281281
},
282282
#[cfg(timergroup_timg_has_timer1)]
283283
timer1: Timer {
284-
timer: 1,
284+
timer: TimerId::Timer1,
285285
tg: T::id(),
286286
register_block: T::register_block(),
287287
_lifetime: PhantomData,
@@ -380,10 +380,18 @@ impl super::Timer for Timer<'_> {
380380
pub struct Timer<'d> {
381381
register_block: *const RegisterBlock,
382382
_lifetime: PhantomData<&'d mut ()>,
383-
timer: u8,
383+
timer: TimerId,
384384
tg: u8,
385385
}
386386

387+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
388+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
389+
enum TimerId {
390+
Timer0,
391+
#[cfg(timergroup_timg_has_timer1)]
392+
Timer1,
393+
}
394+
387395
impl Sealed for Timer<'_> {}
388396
unsafe impl Send for Timer<'_> {}
389397

@@ -444,7 +452,7 @@ impl Timer<'_> {
444452
}
445453

446454
fn timer_number(&self) -> u8 {
447-
self.timer
455+
self.timer as u8
448456
}
449457

450458
fn t(&self) -> &crate::pac::timg0::T {
@@ -517,7 +525,7 @@ impl Timer<'_> {
517525
fn clear_interrupt(&self) {
518526
self.register_block()
519527
.int_clr()
520-
.write(|w| w.t(self.timer).clear_bit_by_one());
528+
.write(|w| w.t(self.timer as _).clear_bit_by_one());
521529
let periodic = self.t().config().read().autoreload().bit_is_set();
522530
self.set_alarm_active(periodic);
523531
}
@@ -567,7 +575,7 @@ impl Timer<'_> {
567575
self.register_block()
568576
.int_raw()
569577
.read()
570-
.t(self.timer)
578+
.t(self.timer as _)
571579
.bit_is_set()
572580
}
573581

@@ -577,8 +585,7 @@ impl Timer<'_> {
577585
// On ESP32 and S2, the `int_ena` register is ineffective - interrupts fire even
578586
// without int_ena enabling them. We use level interrupts so that we have a status
579587
// bit available.
580-
self.register_block()
581-
.t(self.timer as usize)
588+
self.t()
582589
.config()
583590
.modify(|_, w| w.level_int_en().bit(state));
584591
} else if #[cfg(timergroup_timg_has_timer1)] {
@@ -868,7 +875,7 @@ mod asynch {
868875
handle_irq(Timer {
869876
register_block: TIMG0::regs(),
870877
_lifetime: PhantomData,
871-
timer: 0,
878+
timer: TimerId::Timer0,
872879
tg: 0,
873880
});
874881
}
@@ -879,7 +886,7 @@ mod asynch {
879886
handle_irq(Timer {
880887
register_block: TIMG1::regs(),
881888
_lifetime: PhantomData,
882-
timer: 0,
889+
timer: TimerId::Timer0,
883890
tg: 1,
884891
});
885892
}
@@ -890,7 +897,7 @@ mod asynch {
890897
handle_irq(Timer {
891898
register_block: TIMG0::regs(),
892899
_lifetime: PhantomData,
893-
timer: 1,
900+
timer: TimerId::Timer1,
894901
tg: 0,
895902
});
896903
}
@@ -901,7 +908,7 @@ mod asynch {
901908
handle_irq(Timer {
902909
register_block: TIMG1::regs(),
903910
_lifetime: PhantomData,
904-
timer: 1,
911+
timer: TimerId::Timer1,
905912
tg: 1,
906913
});
907914
}

esp-sync/src/raw.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,22 @@ impl RawLock for SingleCoreInterruptLock {
6666
}
6767
}
6868
} else if #[cfg(xtensa)] {
69-
// Reserved bits in the PS register, these must be written as 0.
70-
const RESERVED_MASK: u32 = 0b1111_1111_1111_1000_1111_0000_0000_0000;
71-
debug_assert!(token & RESERVED_MASK == 0);
69+
#[cfg(debug_assertions)]
70+
{
71+
// Reserved bits in the PS register, these must be written as 0.
72+
const RESERVED_MASK: u32 = 0b1111_1111_1111_1000_1111_0000_0000_0000;
73+
if token & RESERVED_MASK != 0 {
74+
// We could do this transformation in fmt.rs automatically, but experiments
75+
// show this is only worth it in terms of binary size for code inlined into many places.
76+
#[cold]
77+
#[inline(never)]
78+
fn __assert_failed() {
79+
panic!("Reserved bits in PS register must be written as 0");
80+
}
81+
82+
__assert_failed();
83+
}
84+
}
7285
unsafe {
7386
core::arch::asm!(
7487
"wsr.ps {0}",

0 commit comments

Comments
 (0)