Okundu Omeni
/
wifi-https-ble-sm-uart-atcmd-5-13-1
this is using the mbed os version 5-13-1
Diff: source/mbed_memory_status.cpp
- Revision:
- 92:ec9550034276
- Child:
- 103:7b566b522427
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/mbed_memory_status.cpp Sat Apr 13 14:17:29 2019 +0000 @@ -0,0 +1,488 @@ +/* + 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 +} +