summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <dirbaio@dirbaio.net>2020-09-05 04:25:34 +0200
committerDario Nieuwenhuis <dirbaio@dirbaio.net>2020-09-05 04:25:34 +0200
commit3076233462b303b2a0758ec4b428eb938ef2b431 (patch)
tree4b5ca5a85f71f90c207090ed3f1c85d5699df6ec
parentb0726e18bfbe1c688c2b8d441c9612a2c6b78ba8 (diff)
downloadnrf-softdevice-3076233462b303b2a0758ec4b428eb938ef2b431.zip
Better panic messages in interrupt.
-rw-r--r--.vscode/settings.json4
-rw-r--r--nrf-softdevice/src/events.rs5
-rw-r--r--nrf-softdevice/src/interrupt.rs116
-rw-r--r--nrf-softdevice/src/lib.rs4
-rw-r--r--nrf-softdevice/src/util/depanic.rs10
-rw-r--r--nrf-softdevice/src/util/macros.rs35
-rw-r--r--nrf-softdevice/src/util/mod.rs2
7 files changed, 140 insertions, 36 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1e1c62d..c0d9016 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,7 @@
{
"editor.formatOnSave": true,
"rust-analyzer.cargo.target": "thumbv7em-none-eabihf",
- "rust-analyzer.checkOnSave.allTargets": false
+ "rust-analyzer.checkOnSave.allTargets": false,
+ "rust-analyzer.cargo.loadOutDirsFromCheck": true,
+ "rust-analyzer.procMacro.enable": true
}
diff --git a/nrf-softdevice/src/events.rs b/nrf-softdevice/src/events.rs
index a92261b..7a0e509 100644
--- a/nrf-softdevice/src/events.rs
+++ b/nrf-softdevice/src/events.rs
@@ -4,8 +4,7 @@ use num_enum::{IntoPrimitive, TryFromPrimitive};
use crate::error::Error;
use crate::util::*;
-use crate::{pac, sd};
-use pac::interrupt;
+use crate::{interrupt, sd};
static SWI2_SIGNAL: Signal<()> = Signal::new();
@@ -146,7 +145,7 @@ pub async fn run() {
}
}
-#[cortex_m_rt::interrupt]
+#[interrupt]
unsafe fn SWI2_EGU2() {
SWI2_SIGNAL.signal(());
}
diff --git a/nrf-softdevice/src/interrupt.rs b/nrf-softdevice/src/interrupt.rs
index 84b9aea..a746904 100644
--- a/nrf-softdevice/src/interrupt.rs
+++ b/nrf-softdevice/src/interrupt.rs
@@ -1,8 +1,13 @@
-use bare_metal::CriticalSection;
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
use cortex_m::interrupt::InterruptNumber;
-use crate::pac::{Interrupt, NVIC, NVIC_PRIO_BITS};
+use crate::pac::{NVIC, NVIC_PRIO_BITS};
+use crate::util::*;
+
+// Re-exports
+pub use crate::pac::Interrupt;
+pub use crate::pac::Interrupt::*; // needed for cortex-m-rt #[interrupt]
+pub use bare_metal::{CriticalSection, Mutex};
const RESERVED_IRQS: [u32; 2] = [
(1 << (Interrupt::POWER_CLOCK as u8))
@@ -17,7 +22,7 @@ const RESERVED_IRQS: [u32; 2] = [
0,
];
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(defmt::Format, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[repr(u8)]
pub enum Priority {
Level0 = 0,
@@ -52,7 +57,7 @@ impl Priority {
}
}
-static mut CS_FLAG: AtomicBool = AtomicBool::new(false);
+static CS_FLAG: AtomicBool = AtomicBool::new(false);
static mut CS_MASK: [u32; 2] = [0; 2];
#[inline]
@@ -91,9 +96,6 @@ where
F: FnOnce(&CriticalSection) -> R,
{
unsafe {
- // TODO: assert that we're in privileged level
- // Needed because disabling irqs in non-privileged level is a noop, which would break safety.
-
let nvic = &*NVIC::ptr();
let nested_cs = CS_FLAG.load(Ordering::SeqCst);
@@ -151,10 +153,26 @@ fn is_app_accessible_priority(priority: Priority) -> bool {
}
}
+macro_rules! assert_app_accessible_irq {
+ ($irq:ident) => {
+ deassert!(
+ is_app_accessible_irq($irq),
+ "irq {:istr} is reserved for the softdevice",
+ irq_str($irq)
+ );
+ };
+}
+
#[inline]
-pub fn unmask(irq: Interrupt) {
- assert!(is_app_accessible_irq(irq));
- assert!(is_app_accessible_priority(get_priority(irq)));
+pub fn enable(irq: Interrupt) {
+ assert_app_accessible_irq!(irq);
+ let prio = get_priority(irq);
+ deassert!(
+ is_app_accessible_priority(prio),
+ "irq {:istr} has priority {:?} which is reserved for the softdevice. Set another prority before enabling it.",
+ irq_str(irq),
+ prio
+ );
unsafe {
if CS_FLAG.load(Ordering::SeqCst) {
@@ -167,8 +185,8 @@ pub fn unmask(irq: Interrupt) {
}
#[inline]
-pub fn mask(irq: Interrupt) {
- assert!(is_app_accessible_irq(irq));
+pub fn disable(irq: Interrupt) {
+ assert_app_accessible_irq!(irq);
unsafe {
if CS_FLAG.load(Ordering::SeqCst) {
@@ -182,46 +200,104 @@ pub fn mask(irq: Interrupt) {
#[inline]
pub fn is_active(irq: Interrupt) -> bool {
- assert!(is_app_accessible_irq(irq));
+ assert_app_accessible_irq!(irq);
NVIC::is_active(irq)
}
#[inline]
pub fn is_enabled(irq: Interrupt) -> bool {
- assert!(is_app_accessible_irq(irq));
- NVIC::is_enabled(irq)
+ assert_app_accessible_irq!(irq);
+ if CS_FLAG.load(Ordering::SeqCst) {
+ let nr = irq.number();
+ unsafe { CS_MASK[usize::from(nr / 32)] & (1 << (nr % 32)) != 0 }
+ } else {
+ NVIC::is_enabled(irq)
+ }
}
#[inline]
pub fn is_pending(irq: Interrupt) -> bool {
- assert!(is_app_accessible_irq(irq));
+ assert_app_accessible_irq!(irq);
NVIC::is_pending(irq)
}
#[inline]
pub fn pend(irq: Interrupt) {
- assert!(is_app_accessible_irq(irq));
+ assert_app_accessible_irq!(irq);
NVIC::pend(irq)
}
#[inline]
pub fn unpend(irq: Interrupt) {
- assert!(is_app_accessible_irq(irq));
+ assert_app_accessible_irq!(irq);
NVIC::unpend(irq)
}
#[inline]
pub fn get_priority(irq: Interrupt) -> Priority {
+ assert_app_accessible_irq!(irq);
Priority::from_nvic(NVIC::get_priority(irq))
}
#[inline]
pub fn set_priority(irq: Interrupt, prio: Priority) {
- assert!(is_app_accessible_irq(irq));
- assert!(is_app_accessible_priority(prio));
+ assert_app_accessible_irq!(irq);
+ deassert!(
+ is_app_accessible_priority(prio),
+ "priority level {:?} is reserved for the softdevice",
+ prio
+ );
unsafe {
cortex_m::peripheral::Peripherals::steal()
.NVIC
.set_priority(irq, prio.to_nvic())
}
}
+
+fn irq_str(irq: Interrupt) -> defmt::Str {
+ match irq {
+ POWER_CLOCK => defmt::intern!("POWER_CLOCK"),
+ RADIO => defmt::intern!("RADIO"),
+ UARTE0_UART0 => defmt::intern!("UARTE0_UART0"),
+ SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => defmt::intern!("SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0"),
+ SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => defmt::intern!("SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1"),
+ NFCT => defmt::intern!("NFCT"),
+ GPIOTE => defmt::intern!("GPIOTE"),
+ SAADC => defmt::intern!("SAADC"),
+ TIMER0 => defmt::intern!("TIMER0"),
+ TIMER1 => defmt::intern!("TIMER1"),
+ TIMER2 => defmt::intern!("TIMER2"),
+ RTC0 => defmt::intern!("RTC0"),
+ TEMP => defmt::intern!("TEMP"),
+ RNG => defmt::intern!("RNG"),
+ ECB => defmt::intern!("ECB"),
+ CCM_AAR => defmt::intern!("CCM_AAR"),
+ WDT => defmt::intern!("WDT"),
+ RTC1 => defmt::intern!("RTC1"),
+ QDEC => defmt::intern!("QDEC"),
+ COMP_LPCOMP => defmt::intern!("COMP_LPCOMP"),
+ SWI0_EGU0 => defmt::intern!("SWI0_EGU0"),
+ SWI1_EGU1 => defmt::intern!("SWI1_EGU1"),
+ SWI2_EGU2 => defmt::intern!("SWI2_EGU2"),
+ SWI3_EGU3 => defmt::intern!("SWI3_EGU3"),
+ SWI4_EGU4 => defmt::intern!("SWI4_EGU4"),
+ SWI5_EGU5 => defmt::intern!("SWI5_EGU5"),
+ TIMER3 => defmt::intern!("TIMER3"),
+ TIMER4 => defmt::intern!("TIMER4"),
+ PWM0 => defmt::intern!("PWM0"),
+ PDM => defmt::intern!("PDM"),
+ MWU => defmt::intern!("MWU"),
+ PWM1 => defmt::intern!("PWM1"),
+ PWM2 => defmt::intern!("PWM2"),
+ SPIM2_SPIS2_SPI2 => defmt::intern!("SPIM2_SPIS2_SPI2"),
+ RTC2 => defmt::intern!("RTC2"),
+ I2S => defmt::intern!("I2S"),
+ FPU => defmt::intern!("FPU"),
+ USBD => defmt::intern!("USBD"),
+ UARTE1 => defmt::intern!("UARTE1"),
+ QSPI => defmt::intern!("QSPI"),
+ CRYPTOCELL => defmt::intern!("CRYPTOCELL"),
+ PWM3 => defmt::intern!("PWM3"),
+ SPIM3 => defmt::intern!("SPIM3"),
+ }
+}
diff --git a/nrf-softdevice/src/lib.rs b/nrf-softdevice/src/lib.rs
index 5de9e22..c423988 100644
--- a/nrf-softdevice/src/lib.rs
+++ b/nrf-softdevice/src/lib.rs
@@ -20,6 +20,8 @@ pub use flash::*;
mod error;
pub use error::*;
+pub use cortex_m_rt::interrupt;
+
use defmt::{info, warn};
unsafe extern "C" fn fault_handler(id: u32, pc: u32, info: u32) {
@@ -64,5 +66,5 @@ pub unsafe fn enable() {
warn!("You're giving more RAM to the softdevice than needed. You can change your app's RAM start address to {:u32}", wanted_app_ram_base);
}
- crate::interrupt::unmask(pac::Interrupt::SWI2_EGU2);
+ interrupt::enable(interrupt::Interrupt::SWI2_EGU2);
}
diff --git a/nrf-softdevice/src/util/depanic.rs b/nrf-softdevice/src/util/depanic.rs
deleted file mode 100644
index 5d1bcc9..0000000
--- a/nrf-softdevice/src/util/depanic.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![macro_use]
-
-macro_rules! depanic {
- ($( $i:expr ),*) => {
- {
- defmt::error!($( $i ),*);
- panic!();
- }
- }
-}
diff --git a/nrf-softdevice/src/util/macros.rs b/nrf-softdevice/src/util/macros.rs
new file mode 100644
index 0000000..0789f71
--- /dev/null
+++ b/nrf-softdevice/src/util/macros.rs
@@ -0,0 +1,35 @@
+#![macro_use]
+
+use core::concat;
+use core::stringify;
+
+macro_rules! depanic {
+ ($( $i:expr ),*) => {
+ {
+ defmt::error!($( $i ),*);
+ panic!();
+ }
+ }
+}
+
+macro_rules! deassert {
+ ($cond:expr) => {
+ deassert!($cond, "assertion failed");
+ };
+ ($cond:expr, $msg:literal) => {
+ {
+ if !$cond {
+ defmt::error!($msg);
+ panic!();
+ }
+ }
+ };
+ ($cond:expr, $msg:literal, $( $i:expr ),*) => {
+ {
+ if !$cond {
+ defmt::error!($msg, $( $i ),*);
+ panic!();
+ }
+ }
+ };
+}
diff --git a/nrf-softdevice/src/util/mod.rs b/nrf-softdevice/src/util/mod.rs
index 22ca7ff..bcc9fe2 100644
--- a/nrf-softdevice/src/util/mod.rs
+++ b/nrf-softdevice/src/util/mod.rs
@@ -1,6 +1,6 @@
#![macro_use]
-mod depanic;
+mod macros;
mod signal;
pub use signal::*;