// // Created by MightyPork on 2017/12/04. // #include "task_msg.h" #include "platform.h" #include "stacksmon.h" #include "hexdump.h" #if USE_STACK_MONITOR struct stackhandle { const char *description; uint8_t *buffer; uint32_t len; }; static uint32_t nextidx = 0; static struct stackhandle stacks[STACK_NUM]; void stackmon_register(const char *description, void *buffer, uint32_t len) { assert_param(nextidx < STACK_NUM); uint8_t *bv = buffer; // This is probably redundant, FreeRTOS does it too. for (uint32_t i = 0; i < len; i++) bv[i] = 0xA5; stacks[nextidx].description = description; stacks[nextidx].buffer = bv; stacks[nextidx].len = len; nextidx++; } void stackmon_dump(void) { PUTS("\r\n\033[1m---- STACK USAGE REPORT ---\033[m\r\n"); for (uint32_t i = 0; i < nextidx; i++) { PRINTF("\033[36m>> %s\033[m @ %p\r\n", stacks[i].description, (void *) stacks[i].buffer); struct stackhandle *stack = &stacks[i]; uint32_t free = 0; if (stack->buffer[0] != 0xA5) { PUTS(" \033[31m!!! OVERRUN !!!\033[m\r\n"); } else { for (uint32_t j = 0; j < stack->len; j++) { if (stack->buffer[j] == 0xA5) { free++; } else { break; } } } uint32_t words = ((stack->len-free)>>2)+1; if (words>stack->len>>2) words=stack->len>>2; PRINTF(" Used: \033[33m%"PRIu32" / %"PRIu32" bytes\033[m (\033[33m%"PRIu32" / %"PRIu32" words\033[m)", (stack->len-free), stack->len, words, stack->len>>2 ); PRINTF(" ~ \033[33m%"PRIu32" %%\033[m\r\n", (stack->len-free)*100/stack->len); } PUTS("\033[36m>> MSG+JOB QUEUE\033[m\r\n"); PRINTF(" Used slots: \033[33m%"PRIu32" / %d\033[m\r\n", msgQueHighWaterMark, RX_QUE_CAPACITY); PRINTF("\033[1m---------------------------\033[m\r\n\r\n"); } void stackmon_check_canaries(void) { for (uint32_t i = 0; i < nextidx; i++) { struct stackhandle *stack = &stacks[i]; if (stack->buffer[0] != 0xA5) { dbg("\r\n\033[31;1m!!!! STACK \"%s\" OVERRUN - CANARY IS DEAD !!!!\033[m", stack->description); stackmon_dump(); trap("ABORT"); } } } #endif