Skip to content

Commit 27d5259

Browse files
committed
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 e41b273 commit 27d5259

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

src/peripheral/scb.rs

+94
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

@@ -1011,4 +1013,96 @@ impl SCB {
10111013
});
10121014
}
10131015
}
1016+
1017+
/// Enable the exception
1018+
///
1019+
/// If the exception is enabled, when the exception is triggered, the exception handler will be executed instead of the
1020+
/// HardFault handler.
1021+
/// This function is only allowed on the following exceptions:
1022+
/// * `MemoryManagement`
1023+
/// * `BusFault`
1024+
/// * `UsageFault`
1025+
/// * `SecureFault` (can only be enabled from Secure state)
1026+
///
1027+
/// Calling this function with any other exception will do nothing.
1028+
#[inline]
1029+
#[cfg(not(any(armv6m, armv8m_base)))]
1030+
pub fn enable(&mut self, exception: Exception) {
1031+
if self.is_enabled(exception) {
1032+
return;
1033+
}
1034+
1035+
// Make sure that the read-modify-write sequence happens during a critical section to avoid
1036+
// modifying pending and active interrupts.
1037+
interrupt::free(|_| {
1038+
let shift = match exception {
1039+
Exception::MemoryManagement => 16,
1040+
Exception::BusFault => 17,
1041+
Exception::UsageFault => 18,
1042+
#[cfg(armv8m_main)]
1043+
Exception::SecureFault => 19,
1044+
_ => return,
1045+
};
1046+
1047+
unsafe { self.shcsr.modify(|value| value | (1 << shift)) }
1048+
})
1049+
}
1050+
1051+
/// Disable the exception
1052+
///
1053+
/// If the exception is disabled, when the exception is triggered, the HardFault handler will be executed instead of the
1054+
/// exception handler.
1055+
/// This function is only allowed on the following exceptions:
1056+
/// * `MemoryManagement`
1057+
/// * `BusFault`
1058+
/// * `UsageFault`
1059+
/// * `SecureFault` (can not be changed from Non-secure state)
1060+
///
1061+
/// Calling this function with any other exception will do nothing.
1062+
#[inline]
1063+
#[cfg(not(any(armv6m, armv8m_base)))]
1064+
pub fn disable(&mut self, exception: Exception) {
1065+
if !self.is_enabled(exception) {
1066+
return;
1067+
}
1068+
1069+
// Make sure that the read-modify-write sequence happens during a critical section to avoid
1070+
// modifying pending and active interrupts.
1071+
interrupt::free(|_| {
1072+
let shift = match exception {
1073+
Exception::MemoryManagement => 16,
1074+
Exception::BusFault => 17,
1075+
Exception::UsageFault => 18,
1076+
#[cfg(armv8m_main)]
1077+
Exception::SecureFault => 19,
1078+
_ => return,
1079+
};
1080+
1081+
unsafe { self.shcsr.modify(|value| value & !(1 << shift)) }
1082+
})
1083+
}
1084+
1085+
/// Check if an exception is enabled
1086+
///
1087+
/// This function is only allowed on the following exception:
1088+
/// * `MemoryManagement`
1089+
/// * `BusFault`
1090+
/// * `UsageFault`
1091+
/// * `SecureFault` (can not be read from Non-secure state)
1092+
///
1093+
/// Calling this function with any other exception will read `false`.
1094+
#[inline]
1095+
#[cfg(not(any(armv6m, armv8m_base)))]
1096+
pub fn is_enabled(&mut self, exception: Exception) -> bool {
1097+
let shift = match exception {
1098+
Exception::MemoryManagement => 16,
1099+
Exception::BusFault => 17,
1100+
Exception::UsageFault => 18,
1101+
#[cfg(armv8m_main)]
1102+
Exception::SecureFault => 19,
1103+
_ => return false,
1104+
};
1105+
1106+
(self.shcsr.read() & (1 << shift)) > 0
1107+
}
10141108
}

0 commit comments

Comments
 (0)