this is using the mbed os version 5-13-1
Diff: source/mbed_memory_status.cpp
- Revision:
- 103:7b566b522427
- Parent:
- 92:ec9550034276
--- a/source/mbed_memory_status.cpp Wed Apr 24 17:34:17 2019 +0000
+++ b/source/mbed_memory_status.cpp Thu May 02 21:50:17 2019 +0000
@@ -1,488 +1,490 @@
-/*
- mbed Memory Status Helper
- Copyright (c) 2017 Max Vilimpoc
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-*/
-
-/**
- * Purpose: Print out thread info and other useful details using
- * only raw serial access.
- *
- * Based on mbed_board.c's error printing functionality, minus
- * pulling in all the printf() code.
- */
-
-// Not great having to pull in all of mbed.h just to get the MBED_VERSION macro,
-// but it's the only way to do it for both pre- and post-5.4 releases
-//
-// If you're only supporting something newer than 5.4, you could use this alone:
-// #include "platform/mbed_version.h"
-//
-// platform/mbed_version.h says:
-// 999999 is default value for development version (master branch)
-
-#include "mbed.h"
-
-// Critical sections header file renamed in mbed OS 5.4 release
-// See: https://github.com/ARMmbed/mbed-os/commit/aff49d8d1e3b5d4dc18286b0510336c36ae9603c
-
-#ifndef MBED_VERSION
-#warning "You're probably using an unsupported version of mbed older than 5.2."
-#endif
-
-#if MBED_VERSION >= 50400
-#include "platform/mbed_critical.h"
-#elif MBED_VERSION >= 50200
-#include "platform/critical.h"
-#endif
-
-#include "platform/mbed_stats.h"
-
-#if !MBED_STACK_STATS_ENABLED
-#warning MBED_STACK_STATS_ENABLED != 1, so there will be no stack usage measurements.
-#endif
-
-#ifndef DEBUG_ISR_STACK_USAGE
-#define DEBUG_ISR_STACK_USAGE 0
-#endif
-
-#ifndef DEBUG_MEMORY_CONTENTS
-#define DEBUG_MEMORY_CONTENTS 0
-#endif
-
-#define OUTPUT_SERIAL 1
-#define OUTPUT_RTT 0
-#define OUTPUT_SWO 0
-
-#if DEBUG_ISR_STACK_USAGE
-#include "compiler_abstraction.h"
-
-// Value is sprayed into all of the ISR stack at boot time.
-static const uint32_t ISR_STACK_CANARY = 0xAFFEC7ED; // AFFECTED
-
-// Refers to linker script defined symbol, may not be available
-// on all platforms.
-extern uint32_t __StackLimit;
-extern uint32_t __StackTop;
-
-void fill_isr_stack_with_canary(void)
-{
- uint32_t * bottom = &__StackLimit;
- uint32_t * top = (uint32_t *) GET_SP();
-
- for (; bottom < top; bottom++)
- {
- *bottom = ISR_STACK_CANARY;
- }
-}
-#endif // DEBUG_ISR_STACK_USAGE
-
-#if OUTPUT_SERIAL && DEVICE_SERIAL
-#include "hal/serial_api.h"
-
-extern int stdio_uart_inited;
-extern serial_t stdio_uart;
-
-static void output_serial_init(void)
-{
- if (!stdio_uart_inited)
- {
- serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
- serial_baud(&stdio_uart, 115200); // This is hard coded.
- }
-}
-
-static void output_serial_print_label(const char * label)
-{
-#if MBED_VERSION < 50902
- // After mbed OS 5.9.2, this locks up the system.
- core_util_critical_section_enter();
-#endif
-
- output_serial_init();
-
- while (*label) serial_putc(&stdio_uart, *label++);
-
-#if MBED_VERSION < 50902
- core_util_critical_section_exit();
-#endif
-}
-#endif // OUTPUT_SERIAL && DEVICE_SERIAL
-
-#if OUTPUT_RTT
-#include "RTT/SEGGER_RTT.h"
-
-enum
-{
- DEFAULT_RTT_UP_BUFFER = 0
-};
-
-static void output_rtt_init(void)
-{
- static int initialized = 0;
-
- if (!initialized)
- {
- SEGGER_RTT_ConfigUpBuffer(DEFAULT_RTT_UP_BUFFER, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_TRIM);
-
- initialized = 1;
- }
-}
-
-static void output_rtt_print_label(const char * label)
-{
- output_rtt_init();
- SEGGER_RTT_WriteString(DEFAULT_RTT_UP_BUFFER, label);
-}
-#endif // OUTPUT_RTT
-
-#if OUTPUT_SWO
-#if defined (NRF52) && !defined (ENABLE_SWO)
- #error "You need to enable SWO using `-D ENABLE_SWO` on the mbed compile command line."
-#endif
-
-#ifdef NRF52
-#include "nrf.h"
-#endif
-
-static void output_swo_init(void)
-{
- static int initialized = 0;
-
- if (!initialized)
- {
- NRF_CLOCK->TRACECONFIG = (NRF_CLOCK->TRACECONFIG & ~CLOCK_TRACECONFIG_TRACEPORTSPEED_Msk) |
- (CLOCK_TRACECONFIG_TRACEPORTSPEED_4MHz << CLOCK_TRACECONFIG_TRACEPORTSPEED_Pos);
-
- ITM->TCR |= 1;
- ITM->TER |= 1;
-
- initialized = 1;
- }
-}
-
-static void output_swo_print_label(const char * label)
-{
- output_swo_init();
- while (*label) ITM_SendChar(*label++);
-}
-#endif // OUTPUT_SWO
-
-static void nway_print_label(const char * label)
-{
-#if OUTPUT_SERIAL
- output_serial_print_label(label);
-#endif
-
-#if OUTPUT_RTT
- output_rtt_print_label(label);
-#endif
-
-#if OUTPUT_SWO
- output_swo_print_label(label);
-#endif
-}
-
-static const char HEX[] = "0123456789ABCDEF";
-
-static void debug_print_u32(uint32_t u32)
-{
- char output[9] = {0};
-
- // Always printed as big endian.
- output[0] = HEX[(((uint32_t) u32 & 0xf0000000) >> 28)];
- output[1] = HEX[(((uint32_t) u32 & 0x0f000000) >> 24)];
- output[2] = HEX[(((uint32_t) u32 & 0x00f00000) >> 20)];
- output[3] = HEX[(((uint32_t) u32 & 0x000f0000) >> 16)];
- output[4] = HEX[(((uint32_t) u32 & 0x0000f000) >> 12)];
- output[5] = HEX[(((uint32_t) u32 & 0x00000f00) >> 8)];
- output[6] = HEX[(((uint32_t) u32 & 0x000000f0) >> 4)];
- output[7] = HEX[(((uint32_t) u32 & 0x0000000f) >> 0)];
-
- nway_print_label(output);
-}
-
-static void debug_print_pointer(const void * pointer)
-{
- debug_print_u32((uint32_t) pointer);
-}
-
-#define DPL(X) nway_print_label((X))
-
-#if (defined (MBED_CONF_RTOS_PRESENT) && (MBED_CONF_RTOS_PRESENT != 0))
-#include "cmsis_os.h"
-
-// cmsis_os.h provides some useful defines:
-//
-// For mbed OS 5.4 and lower, osCMSIS == 0x10002U (see: rtos/rtx/TARGET_CORTEX_M)
-// For mbed OS 5.5 and higher, osCMSIS == 0x20001U (see: rtos/TARGET_CORTEX/rtx{4|5})
-//
-// Starting in mbed OS 5.5, a new RTOS layer was introduced with a different API.
-
-#if (osCMSIS < 0x20000U)
- // Temporarily #undef NULL or the compiler complains about previous def.
- #undef NULL
- #include "rt_TypeDef.h"
-#else
- #include "rtx_lib.h"
- // #include <stdlib.h> // Include if you need malloc() / free() below. (probably better for non-C99 compilers)
-#endif
-
-#if (osCMSIS < 0x20000U)
-
-// No public forward declaration for this.
-extern "C" P_TCB rt_tid2ptcb (osThreadId thread_id);
-
-static void print_thread_info(osThreadId threadId)
-{
- if (!threadId) return;
-
- osEvent event;
-
- P_TCB tcb = rt_tid2ptcb(threadId);
-
- DPL(" stack ( start: ");
- debug_print_pointer(tcb->stack);
-
- event = _osThreadGetInfo(threadId, osThreadInfoStackSize);
-
- DPL(" end: ");
- debug_print_pointer(((uint8_t *) tcb->stack + event.value.v)); // (tcb->priv_stack)));
-
- DPL(" size: ");
- debug_print_u32(event.value.v);
-
- event = _osThreadGetInfo(threadId, osThreadInfoStackMax);
- DPL(" used: ");
- debug_print_u32(event.value.v);
-
-
- DPL(" ) ");
-
- DPL("thread ( id: ");
- debug_print_pointer(threadId);
-
- event = _osThreadGetInfo(threadId, osThreadInfoEntry);
- DPL(" entry: ");
- debug_print_pointer(event.value.p);
-
- DPL(" )\r\n");
-}
-
-void print_all_thread_info(void)
-{
- osThreadEnumId enumId = _osThreadsEnumStart();
- osThreadId threadId = (osThreadId) NULL; // Can't use nullptr yet because mbed doesn't support C++11.
-
- while ((threadId = _osThreadEnumNext(enumId)))
- {
- print_thread_info(threadId);
- }
-
- _osThreadEnumFree(enumId);
-}
-
-#else
-
-static void print_thread_info(osThreadId threadId)
-{
- // Refs: rtx_lib.h - #define os_thread_t osRtxThread_t
- // rtx_os.h - typedef struct osRtxThread_s { } osRtxThread_t
-
- if (!threadId) return;
-
- os_thread_t * tcb = (os_thread_t *) threadId;
-
- uint32_t stackSize = osThreadGetStackSize(threadId);
- uint32_t stackUsed = osThreadGetStackSpace(threadId);
-
- DPL(" stack ( start: ");
- debug_print_pointer(tcb->stack_mem);
-
- DPL(" end: ");
- debug_print_pointer((uint8_t *) tcb->stack_mem + stackSize);
-
- DPL(" size: ");
- debug_print_u32(stackSize);
-
- DPL(" used: ");
- debug_print_u32(stackSize - stackUsed);
-
- DPL(" ) ");
-
- DPL("thread ( id: ");
- debug_print_pointer(threadId);
-
- DPL(" entry: ");
- debug_print_u32(tcb->thread_addr);
-
- DPL(" name: ");
- DPL(osThreadGetName(threadId) ? osThreadGetName(threadId) : "unknown");
-
- DPL(" )\r\n");
-}
-
-void print_all_thread_info(void)
-{
- // Refs: mbed_stats.c - mbed_stats_stack_get_each()
-
- uint32_t threadCount = osThreadGetCount();
- osThreadId_t threads[threadCount]; // g++ will throw a -Wvla on this, but it is likely ok.
-
- // osThreadId_t * threads = malloc(sizeof(osThreadId_t) * threadCount);
- // MBED_ASSERT(NULL != threads);
-
- memset(threads, 0, threadCount * sizeof(osThreadId_t));
-
- // This will probably only work if the number of threads remains constant
- // (i.e. the number of thread control blocks remains constant)
- //
- // This is probably the case on a deterministic realtime embedded system
- // with limited SRAM.
-
- osKernelLock();
-
- threadCount = osThreadEnumerate(threads, threadCount);
-
- for (uint32_t i = 0; i < threadCount; i++)
- {
- // There seems to be a Heisenbug when calling print_thread_info()
- // inside of osKernelLock()!
-
- // This error may appear on the serial console:
- // mbed assertation failed: os_timer->get_tick() == svcRtxKernelGetTickCount(), file: .\mbed-os\rtos\TARGET_CORTEX\mbed_rtx_idle.c
-
- // The RTOS seems to be asserting an idle constraint violation due
- // to the slowness of sending data through the serial port, but it
- // does not happen consistently.
- print_thread_info(threads[i]);
- }
-
- osKernelUnlock();
-
- // free(threads);
-}
-
-#endif
-
-void print_current_thread_id(void)
-{
- DPL("Current thread: ");
- debug_print_pointer(osThreadGetId());
- DPL("\r\n");
-}
-#endif // MBED_CONF_RTOS_PRESENT
-
-#if DEBUG_MEMORY_CONTENTS
-static void print_memory_contents(const uint32_t * start, const uint32_t * end)
-{
- uint8_t line = 0;
-
- for (; start < end; start++)
- {
- if (0 == line)
- {
- debug_print_pointer(start);
- DPL(": ");
- }
-
- debug_print_u32(*start);
-
- line++;
-
- if (16 == line)
- {
- DPL("\r\n");
- line = 0;
- }
- }
-}
-#endif
-
-extern uint32_t mbed_stack_isr_size;
-
-#if DEBUG_ISR_STACK_USAGE
-uint32_t calculate_isr_stack_usage(void)
-{
- for (const uint32_t * stack = &__StackLimit; stack < &__StackTop; stack++)
- {
- if (*stack != ISR_STACK_CANARY)
- {
- return (uint32_t) &__StackTop - (uint32_t) stack;
- }
- }
-
- return mbed_stack_isr_size;
-}
-#endif
-
-void print_heap_and_isr_stack_info(void)
-{
- extern unsigned char * mbed_heap_start;
- extern uint32_t mbed_heap_size;
-
- extern unsigned char * mbed_stack_isr_start;
-
- mbed_stats_heap_t heap_stats;
-
- mbed_stats_heap_get(&heap_stats);
-
- DPL(" heap ( start: ");
- debug_print_pointer(mbed_heap_start);
-
- DPL(" end: ");
- debug_print_pointer(mbed_heap_start + mbed_heap_size);
-
- DPL(" size: ");
- debug_print_u32(mbed_heap_size);
-
- DPL(" used: ");
- debug_print_u32(heap_stats.max_size);
-
- DPL(" ) alloc ( ok: ");
- debug_print_u32(heap_stats.alloc_cnt);
-
- DPL(" fail: ");
- debug_print_u32(heap_stats.alloc_fail_cnt);
-
- DPL(" )\r\n");
-
- DPL("isr_stack ( start: ");
- debug_print_pointer(mbed_stack_isr_start);
-
- DPL(" end: ");
- debug_print_pointer(mbed_stack_isr_start + mbed_stack_isr_size);
-
- DPL(" size: ");
- debug_print_u32(mbed_stack_isr_size);
-
-#if DEBUG_ISR_STACK_USAGE
- DPL(" used: ");
- debug_print_u32(calculate_isr_stack_usage());
-#endif
-
- DPL(" )\r\n");
-
-#if DEBUG_MEMORY_CONTENTS
- // Print ISR stack contents.
- print_memory_contents(&__StackLimit, &__StackTop);
-#endif
-}
+/*
+ mbed Memory Status Helper
+ Copyright (c) 2017 Max Vilimpoc
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+/**
+ * Purpose: Print out thread info and other useful details using
+ * only raw serial access.
+ *
+ * Based on mbed_board.c's error printing functionality, minus
+ * pulling in all the printf() code.
+ */
+
+// Not great having to pull in all of mbed.h just to get the MBED_VERSION macro,
+// but it's the only way to do it for both pre- and post-5.4 releases
+//
+// If you're only supporting something newer than 5.4, you could use this alone:
+// #include "platform/mbed_version.h"
+//
+// platform/mbed_version.h says:
+// 999999 is default value for development version (master branch)
+
+#include "mbed.h"
+
+// Critical sections header file renamed in mbed OS 5.4 release
+// See: https://github.com/ARMmbed/mbed-os/commit/aff49d8d1e3b5d4dc18286b0510336c36ae9603c
+
+#ifndef MBED_VERSION
+#warning "You're probably using an unsupported version of mbed older than 5.2."
+#endif
+
+#if MBED_VERSION >= 50400
+#include "platform/mbed_critical.h"
+#elif MBED_VERSION >= 50200
+#include "platform/critical.h"
+#endif
+
+#include "platform/mbed_stats.h"
+
+#if !MBED_STACK_STATS_ENABLED
+#warning MBED_STACK_STATS_ENABLED != 1, so there will be no stack usage measurements.
+#endif
+
+#ifndef DEBUG_ISR_STACK_USAGE
+#define DEBUG_ISR_STACK_USAGE 0
+#endif
+
+#ifndef DEBUG_MEMORY_CONTENTS
+#define DEBUG_MEMORY_CONTENTS 0
+#endif
+
+#define OUTPUT_SERIAL 1
+#define OUTPUT_RTT 0
+#define OUTPUT_SWO 0
+
+#if DEBUG_ISR_STACK_USAGE
+#include "compiler_abstraction.h"
+
+// Value is sprayed into all of the ISR stack at boot time.
+static const uint32_t ISR_STACK_CANARY = 0xAFFEC7ED; // AFFECTED
+
+// Refers to linker script defined symbol, may not be available
+// on all platforms.
+extern uint32_t __StackLimit;
+extern uint32_t __StackTop;
+
+void fill_isr_stack_with_canary(void)
+{
+ uint32_t * bottom = &__StackLimit;
+ uint32_t * top = (uint32_t *) GET_SP();
+
+ for (; bottom < top; bottom++)
+ {
+ *bottom = ISR_STACK_CANARY;
+ }
+}
+#endif // DEBUG_ISR_STACK_USAGE
+
+#if OUTPUT_SERIAL && DEVICE_SERIAL
+#include "hal/serial_api.h"
+
+extern int stdio_uart_inited;
+extern serial_t stdio_uart;
+
+static void output_serial_init(void)
+{
+ if (!stdio_uart_inited)
+ {
+ serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
+ serial_baud(&stdio_uart, 115200); // This is hard coded.
+ }
+}
+
+static void output_serial_print_label(const char * label)
+{
+#if MBED_VERSION < 50902
+ // After mbed OS 5.9.2, this locks up the system.
+ core_util_critical_section_enter();
+#endif
+
+ output_serial_init();
+
+ while (*label) serial_putc(&stdio_uart, *label++);
+
+#if MBED_VERSION < 50902
+ core_util_critical_section_exit();
+#endif
+}
+#endif // OUTPUT_SERIAL && DEVICE_SERIAL
+
+#if OUTPUT_RTT
+#include "RTT/SEGGER_RTT.h"
+
+enum
+{
+ DEFAULT_RTT_UP_BUFFER = 0
+};
+
+static void output_rtt_init(void)
+{
+ static int initialized = 0;
+
+ if (!initialized)
+ {
+ SEGGER_RTT_ConfigUpBuffer(DEFAULT_RTT_UP_BUFFER, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_TRIM);
+
+ initialized = 1;
+ }
+}
+
+static void output_rtt_print_label(const char * label)
+{
+ output_rtt_init();
+ SEGGER_RTT_WriteString(DEFAULT_RTT_UP_BUFFER, label);
+}
+#endif // OUTPUT_RTT
+
+#if OUTPUT_SWO
+#if defined (NRF52) && !defined (ENABLE_SWO)
+ #error "You need to enable SWO using `-D ENABLE_SWO` on the mbed compile command line."
+#endif
+
+#ifdef NRF52
+#include "nrf.h"
+#endif
+
+static void output_swo_init(void)
+{
+ static int initialized = 0;
+
+ if (!initialized)
+ {
+ NRF_CLOCK->TRACECONFIG = (NRF_CLOCK->TRACECONFIG & ~CLOCK_TRACECONFIG_TRACEPORTSPEED_Msk) |
+ (CLOCK_TRACECONFIG_TRACEPORTSPEED_4MHz << CLOCK_TRACECONFIG_TRACEPORTSPEED_Pos);
+
+ ITM->TCR |= 1;
+ ITM->TER |= 1;
+
+ initialized = 1;
+ }
+}
+
+static void output_swo_print_label(const char * label)
+{
+ output_swo_init();
+ while (*label) ITM_SendChar(*label++);
+}
+#endif // OUTPUT_SWO
+
+static void nway_print_label(const char * label)
+{
+#if OUTPUT_SERIAL
+ output_serial_print_label(label);
+#endif
+
+#if OUTPUT_RTT
+ output_rtt_print_label(label);
+#endif
+
+#if OUTPUT_SWO
+ output_swo_print_label(label);
+#endif
+}
+
+static const char HEX[] = "0123456789ABCDEF";
+
+static void debug_print_u32(uint32_t u32)
+{
+ char output[9] = {0};
+
+ // Always printed as big endian.
+ output[0] = HEX[(((uint32_t) u32 & 0xf0000000) >> 28)];
+ output[1] = HEX[(((uint32_t) u32 & 0x0f000000) >> 24)];
+ output[2] = HEX[(((uint32_t) u32 & 0x00f00000) >> 20)];
+ output[3] = HEX[(((uint32_t) u32 & 0x000f0000) >> 16)];
+ output[4] = HEX[(((uint32_t) u32 & 0x0000f000) >> 12)];
+ output[5] = HEX[(((uint32_t) u32 & 0x00000f00) >> 8)];
+ output[6] = HEX[(((uint32_t) u32 & 0x000000f0) >> 4)];
+ output[7] = HEX[(((uint32_t) u32 & 0x0000000f) >> 0)];
+
+ nway_print_label(output);
+}
+
+static void debug_print_pointer(const void * pointer)
+{
+ debug_print_u32((uint32_t) pointer);
+}
+
+#define DPL(X) nway_print_label((X))
+
+#if (defined (MBED_CONF_RTOS_PRESENT) && (MBED_CONF_RTOS_PRESENT != 0))
+#include "cmsis_os.h"
+
+// cmsis_os.h provides some useful defines:
+//
+// For mbed OS 5.4 and lower, osCMSIS == 0x10002U (see: rtos/rtx/TARGET_CORTEX_M)
+// For mbed OS 5.5 and higher, osCMSIS == 0x20001U (see: rtos/TARGET_CORTEX/rtx{4|5})
+//
+// Starting in mbed OS 5.5, a new RTOS layer was introduced with a different API.
+#if (osCMSIS < 0x20000U)
+ // Temporarily #undef NULL or the compiler complains about previous def.
+ #undef NULL
+ #include "rt_TypeDef.h"
+#else
+ #include "rtx_lib.h"
+ // #include <stdlib.h> // Include if you need malloc() / free() below. (probably better for non-C99 compilers)
+#endif
+
+#if (osCMSIS < 0x20000U)
+
+// No public forward declaration for this.
+extern "C" P_TCB rt_tid2ptcb (osThreadId thread_id);
+
+static void print_thread_info(osThreadId threadId)
+{
+ if (!threadId) return;
+
+ osEvent event;
+
+ P_TCB tcb = rt_tid2ptcb(threadId);
+
+ DPL(" stack ( start: ");
+ debug_print_pointer(tcb->stack);
+
+ event = _osThreadGetInfo(threadId, osThreadInfoStackSize);
+
+ DPL(" end: ");
+ debug_print_pointer(((uint8_t *) tcb->stack + event.value.v)); // (tcb->priv_stack)));
+
+ DPL(" size: ");
+ debug_print_u32(event.value.v);
+
+ event = _osThreadGetInfo(threadId, osThreadInfoStackMax);
+ DPL(" used: ");
+ debug_print_u32(event.value.v);
+
+
+ DPL(" ) ");
+
+ DPL("thread ( id: ");
+ debug_print_pointer(threadId);
+
+ event = _osThreadGetInfo(threadId, osThreadInfoEntry);
+ DPL(" entry: ");
+ debug_print_pointer(event.value.p);
+
+ DPL(" )\r\n");
+}
+
+void print_all_thread_info(void)
+{
+ osThreadEnumId enumId = _osThreadsEnumStart();
+ osThreadId threadId = (osThreadId) NULL; // Can't use nullptr yet because mbed doesn't support C++11.
+
+ while ((threadId = _osThreadEnumNext(enumId)))
+ {
+ print_thread_info(threadId);
+ }
+
+ _osThreadEnumFree(enumId);
+}
+
+#else
+
+static void print_thread_info(osThreadId threadId)
+{
+ // Refs: rtx_lib.h - #define os_thread_t osRtxThread_t
+ // rtx_os.h - typedef struct osRtxThread_s { } osRtxThread_t
+
+ if (!threadId) return;
+
+ os_thread_t * tcb = (os_thread_t *) threadId;
+
+ uint32_t stackSize = osThreadGetStackSize(threadId);
+ uint32_t stackUsed = osThreadGetStackSpace(threadId);
+
+ DPL(" stack ( start: ");
+ debug_print_pointer(tcb->stack_mem);
+
+ DPL(" end: ");
+ debug_print_pointer((uint8_t *) tcb->stack_mem + stackSize);
+
+ DPL(" size: ");
+ debug_print_u32(stackSize);
+
+ DPL(" used: ");
+ debug_print_u32(stackSize - stackUsed);
+
+ DPL(" ) ");
+
+ DPL("thread ( id: ");
+ debug_print_pointer(threadId);
+
+ DPL(" entry: ");
+ debug_print_u32(tcb->thread_addr);
+
+ DPL(" name: ");
+ DPL(osThreadGetName(threadId) ? osThreadGetName(threadId) : "unknown");
+
+ DPL(" )\r\n");
+}
+
+void print_all_thread_info(void)
+{
+ // Refs: mbed_stats.c - mbed_stats_stack_get_each()
+
+ uint32_t threadCount = osThreadGetCount();
+ osThreadId_t threads[threadCount]; // g++ will throw a -Wvla on this, but it is likely ok.
+
+ // osThreadId_t * threads = malloc(sizeof(osThreadId_t) * threadCount);
+ // MBED_ASSERT(NULL != threads);
+
+ memset(threads, 0, threadCount * sizeof(osThreadId_t));
+
+ // This will probably only work if the number of threads remains constant
+ // (i.e. the number of thread control blocks remains constant)
+ //
+ // This is probably the case on a deterministic realtime embedded system
+ // with limited SRAM.
+
+ osKernelLock();
+
+ threadCount = osThreadEnumerate(threads, threadCount);
+
+ for (uint32_t i = 0; i < threadCount; i++)
+ {
+ // There seems to be a Heisenbug when calling print_thread_info()
+ // inside of osKernelLock()!
+
+ // This error may appear on the serial console:
+ // mbed assertation failed: os_timer->get_tick() == svcRtxKernelGetTickCount(), file: .\mbed-os\rtos\TARGET_CORTEX\mbed_rtx_idle.c
+
+ // The RTOS seems to be asserting an idle constraint violation due
+ // to the slowness of sending data through the serial port, but it
+ // does not happen consistently.
+ print_thread_info(threads[i]);
+ }
+
+ osKernelUnlock();
+
+ // free(threads);
+}
+
+#endif
+
+void print_current_thread_id(void)
+{
+ DPL("Current thread: ");
+ debug_print_pointer(osThreadGetId());
+ DPL("\r\n");
+}
+#endif // MBED_CONF_RTOS_PRESENT
+
+#if DEBUG_MEMORY_CONTENTS
+static void print_memory_contents(const uint32_t * start, const uint32_t * end)
+{
+ uint8_t line = 0;
+
+ for (; start < end; start++)
+ {
+ if (0 == line)
+ {
+ debug_print_pointer(start);
+ DPL(": ");
+ }
+
+ debug_print_u32(*start);
+
+ line++;
+
+ if (16 == line)
+ {
+ DPL("\r\n");
+ line = 0;
+ }
+ }
+}
+#endif
+
+extern uint32_t mbed_stack_isr_size;
+
+#if DEBUG_ISR_STACK_USAGE
+uint32_t calculate_isr_stack_usage(void)
+{
+ for (const uint32_t * stack = &__StackLimit; stack < &__StackTop; stack++)
+ {
+ if (*stack != ISR_STACK_CANARY)
+ {
+ return (uint32_t) &__StackTop - (uint32_t) stack;
+ }
+ }
+
+ return mbed_stack_isr_size;
+}
+#endif
+
+void print_heap_and_isr_stack_info(void)
+{
+#ifdef ENABLE_MEMORY_CHECKS
+ extern unsigned char * mbed_heap_start;
+ extern uint32_t mbed_heap_size;
+
+ extern unsigned char * mbed_stack_isr_start;
+
+ mbed_stats_heap_t heap_stats;
+
+ mbed_stats_heap_get(&heap_stats);
+
+ DPL(" heap ( start: ");
+ debug_print_pointer(mbed_heap_start);
+
+ DPL(" end: ");
+ debug_print_pointer(mbed_heap_start + mbed_heap_size);
+
+ DPL(" size: ");
+ debug_print_u32(mbed_heap_size);
+
+ DPL(" used: ");
+ debug_print_u32(heap_stats.max_size);
+
+ DPL(" ) alloc ( ok: ");
+ debug_print_u32(heap_stats.alloc_cnt);
+
+ DPL(" fail: ");
+ debug_print_u32(heap_stats.alloc_fail_cnt);
+
+ DPL(" )\r\n");
+
+ DPL("isr_stack ( start: ");
+ debug_print_pointer(mbed_stack_isr_start);
+
+ DPL(" end: ");
+ debug_print_pointer(mbed_stack_isr_start + mbed_stack_isr_size);
+
+ DPL(" size: ");
+ debug_print_u32(mbed_stack_isr_size);
+
+#if DEBUG_ISR_STACK_USAGE
+ DPL(" used: ");
+ debug_print_u32(calculate_isr_stack_usage());
+#endif
+
+ DPL(" )\r\n");
+
+#if DEBUG_MEMORY_CONTENTS
+ // Print ISR stack contents.
+ print_memory_contents(&__StackLimit, &__StackTop);
+#endif
+#endif
+}
+