aboutsummaryrefslogtreecommitdiffstats
path: root/os/kernel/src/chdebug.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/kernel/src/chdebug.c')
-rw-r--r--os/kernel/src/chdebug.c163
1 files changed, 154 insertions, 9 deletions
diff --git a/os/kernel/src/chdebug.c b/os/kernel/src/chdebug.c
index 0e378cc6d..28d4f7520 100644
--- a/os/kernel/src/chdebug.c
+++ b/os/kernel/src/chdebug.c
@@ -24,18 +24,161 @@
*
* @addtogroup debug
* @details Debug APIs and services:
+ * - Runtime system state and call protocol check. The following
+ * panic messages can be generated:
+ * - SV#1, misplaced @p chSysDisable().
+ * - SV#2, misplaced @p chSysSuspend()
+ * - SV#3, misplaced @p chSysEnable().
+ * - SV#4, misplaced @p chSysLock().
+ * - SV#5, misplaced @p chSysUnlock().
+ * - SV#6, misplaced @p chSysLockFromIsr().
+ * - SV#7, misplaced @p chSysUnlockFromIsr().
+ * - SV#8, misplaced @p CH_IRQ_PROLOGUE().
+ * - SV#9, misplaced @p CH_IRQ_EPILOGUE().
+ * .
* - Trace buffer.
* - Parameters check.
* - Kernel assertions.
+ * - Kernel panics.
* .
- * @pre In order to use the debug APIs the @p CH_DBG_ENABLE_TRACE,
- * @p CH_DBG_ENABLE_ASSERTS, @p CH_DBG_ENABLE_CHECKS options must
- * be enabled in @p chconf.h.
+ * @note Stack checks are not implemented in this module but in the port
+ * layer in an architecture-dependent way.
* @{
*/
#include "ch.h"
+/*===========================================================================*/
+/* System state checker related code and variables. */
+/*===========================================================================*/
+
+#if CH_DBG_SYSTEM_STATE_CHECK || defined(__DOXYGEN__)
+
+/**
+ * @brief ISR nesting level.
+ */
+cnt_t dbg_isr_cnt;
+
+/**
+ * @brief Lock nesting level.
+ */
+cnt_t dbg_lock_cnt;
+
+/**
+ * @brief Guard code for @p chSysDisable().
+ *
+ * @notapi
+ */
+void dbg_check_disable(void) {
+
+ if ((dbg_isr_cnt != 0) || (dbg_lock_cnt != 0))
+ chDbgPanic("SV#1");
+}
+
+/**
+ * @brief Guard code for @p chSysSuspend().
+ *
+ * @notapi
+ */
+void dbg_check_suspend(void) {
+
+ if ((dbg_isr_cnt != 0) || (dbg_lock_cnt != 0))
+ chDbgPanic("SV#2");
+}
+
+/**
+ * @brief Guard code for @p chSysEnable().
+ *
+ * @notapi
+ */
+void dbg_check_enable(void) {
+
+ if ((dbg_isr_cnt != 0) || (dbg_lock_cnt != 0))
+ chDbgPanic("SV#3");
+}
+
+/**
+ * @brief Guard code for @p chSysLock().
+ *
+ * @notapi
+ */
+void dbg_check_lock(void) {
+
+ if ((dbg_isr_cnt != 0) || (dbg_lock_cnt != 0))
+ chDbgPanic("SV#4");
+ dbg_lock_cnt = 1;
+}
+
+/**
+ * @brief Guard code for @p chSysUnlock().
+ *
+ * @notapi
+ */
+void dbg_check_unlock(void) {
+
+ if ((dbg_isr_cnt != 0) || (dbg_lock_cnt <= 0))
+ chDbgPanic("SV#5");
+ dbg_lock_cnt = 0;
+}
+
+/**
+ * @brief Guard code for @p chSysLockFromIsr().
+ *
+ * @notapi
+ */
+void dbg_check_lock_from_isr(void) {
+
+ if ((dbg_isr_cnt <= 0) || (dbg_lock_cnt != 0))
+ chDbgPanic("SV#6");
+ dbg_lock_cnt = 1;
+}
+
+/**
+ * @brief Guard code for @p chSysUnlockFromIsr().
+ *
+ * @notapi
+ */
+void dbg_check_unlock_from_isr(void) {
+
+ if ((dbg_isr_cnt <= 0) || (dbg_lock_cnt <= 0))
+ chDbgPanic("SV#7");
+ dbg_lock_cnt = 0;
+}
+
+/**
+ * @brief Guard code for @p CH_IRQ_PROLOGUE().
+ *
+ * @notapi
+ */
+void dbg_check_enter_isr(void) {
+
+ port_lock_from_isr();
+ if (dbg_isr_cnt < 0)
+ chDbgPanic("SV#8");
+ dbg_isr_cnt++;
+ port_unlock_from_isr();
+}
+
+/**
+ * @brief Guard code for @p CH_IRQ_EPILOGUE().
+ *
+ * @notapi
+ */
+void dbg_check_leave_isr(void) {
+
+ port_lock_from_isr();
+ if (dbg_isr_cnt <= 0)
+ chDbgPanic("SV#9");
+ dbg_isr_cnt--;
+ port_unlock_from_isr();
+}
+
+#endif /* CH_DBG_SYSTEM_STATE_CHECK */
+
+/*===========================================================================*/
+/* Trace related code and variables. */
+/*===========================================================================*/
+
#if CH_DBG_ENABLE_TRACE || defined(__DOXYGEN__)
/**
* @brief Public trace buffer.
@@ -59,7 +202,7 @@ void _trace_init(void) {
*
* @notapi
*/
-void chDbgTrace(Thread *otp) {
+void dbg_trace(Thread *otp) {
dbg_trace_buffer.tb_ptr->se_time = chTimeNow();
dbg_trace_buffer.tb_ptr->se_tp = currp;
@@ -71,13 +214,15 @@ void chDbgTrace(Thread *otp) {
}
#endif /* CH_DBG_ENABLE_TRACE */
-#if CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || \
- CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__)
+/*===========================================================================*/
+/* Panic related code and variables. */
+/*===========================================================================*/
+
+#if CH_DBG_ENABLED || defined(__DOXYGEN__)
/**
* @brief Pointer to the panic message.
* @details This pointer is meant to be accessed through the debugger, it is
- * written once and then the system is halted. This variable can be
- * set to @p NULL if the halt is caused by a stack overflow.
+ * written once and then the system is halted.
*/
char *dbg_panic_msg;
@@ -91,6 +236,6 @@ void chDbgPanic(char *msg) {
dbg_panic_msg = msg;
chSysHalt();
}
-#endif /* CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK */
+#endif /* CH_DBG_ENABLED */
/** @} */