aboutsummaryrefslogtreecommitdiff
path: root/embassy-extras/src
diff options
context:
space:
mode:
authorLiam Murphy <[email protected]>2021-07-28 21:31:31 +1000
committerLiam Murphy <[email protected]>2021-07-28 21:31:31 +1000
commit68c93256bcab8dfe0f65c694fa5fadb890fd3f00 (patch)
treed76ddc56ac3f4caeef279919b5aca000aed2dc0e /embassy-extras/src
parenta6fea3cb28f717627bd8858016622270c3e76721 (diff)
fix: interrupts with equal priority can't preempt each other
Diffstat (limited to 'embassy-extras/src')
-rw-r--r--embassy-extras/src/peripheral.rs28
1 files changed, 4 insertions, 24 deletions
diff --git a/embassy-extras/src/peripheral.rs b/embassy-extras/src/peripheral.rs
index 2402ba9eb..396ab5432 100644
--- a/embassy-extras/src/peripheral.rs
+++ b/embassy-extras/src/peripheral.rs
@@ -21,7 +21,7 @@ pub unsafe trait PeripheralStateUnchecked: Send {
21/// A type which can be used as state with `PeripheralMutex`. 21/// A type which can be used as state with `PeripheralMutex`.
22/// 22///
23/// It needs to be `Send` because `&mut` references are sent back and forth between the 'thread' which owns the `PeripheralMutex` and the interrupt, 23/// It needs to be `Send` because `&mut` references are sent back and forth between the 'thread' which owns the `PeripheralMutex` and the interrupt,
24/// and `&mut T` is `Send` where `T: Send`. 24/// and `&mut T` is only `Send` where `T: Send`.
25/// 25///
26/// It also requires `'static`, because although `Pin` guarantees that the memory of the state won't be invalidated, 26/// It also requires `'static`, because although `Pin` guarantees that the memory of the state won't be invalidated,
27/// it doesn't guarantee that the lifetime will last. 27/// it doesn't guarantee that the lifetime will last.
@@ -73,23 +73,13 @@ fn exception_to_system_handler(exception: Exception) -> Option<SystemHandler> {
73/// Whether `irq` can be preempted by the current interrupt. 73/// Whether `irq` can be preempted by the current interrupt.
74pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool { 74pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool {
75 match SCB::vect_active() { 75 match SCB::vect_active() {
76 // Thread mode can't preempt each other 76 // Thread mode can't preempt anything
77 VectActive::ThreadMode => false, 77 VectActive::ThreadMode => false,
78 VectActive::Exception(exception) => { 78 VectActive::Exception(exception) => {
79 // `SystemHandler` is a subset of `Exception` for those with configurable priority. 79 // `SystemHandler` is a subset of `Exception` for those with configurable priority.
80 // There's no built in way to convert between them, so `exception_to_system_handler` was necessary. 80 // There's no built in way to convert between them, so `exception_to_system_handler` was necessary.
81 if let Some(system_handler) = exception_to_system_handler(exception) { 81 if let Some(system_handler) = exception_to_system_handler(exception) {
82 let current_prio = SCB::get_priority(system_handler); 82 SCB::get_priority(system_handler) < irq.get_priority().into()
83 let irq_prio = irq.get_priority().into();
84 if current_prio < irq_prio {
85 true
86 } else if current_prio == irq_prio {
87 // When multiple interrupts have the same priority number,
88 // the pending interrupt with the lowest interrupt number takes precedence.
89 (exception.irqn() as i16) < irq.number() as i16
90 } else {
91 false
92 }
93 } else { 83 } else {
94 // There's no safe way I know of to maintain `!Send` state across invocations of HardFault or NMI, so that should be fine. 84 // There's no safe way I know of to maintain `!Send` state across invocations of HardFault or NMI, so that should be fine.
95 false 85 false
@@ -103,17 +93,7 @@ pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool {
103 self.0 93 self.0
104 } 94 }
105 } 95 }
106 let current_prio = NVIC::get_priority(NrWrap(irqn.into())); 96 NVIC::get_priority(NrWrap(irqn.into())) < irq.get_priority().into()
107 let irq_prio = irq.get_priority().into();
108 if current_prio < irq_prio {
109 true
110 } else if current_prio == irq_prio {
111 // When multiple interrupts have the same priority number,
112 // the pending interrupt with the lowest interrupt number takes precedence.
113 (irqn as u16) < irq.number()
114 } else {
115 false
116 }
117 } 97 }
118 } 98 }
119} 99}