ChibiOS/RT
2.5.1
chdebug.c
Go to the documentation of this file.
00001 /*
00002     ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
00003                  2011,2012 Giovanni Di Sirio.
00004 
00005     This file is part of ChibiOS/RT.
00006 
00007     ChibiOS/RT is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 3 of the License, or
00010     (at your option) any later version.
00011 
00012     ChibiOS/RT is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 /**
00022  * @file    chdebug.c
00023  * @brief   ChibiOS/RT Debug code.
00024  *
00025  * @addtogroup debug
00026  * @details Debug APIs and services:
00027  *          - Runtime system state and call protocol check. The following
00028  *            panic messages can be generated:
00029  *            - SV#1, misplaced @p chSysDisable().
00030  *            - SV#2, misplaced @p chSysSuspend()
00031  *            - SV#3, misplaced @p chSysEnable().
00032  *            - SV#4, misplaced @p chSysLock().
00033  *            - SV#5, misplaced @p chSysUnlock().
00034  *            - SV#6, misplaced @p chSysLockFromIsr().
00035  *            - SV#7, misplaced @p chSysUnlockFromIsr().
00036  *            - SV#8, misplaced @p CH_IRQ_PROLOGUE().
00037  *            - SV#9, misplaced @p CH_IRQ_EPILOGUE().
00038  *            - SV#10, misplaced I-class function.
00039  *            - SV#11, misplaced S-class function.
00040  *            .
00041  *          - Trace buffer.
00042  *          - Parameters check.
00043  *          - Kernel assertions.
00044  *          - Kernel panics.
00045  *          .
00046  * @note    Stack checks are not implemented in this module but in the port
00047  *          layer in an architecture-dependent way.
00048  * @{
00049  */
00050 
00051 #include "ch.h"
00052 
00053 /*===========================================================================*/
00054 /* System state checker related code and variables.                          */
00055 /*===========================================================================*/
00056 
00057 #if CH_DBG_SYSTEM_STATE_CHECK || defined(__DOXYGEN__)
00058 
00059 /**
00060  * @brief   ISR nesting level.
00061  */
00062 cnt_t dbg_isr_cnt;
00063 
00064 /**
00065  * @brief   Lock nesting level.
00066  */
00067 cnt_t dbg_lock_cnt;
00068 
00069 /**
00070  * @brief   Guard code for @p chSysDisable().
00071  *
00072  * @notapi
00073  */
00074 void dbg_check_disable(void) {
00075 
00076   if ((dbg_isr_cnt != 0) || (dbg_lock_cnt != 0))
00077     chDbgPanic("SV#1");
00078 }
00079 
00080 /**
00081  * @brief   Guard code for @p chSysSuspend().
00082  *
00083  * @notapi
00084  */
00085 void dbg_check_suspend(void) {
00086 
00087   if ((dbg_isr_cnt != 0) || (dbg_lock_cnt != 0))
00088     chDbgPanic("SV#2");
00089 }
00090 
00091 /**
00092  * @brief   Guard code for @p chSysEnable().
00093  *
00094  * @notapi
00095  */
00096 void dbg_check_enable(void) {
00097 
00098   if ((dbg_isr_cnt != 0) || (dbg_lock_cnt != 0))
00099     chDbgPanic("SV#3");
00100 }
00101 
00102 /**
00103  * @brief   Guard code for @p chSysLock().
00104  *
00105  * @notapi
00106  */
00107 void dbg_check_lock(void) {
00108 
00109   if ((dbg_isr_cnt != 0) || (dbg_lock_cnt != 0))
00110     chDbgPanic("SV#4");
00111   dbg_enter_lock();
00112 }
00113 
00114 /**
00115  * @brief   Guard code for @p chSysUnlock().
00116  *
00117  * @notapi
00118  */
00119 void dbg_check_unlock(void) {
00120 
00121   if ((dbg_isr_cnt != 0) || (dbg_lock_cnt <= 0))
00122     chDbgPanic("SV#5");
00123   dbg_leave_lock();
00124 }
00125 
00126 /**
00127  * @brief   Guard code for @p chSysLockFromIsr().
00128  *
00129  * @notapi
00130  */
00131 void dbg_check_lock_from_isr(void) {
00132 
00133   if ((dbg_isr_cnt <= 0) || (dbg_lock_cnt != 0))
00134     chDbgPanic("SV#6");
00135   dbg_enter_lock();
00136 }
00137 
00138 /**
00139  * @brief   Guard code for @p chSysUnlockFromIsr().
00140  *
00141  * @notapi
00142  */
00143 void dbg_check_unlock_from_isr(void) {
00144 
00145   if ((dbg_isr_cnt <= 0) || (dbg_lock_cnt <= 0))
00146     chDbgPanic("SV#7");
00147   dbg_leave_lock();
00148 }
00149 
00150 /**
00151  * @brief   Guard code for @p CH_IRQ_PROLOGUE().
00152  *
00153  * @notapi
00154  */
00155 void dbg_check_enter_isr(void) {
00156 
00157   port_lock_from_isr();
00158   if ((dbg_isr_cnt < 0) || (dbg_lock_cnt != 0))
00159     chDbgPanic("SV#8");
00160   dbg_isr_cnt++;
00161   port_unlock_from_isr();
00162 }
00163 
00164 /**
00165  * @brief   Guard code for @p CH_IRQ_EPILOGUE().
00166  *
00167  * @notapi
00168  */
00169 void dbg_check_leave_isr(void) {
00170 
00171   port_lock_from_isr();
00172   if ((dbg_isr_cnt <= 0) || (dbg_lock_cnt != 0))
00173     chDbgPanic("SV#9");
00174   dbg_isr_cnt--;
00175   port_unlock_from_isr();
00176 }
00177 
00178 /**
00179  * @brief   I-class functions context check.
00180  * @details Verifies that the system is in an appropriate state for invoking
00181  *          an I-class API function. A panic is generated if the state is
00182  *          not compatible.
00183  *
00184  * @api
00185  */
00186 void chDbgCheckClassI(void) {
00187 
00188   if ((dbg_isr_cnt < 0) || (dbg_lock_cnt <= 0))
00189     chDbgPanic("SV#10");
00190 }
00191 
00192 /**
00193  * @brief   S-class functions context check.
00194  * @details Verifies that the system is in an appropriate state for invoking
00195  *          an S-class API function. A panic is generated if the state is
00196  *          not compatible.
00197  *
00198  * @api
00199  */
00200 void chDbgCheckClassS(void) {
00201 
00202   if ((dbg_isr_cnt != 0) || (dbg_lock_cnt <= 0))
00203     chDbgPanic("SV#11");
00204 }
00205 
00206 #endif /* CH_DBG_SYSTEM_STATE_CHECK */
00207 
00208 /*===========================================================================*/
00209 /* Trace related code and variables.                                         */
00210 /*===========================================================================*/
00211 
00212 #if CH_DBG_ENABLE_TRACE || defined(__DOXYGEN__)
00213 /**
00214  * @brief   Public trace buffer.
00215  */
00216 ch_trace_buffer_t dbg_trace_buffer;
00217 
00218 /**
00219  * @brief   Trace circular buffer subsystem initialization.
00220  * @note    Internal use only.
00221  */
00222 void _trace_init(void) {
00223 
00224   dbg_trace_buffer.tb_size = CH_TRACE_BUFFER_SIZE;
00225   dbg_trace_buffer.tb_ptr = &dbg_trace_buffer.tb_buffer[0];
00226 }
00227 
00228 /**
00229  * @brief   Inserts in the circular debug trace buffer a context switch record.
00230  *
00231  * @param[in] otp       the thread being switched out
00232  *
00233  * @notapi
00234  */
00235 void dbg_trace(Thread *otp) {
00236 
00237   dbg_trace_buffer.tb_ptr->se_time   = chTimeNow();
00238   dbg_trace_buffer.tb_ptr->se_tp     = currp;
00239   dbg_trace_buffer.tb_ptr->se_wtobjp = otp->p_u.wtobjp;
00240   dbg_trace_buffer.tb_ptr->se_state  = (uint8_t)otp->p_state;
00241   if (++dbg_trace_buffer.tb_ptr >=
00242       &dbg_trace_buffer.tb_buffer[CH_TRACE_BUFFER_SIZE])
00243     dbg_trace_buffer.tb_ptr = &dbg_trace_buffer.tb_buffer[0];
00244 }
00245 #endif /* CH_DBG_ENABLE_TRACE */
00246 
00247 /*===========================================================================*/
00248 /* Panic related code and variables.                                         */
00249 /*===========================================================================*/
00250 
00251 #if CH_DBG_ENABLED || defined(__DOXYGEN__)
00252 /**
00253  * @brief   Pointer to the panic message.
00254  * @details This pointer is meant to be accessed through the debugger, it is
00255  *          written once and then the system is halted.
00256  */
00257 const char *dbg_panic_msg;
00258 
00259 /**
00260  * @brief   Prints a panic message on the console and then halts the system.
00261  *
00262  * @param[in] msg       the pointer to the panic message string
00263  */
00264 void chDbgPanic(const char *msg) {
00265 
00266   dbg_panic_msg = msg;
00267   chSysHalt();
00268 }
00269 #endif /* CH_DBG_ENABLED */
00270 
00271 /** @} */