fix: interrupts with equal priority can't preempt each other
This commit is contained in:
parent
a6fea3cb28
commit
68c93256bc
@ -21,7 +21,7 @@ pub unsafe trait PeripheralStateUnchecked: Send {
|
|||||||
/// A type which can be used as state with `PeripheralMutex`.
|
/// A type which can be used as state with `PeripheralMutex`.
|
||||||
///
|
///
|
||||||
/// It needs to be `Send` because `&mut` references are sent back and forth between the 'thread' which owns the `PeripheralMutex` and the interrupt,
|
/// It needs to be `Send` because `&mut` references are sent back and forth between the 'thread' which owns the `PeripheralMutex` and the interrupt,
|
||||||
/// and `&mut T` is `Send` where `T: Send`.
|
/// and `&mut T` is only `Send` where `T: Send`.
|
||||||
///
|
///
|
||||||
/// It also requires `'static`, because although `Pin` guarantees that the memory of the state won't be invalidated,
|
/// It also requires `'static`, because although `Pin` guarantees that the memory of the state won't be invalidated,
|
||||||
/// it doesn't guarantee that the lifetime will last.
|
/// it doesn't guarantee that the lifetime will last.
|
||||||
@ -73,23 +73,13 @@ fn exception_to_system_handler(exception: Exception) -> Option<SystemHandler> {
|
|||||||
/// Whether `irq` can be preempted by the current interrupt.
|
/// Whether `irq` can be preempted by the current interrupt.
|
||||||
pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool {
|
pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool {
|
||||||
match SCB::vect_active() {
|
match SCB::vect_active() {
|
||||||
// Thread mode can't preempt each other
|
// Thread mode can't preempt anything
|
||||||
VectActive::ThreadMode => false,
|
VectActive::ThreadMode => false,
|
||||||
VectActive::Exception(exception) => {
|
VectActive::Exception(exception) => {
|
||||||
// `SystemHandler` is a subset of `Exception` for those with configurable priority.
|
// `SystemHandler` is a subset of `Exception` for those with configurable priority.
|
||||||
// There's no built in way to convert between them, so `exception_to_system_handler` was necessary.
|
// There's no built in way to convert between them, so `exception_to_system_handler` was necessary.
|
||||||
if let Some(system_handler) = exception_to_system_handler(exception) {
|
if let Some(system_handler) = exception_to_system_handler(exception) {
|
||||||
let current_prio = SCB::get_priority(system_handler);
|
SCB::get_priority(system_handler) < irq.get_priority().into()
|
||||||
let irq_prio = irq.get_priority().into();
|
|
||||||
if current_prio < irq_prio {
|
|
||||||
true
|
|
||||||
} else if current_prio == irq_prio {
|
|
||||||
// When multiple interrupts have the same priority number,
|
|
||||||
// the pending interrupt with the lowest interrupt number takes precedence.
|
|
||||||
(exception.irqn() as i16) < irq.number() as i16
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// There's no safe way I know of to maintain `!Send` state across invocations of HardFault or NMI, so that should be fine.
|
// There's no safe way I know of to maintain `!Send` state across invocations of HardFault or NMI, so that should be fine.
|
||||||
false
|
false
|
||||||
@ -103,17 +93,7 @@ pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool {
|
|||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let current_prio = NVIC::get_priority(NrWrap(irqn.into()));
|
NVIC::get_priority(NrWrap(irqn.into())) < irq.get_priority().into()
|
||||||
let irq_prio = irq.get_priority().into();
|
|
||||||
if current_prio < irq_prio {
|
|
||||||
true
|
|
||||||
} else if current_prio == irq_prio {
|
|
||||||
// When multiple interrupts have the same priority number,
|
|
||||||
// the pending interrupt with the lowest interrupt number takes precedence.
|
|
||||||
(irqn as u16) < irq.number()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user