|
32 | 32 | #include "platform/mbed_critical.h"
|
33 | 33 | #include "platform/mbed_stats.h"
|
34 | 34 |
|
| 35 | +#if !MBED_STACK_STATS_ENABLED |
| 36 | +#warning MBED_STACK_STATS_ENABLED != 1, so there will be no stack usage measurements. |
| 37 | +#endif |
| 38 | + |
35 | 39 | #ifndef DEBUG_ISR_STACK_USAGE
|
36 | 40 | #define DEBUG_ISR_STACK_USAGE 0
|
37 | 41 | #endif
|
@@ -192,10 +196,24 @@ static void debug_print_pointer(const void * pointer)
|
192 | 196 | #if (defined (MBED_CONF_RTOS_PRESENT) && (MBED_CONF_RTOS_PRESENT != 0))
|
193 | 197 | #include "cmsis_os.h"
|
194 | 198 |
|
195 |
| -// Temporarily #undef NULL or the compiler complains about previous def. |
196 |
| -#undef NULL |
197 |
| -#include "rt_TypeDef.h" |
198 |
| - |
| 199 | +// cmsis_os.h provides some useful defines: |
| 200 | +// |
| 201 | +// For mbed OS 5.4 and lower, osCMSIS == 0x10002U (see: rtos/rtx/TARGET_CORTEX_M) |
| 202 | +// For mbed OS 5.5 and higher, osCMSIS == 0x20001U (see: rtos/TARGET_CORTEX/rtx{4|5}) |
| 203 | +// |
| 204 | +// Starting in mbed OS 5.5, a new RTOS layer was introduced with a different API. |
| 205 | + |
| 206 | +#if (osCMSIS < 0x20000U) |
| 207 | + // Temporarily #undef NULL or the compiler complains about previous def. |
| 208 | + #undef NULL |
| 209 | + #include "rt_TypeDef.h" |
| 210 | +#else |
| 211 | + #include "rtx_lib.h" |
| 212 | + // #include <stdlib.h> // Include if you need malloc() / free() below. (probably better for non-C99 compilers) |
| 213 | +#endif |
| 214 | + |
| 215 | +#if (osCMSIS < 0x20000U) |
| 216 | + |
199 | 217 | // No public forward declaration for this.
|
200 | 218 | extern P_TCB rt_tid2ptcb (osThreadId thread_id);
|
201 | 219 |
|
@@ -248,6 +266,89 @@ void print_all_thread_info(void)
|
248 | 266 | _osThreadEnumFree(enumId);
|
249 | 267 | }
|
250 | 268 |
|
| 269 | +#else |
| 270 | + |
| 271 | +static void print_thread_info(osThreadId threadId) |
| 272 | +{ |
| 273 | + // Refs: rtx_lib.h - #define os_thread_t osRtxThread_t |
| 274 | + // rtx_os.h - typedef struct osRtxThread_s { } osRtxThread_t |
| 275 | + |
| 276 | + if (!threadId) return; |
| 277 | + |
| 278 | + os_thread_t * tcb = (os_thread_t *) threadId; |
| 279 | + |
| 280 | + uint32_t stackSize = osThreadGetStackSize(threadId); |
| 281 | + uint32_t stackUsed = osThreadGetStackSpace(threadId); |
| 282 | + |
| 283 | + DPL(" stack ( start: "); |
| 284 | + debug_print_pointer(tcb->stack_mem); |
| 285 | + |
| 286 | + DPL(" end: "); |
| 287 | + debug_print_pointer((uint8_t *) tcb->stack_mem + stackSize); |
| 288 | + |
| 289 | + DPL(" size: "); |
| 290 | + debug_print_u32(stackSize); |
| 291 | + |
| 292 | + DPL(" used: "); |
| 293 | + debug_print_u32(stackSize - stackUsed); |
| 294 | + |
| 295 | + DPL(" ) "); |
| 296 | + |
| 297 | + DPL("thread ( id: "); |
| 298 | + debug_print_pointer(threadId); |
| 299 | + |
| 300 | + DPL(" entry: "); |
| 301 | + debug_print_u32(tcb->thread_addr); |
| 302 | + |
| 303 | + DPL(" name: "); |
| 304 | + DPL(osThreadGetName(threadId) ? osThreadGetName(threadId) : "unknown"); |
| 305 | + |
| 306 | + DPL(" )\r\n"); |
| 307 | +} |
| 308 | + |
| 309 | +void print_all_thread_info(void) |
| 310 | +{ |
| 311 | + // Refs: mbed_stats.c - mbed_stats_stack_get_each() |
| 312 | + |
| 313 | + uint32_t threadCount = osThreadGetCount(); |
| 314 | + osThreadId_t threads[threadCount]; |
| 315 | + |
| 316 | + // osThreadId_t * threads = malloc(sizeof(osThreadId_t) * threadCount); |
| 317 | + // MBED_ASSERT(NULL != threads); |
| 318 | + |
| 319 | + memset(threads, 0, threadCount * sizeof(osThreadId_t)); |
| 320 | + |
| 321 | + // This will probably only work if the number of threads remains constant |
| 322 | + // (i.e. the number of thread control blocks remains constant) |
| 323 | + // |
| 324 | + // This is probably the case on a deterministic realtime embedded system |
| 325 | + // with limited SRAM. |
| 326 | + |
| 327 | + osKernelLock(); |
| 328 | + |
| 329 | + threadCount = osThreadEnumerate(threads, threadCount); |
| 330 | + |
| 331 | + for (uint32_t i = 0; i < threadCount; i++) |
| 332 | + { |
| 333 | + // There seems to be a Heisenbug when calling print_thread_info() |
| 334 | + // inside of osKernelLock()! |
| 335 | + |
| 336 | + // This error may appear on the serial console: |
| 337 | + // mbed assertation failed: os_timer->get_tick() == svcRtxKernelGetTickCount(), file: .\mbed-os\rtos\TARGET_CORTEX\mbed_rtx_idle.c |
| 338 | + |
| 339 | + // The RTOS seems to be asserting an idle constraint violation due |
| 340 | + // to the slowness of sending data through the serial port, but it |
| 341 | + // does not happen consistently. |
| 342 | + print_thread_info(threads[i]); |
| 343 | + } |
| 344 | + |
| 345 | + osKernelUnlock(); |
| 346 | + |
| 347 | + // free(threads); |
| 348 | +} |
| 349 | + |
| 350 | +#endif |
| 351 | + |
251 | 352 | void print_current_thread_id(void)
|
252 | 353 | {
|
253 | 354 | DPL("Current thread: ");
|
|
0 commit comments