Skip to content

Commit 477b9ea

Browse files
hug-devjonas-schievink
authored andcommitted
Add SCB methods to enable/disable exceptions
Some exceptions might be disabled by default which means that the HardFault handler will be called instead of the exception handler. This commit adds methods on the SCB peripheral that use the SHCSR register to enable/disable exceptions. Signed-off-by: Hugues de Valon <[email protected]>
1 parent b8a0ee7 commit 477b9ea

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

src/peripheral/scb.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! System Control Block
22
33
use core::ptr;
4+
#[cfg(not(any(armv6m, armv8m_base)))]
5+
use crate::interrupt;
46

57
use volatile_register::RW;
68

@@ -839,4 +841,96 @@ impl SCB {
839841
});
840842
}
841843
}
844+
845+
/// Enable the exception
846+
///
847+
/// If the exception is enabled, when the exception is triggered, the exception handler will be executed instead of the
848+
/// HardFault handler.
849+
/// This function is only allowed on the following exceptions:
850+
/// * `MemoryManagement`
851+
/// * `BusFault`
852+
/// * `UsageFault`
853+
/// * `SecureFault` (can only be enabled from Secure state)
854+
///
855+
/// Calling this function with any other exception will do nothing.
856+
#[inline]
857+
#[cfg(not(any(armv6m, armv8m_base)))]
858+
pub fn enable(&mut self, exception: Exception) {
859+
if self.is_enabled(exception) {
860+
return;
861+
}
862+
863+
// Make sure that the read-modify-write sequence happens during a critical section to avoid
864+
// modifying pending and active interrupts.
865+
interrupt::free(|_| {
866+
let shift = match exception {
867+
Exception::MemoryManagement => 16,
868+
Exception::BusFault => 17,
869+
Exception::UsageFault => 18,
870+
#[cfg(armv8m_main)]
871+
Exception::SecureFault => 19,
872+
_ => return,
873+
};
874+
875+
unsafe { self.shcsr.modify(|value| value | (1 << shift)) }
876+
})
877+
}
878+
879+
/// Disable the exception
880+
///
881+
/// If the exception is disabled, when the exception is triggered, the HardFault handler will be executed instead of the
882+
/// exception handler.
883+
/// This function is only allowed on the following exceptions:
884+
/// * `MemoryManagement`
885+
/// * `BusFault`
886+
/// * `UsageFault`
887+
/// * `SecureFault` (can not be changed from Non-secure state)
888+
///
889+
/// Calling this function with any other exception will do nothing.
890+
#[inline]
891+
#[cfg(not(any(armv6m, armv8m_base)))]
892+
pub fn disable(&mut self, exception: Exception) {
893+
if !self.is_enabled(exception) {
894+
return;
895+
}
896+
897+
// Make sure that the read-modify-write sequence happens during a critical section to avoid
898+
// modifying pending and active interrupts.
899+
interrupt::free(|_| {
900+
let shift = match exception {
901+
Exception::MemoryManagement => 16,
902+
Exception::BusFault => 17,
903+
Exception::UsageFault => 18,
904+
#[cfg(armv8m_main)]
905+
Exception::SecureFault => 19,
906+
_ => return,
907+
};
908+
909+
unsafe { self.shcsr.modify(|value| value & !(1 << shift)) }
910+
})
911+
}
912+
913+
/// Check if an exception is enabled
914+
///
915+
/// This function is only allowed on the following exception:
916+
/// * `MemoryManagement`
917+
/// * `BusFault`
918+
/// * `UsageFault`
919+
/// * `SecureFault` (can not be read from Non-secure state)
920+
///
921+
/// Calling this function with any other exception will read `false`.
922+
#[inline]
923+
#[cfg(not(any(armv6m, armv8m_base)))]
924+
pub fn is_enabled(&mut self, exception: Exception) -> bool {
925+
let shift = match exception {
926+
Exception::MemoryManagement => 16,
927+
Exception::BusFault => 17,
928+
Exception::UsageFault => 18,
929+
#[cfg(armv8m_main)]
930+
Exception::SecureFault => 19,
931+
_ => return false,
932+
};
933+
934+
(self.shcsr.read() & (1 << shift)) > 0
935+
}
842936
}

0 commit comments

Comments
 (0)