|
ChibiOS/RT
2.5.1 |
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 /** @} */