mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
FreeRTOS: temporary solution for memory canaries and memory debug
1. This is just a temporary solution, it will be removed when umm_malloc is ready 2. Support memory canaries mechanism 2. Add debug code to show allocated memory info
This commit is contained in:
parent
1a6e63feef
commit
b21d2dfa6b
@ -158,6 +158,12 @@ config FREERTOS_BREAK_ON_SCHEDULER_START_JTAG
|
|||||||
If JTAG/OCD is connected, stop execution when the scheduler is started and the first
|
If JTAG/OCD is connected, stop execution when the scheduler is started and the first
|
||||||
task is executed.
|
task is executed.
|
||||||
|
|
||||||
|
menuconfig ENABLE_MEMORY_DEBUG
|
||||||
|
bool "Enable heap memory debug"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable this option to show malloc heap block and memory crash detect
|
||||||
|
|
||||||
menuconfig FREERTOS_DEBUG_INTERNALS
|
menuconfig FREERTOS_DEBUG_INTERNALS
|
||||||
bool "Debug FreeRTOS internals"
|
bool "Debug FreeRTOS internals"
|
||||||
default n
|
default n
|
||||||
|
@ -132,6 +132,7 @@ task.h is included from an application file. */
|
|||||||
|
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "heap_regions_debug.h"
|
||||||
|
|
||||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
@ -171,7 +172,7 @@ static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
|
|||||||
|
|
||||||
/* The size of the structure placed at the beginning of each allocated memory
|
/* The size of the structure placed at the beginning of each allocated memory
|
||||||
block must by correctly byte aligned. */
|
block must by correctly byte aligned. */
|
||||||
static const uint32_t uxHeapStructSize = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
|
static const uint32_t uxHeapStructSize = ( ( sizeof ( BlockLink_t ) + BLOCK_HEAD_LEN + BLOCK_TAIL_LEN + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
|
||||||
|
|
||||||
/* Create a couple of list links to mark the start and end of the list. */
|
/* Create a couple of list links to mark the start and end of the list. */
|
||||||
static BlockLink_t xStart, *pxEnd = NULL;
|
static BlockLink_t xStart, *pxEnd = NULL;
|
||||||
@ -238,6 +239,13 @@ void *pvReturn = NULL;
|
|||||||
while( ( ( pxBlock->xTag != tag ) || ( pxBlock->xBlockSize < xWantedSize ) ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
while( ( ( pxBlock->xTag != tag ) || ( pxBlock->xBlockSize < xWantedSize ) ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||||
{
|
{
|
||||||
// ets_printf("Block %x -> %x\n", (uint32_t)pxBlock, (uint32_t)pxBlock->pxNextFreeBlock);
|
// ets_printf("Block %x -> %x\n", (uint32_t)pxBlock, (uint32_t)pxBlock->pxNextFreeBlock);
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
{
|
||||||
|
mem_check_block(pxBlock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pxPreviousBlock = pxBlock;
|
pxPreviousBlock = pxBlock;
|
||||||
pxBlock = pxBlock->pxNextFreeBlock;
|
pxBlock = pxBlock->pxNextFreeBlock;
|
||||||
}
|
}
|
||||||
@ -248,7 +256,7 @@ void *pvReturn = NULL;
|
|||||||
{
|
{
|
||||||
/* Return the memory space pointed to - jumping over the
|
/* Return the memory space pointed to - jumping over the
|
||||||
BlockLink_t structure at its start. */
|
BlockLink_t structure at its start. */
|
||||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize );
|
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize - BLOCK_TAIL_LEN - BLOCK_HEAD_LEN);
|
||||||
|
|
||||||
/* This block is being returned for use so must be taken out
|
/* This block is being returned for use so must be taken out
|
||||||
of the list of free blocks. */
|
of the list of free blocks. */
|
||||||
@ -256,13 +264,14 @@ void *pvReturn = NULL;
|
|||||||
|
|
||||||
/* If the block is larger than required it can be split into
|
/* If the block is larger than required it can be split into
|
||||||
two. */
|
two. */
|
||||||
|
|
||||||
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
||||||
{
|
{
|
||||||
/* This block is to be split into two. Create a new
|
/* This block is to be split into two. Create a new
|
||||||
block following the number of bytes requested. The void
|
block following the number of bytes requested. The void
|
||||||
cast is used to prevent byte alignment warnings from the
|
cast is used to prevent byte alignment warnings from the
|
||||||
compiler. */
|
compiler. */
|
||||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize);
|
||||||
|
|
||||||
/* Calculate the sizes of two blocks split from the
|
/* Calculate the sizes of two blocks split from the
|
||||||
single block. */
|
single block. */
|
||||||
@ -270,6 +279,13 @@ void *pvReturn = NULL;
|
|||||||
pxNewBlockLink->xTag = tag;
|
pxNewBlockLink->xTag = tag;
|
||||||
pxBlock->xBlockSize = xWantedSize;
|
pxBlock->xBlockSize = xWantedSize;
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
{
|
||||||
|
mem_init_dog(pxNewBlockLink);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Insert the new block into the list of free blocks. */
|
/* Insert the new block into the list of free blocks. */
|
||||||
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
|
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
|
||||||
}
|
}
|
||||||
@ -293,6 +309,13 @@ void *pvReturn = NULL;
|
|||||||
by the application and has no "next" block. */
|
by the application and has no "next" block. */
|
||||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||||
pxBlock->pxNextFreeBlock = NULL;
|
pxBlock->pxNextFreeBlock = NULL;
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
{
|
||||||
|
mem_init_dog(pxBlock);
|
||||||
|
mem_malloc_block(pxBlock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -340,11 +363,20 @@ BlockLink_t *pxLink;
|
|||||||
{
|
{
|
||||||
/* The memory being freed will have an BlockLink_t structure immediately
|
/* The memory being freed will have an BlockLink_t structure immediately
|
||||||
before it. */
|
before it. */
|
||||||
puc -= uxHeapStructSize;
|
puc -= (uxHeapStructSize - BLOCK_TAIL_LEN - BLOCK_HEAD_LEN) ;
|
||||||
|
|
||||||
/* This casting is to keep the compiler from issuing warnings. */
|
/* This casting is to keep the compiler from issuing warnings. */
|
||||||
pxLink = ( void * ) puc;
|
pxLink = ( void * ) puc;
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
{
|
||||||
|
taskENTER_CRITICAL(&xMallocMutex);
|
||||||
|
mem_check_block(pxLink);
|
||||||
|
mem_free_block(pxLink);
|
||||||
|
taskEXIT_CRITICAL(&xMallocMutex);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check the block is actually allocated. */
|
/* Check the block is actually allocated. */
|
||||||
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||||
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||||
@ -497,7 +529,7 @@ const HeapRegionTagged_t *pxHeapRegion;
|
|||||||
{
|
{
|
||||||
/* xStart is used to hold a pointer to the first item in the list of
|
/* xStart is used to hold a pointer to the first item in the list of
|
||||||
free blocks. The void cast is used to prevent compiler warnings. */
|
free blocks. The void cast is used to prevent compiler warnings. */
|
||||||
xStart.pxNextFreeBlock = ( BlockLink_t * ) pucAlignedHeap;
|
xStart.pxNextFreeBlock = ( BlockLink_t * ) (pucAlignedHeap + BLOCK_HEAD_LEN);
|
||||||
xStart.xBlockSize = ( size_t ) 0;
|
xStart.xBlockSize = ( size_t ) 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -519,7 +551,7 @@ const HeapRegionTagged_t *pxHeapRegion;
|
|||||||
ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalRegionSize;
|
ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalRegionSize;
|
||||||
ulAddress -= uxHeapStructSize;
|
ulAddress -= uxHeapStructSize;
|
||||||
ulAddress &= ~portBYTE_ALIGNMENT_MASK;
|
ulAddress &= ~portBYTE_ALIGNMENT_MASK;
|
||||||
pxEnd = ( BlockLink_t * ) ulAddress;
|
pxEnd = ( BlockLink_t * ) (ulAddress + BLOCK_HEAD_LEN);
|
||||||
pxEnd->xBlockSize = 0;
|
pxEnd->xBlockSize = 0;
|
||||||
pxEnd->pxNextFreeBlock = NULL;
|
pxEnd->pxNextFreeBlock = NULL;
|
||||||
pxEnd->xTag = -1;
|
pxEnd->xTag = -1;
|
||||||
@ -527,8 +559,8 @@ const HeapRegionTagged_t *pxHeapRegion;
|
|||||||
/* To start with there is a single free block in this region that is
|
/* To start with there is a single free block in this region that is
|
||||||
sized to take up the entire heap region minus the space taken by the
|
sized to take up the entire heap region minus the space taken by the
|
||||||
free block structure. */
|
free block structure. */
|
||||||
pxFirstFreeBlockInRegion = ( BlockLink_t * ) pucAlignedHeap;
|
pxFirstFreeBlockInRegion = ( BlockLink_t * ) (pucAlignedHeap + BLOCK_HEAD_LEN);
|
||||||
pxFirstFreeBlockInRegion->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlockInRegion;
|
pxFirstFreeBlockInRegion->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlockInRegion + BLOCK_HEAD_LEN;
|
||||||
pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;
|
pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;
|
||||||
pxFirstFreeBlockInRegion->xTag=pxHeapRegion->xTag;
|
pxFirstFreeBlockInRegion->xTag=pxHeapRegion->xTag;
|
||||||
|
|
||||||
@ -545,6 +577,13 @@ const HeapRegionTagged_t *pxHeapRegion;
|
|||||||
xDefinedRegions++;
|
xDefinedRegions++;
|
||||||
xRegIdx++;
|
xRegIdx++;
|
||||||
pxHeapRegion = &( pxHeapRegions[ xRegIdx ] );
|
pxHeapRegion = &( pxHeapRegions[ xRegIdx ] );
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
{
|
||||||
|
mem_init_dog(pxFirstFreeBlockInRegion);
|
||||||
|
mem_init_dog(pxEnd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
|
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
|
||||||
@ -555,5 +594,12 @@ const HeapRegionTagged_t *pxHeapRegion;
|
|||||||
|
|
||||||
/* Work out the position of the top bit in a size_t variable. */
|
/* Work out the position of the top bit in a size_t variable. */
|
||||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
|
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
{
|
||||||
|
mem_debug_init(uxHeapStructSize, &xStart, pxEnd, &xMallocMutex, xBlockAllocatedBit);
|
||||||
|
mem_check_all(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
193
components/freertos/heap_regions_debug.c
Normal file
193
components/freertos/heap_regions_debug.c
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#include "heap_regions_debug.h"
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
|
||||||
|
static os_block_t g_malloc_list, *g_free_list=NULL, *g_end;
|
||||||
|
static size_t g_heap_struct_size;
|
||||||
|
static mem_dbg_ctl_t g_mem_dbg;
|
||||||
|
char g_mem_print = 0;
|
||||||
|
static portMUX_TYPE *g_malloc_mutex = NULL;
|
||||||
|
static unsigned int g_alloc_bit;
|
||||||
|
#define MEM_DEBUG(...)
|
||||||
|
|
||||||
|
void mem_debug_init(size_t size, void *start, void *end, portMUX_TYPE *mutex, unsigned int alloc_bit)
|
||||||
|
{
|
||||||
|
MEM_DEBUG("size=%d start=%p end=%p mutex=%p alloc_bit=0x%x\n", size, start, end, mutex, alloc_bit);
|
||||||
|
memset(&g_mem_dbg, 0, sizeof(g_mem_dbg));
|
||||||
|
memset(&g_malloc_list, 0, sizeof(g_malloc_list));
|
||||||
|
g_malloc_mutex = mutex;
|
||||||
|
g_heap_struct_size = size;
|
||||||
|
g_free_list = start;
|
||||||
|
g_end = end;
|
||||||
|
g_alloc_bit = alloc_bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_debug_push(char type, void *addr)
|
||||||
|
{
|
||||||
|
os_block_t *b = (os_block_t*)addr;
|
||||||
|
debug_block_t *debug_b = DEBUG_BLOCK(b);
|
||||||
|
|
||||||
|
MEM_DEBUG("push type=%d addr=%p\n", type, addr);
|
||||||
|
if (g_mem_print){
|
||||||
|
if (type == DEBUG_TYPE_MALLOC){
|
||||||
|
ets_printf("task=%s t=%s s=%u a=%p\n", debug_b->head.task?debug_b->head.task:"", type==DEBUG_TYPE_MALLOC?"m":"f", b->size&(~g_alloc_bit), addr);
|
||||||
|
} else {
|
||||||
|
ets_printf("task=%s t=%s s=%u a=%p\n", debug_b->head.task?debug_b->head.task:"", type==DEBUG_TYPE_MALLOC?"m":"f", b->size&(~g_alloc_bit), addr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mem_dbg_info_t *info = &g_mem_dbg.info[g_mem_dbg.cnt%DEBUG_MAX_INFO_NUM];
|
||||||
|
|
||||||
|
info->addr = addr;
|
||||||
|
info->type = type;
|
||||||
|
info->time = g_mem_dbg.cnt;
|
||||||
|
g_mem_dbg.cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_debug_malloc_show(void)
|
||||||
|
{
|
||||||
|
os_block_t *b = g_malloc_list.next;
|
||||||
|
debug_block_t *d;
|
||||||
|
|
||||||
|
taskENTER_CRITICAL(g_malloc_mutex);
|
||||||
|
while (b){
|
||||||
|
d = DEBUG_BLOCK(b);
|
||||||
|
d->head.task[3] = '\0';
|
||||||
|
ets_printf("t=%s s=%u a=%p\n", d->head.task?d->head.task:"", b->size&(~g_alloc_bit), b);
|
||||||
|
b = b->next;
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL(g_malloc_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_debug_show(void)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if (!g_mem_print) return;
|
||||||
|
|
||||||
|
for (i=0; i<DEBUG_MAX_INFO_NUM; i++){
|
||||||
|
ets_printf("%u %s %p\n", g_mem_dbg.info[i].time, g_mem_dbg.info[i].type == DEBUG_TYPE_FREE?"f":"m", g_mem_dbg.info[i].addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_check_block(void* data)
|
||||||
|
{
|
||||||
|
debug_block_t *b = DEBUG_BLOCK(data);
|
||||||
|
|
||||||
|
MEM_DEBUG("check block data=%p\n", data);
|
||||||
|
if (data && (HEAD_DOG(b) == DEBUG_DOG_VALUE)){
|
||||||
|
if (TAIL_DOG(b) != DEBUG_DOG_VALUE){
|
||||||
|
ets_printf("f task=%s a=%p h=%08x t=%08x\n", b->head.task?b->head.task:"", b, HEAD_DOG(b), TAIL_DOG(b));
|
||||||
|
DOG_ASSERT();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ets_printf("f task=%s a=%p h=%08x\n", b->head.task?b->head.task:"", b, HEAD_DOG(b));\
|
||||||
|
DOG_ASSERT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_init_dog(void *data)
|
||||||
|
{
|
||||||
|
debug_block_t *b = DEBUG_BLOCK(data);
|
||||||
|
xTaskHandle task;
|
||||||
|
|
||||||
|
MEM_DEBUG("init dog, data=%p debug_block=%p block_size=%x\n", data, b, b->os_block.size);
|
||||||
|
if (!data) return;
|
||||||
|
#if (INCLUDE_pcTaskGetTaskName == 1)
|
||||||
|
task = xTaskGetCurrentTaskHandle();
|
||||||
|
if (task){
|
||||||
|
strncpy(b->head.task, pcTaskGetTaskName(task), 3);
|
||||||
|
b->head.task[3] = '\0';
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
b->head.task = '\0';
|
||||||
|
#endif
|
||||||
|
HEAD_DOG(b) = DEBUG_DOG_VALUE;
|
||||||
|
TAIL_DOG(b) = DEBUG_DOG_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_check_all(void* pv)
|
||||||
|
{
|
||||||
|
os_block_t *b;
|
||||||
|
|
||||||
|
if (pv){
|
||||||
|
char *puc = (char*)(pv);
|
||||||
|
os_block_t *b;
|
||||||
|
puc -= (g_heap_struct_size - BLOCK_TAIL_LEN - BLOCK_HEAD_LEN);
|
||||||
|
b = (os_block_t*)puc;
|
||||||
|
mem_check_block(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
taskENTER_CRITICAL(g_malloc_mutex);
|
||||||
|
b = g_free_list->next;
|
||||||
|
while(b && b != g_end){
|
||||||
|
mem_check_block(b);
|
||||||
|
ets_printf("check b=%p size=%d ok\n", b, b->size);
|
||||||
|
b = b->next;
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL(g_malloc_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_malloc_show(void)
|
||||||
|
{
|
||||||
|
os_block_t *b = g_malloc_list.next;
|
||||||
|
debug_block_t *debug_b;
|
||||||
|
|
||||||
|
while (b){
|
||||||
|
debug_b = DEBUG_BLOCK(b);
|
||||||
|
ets_printf("%s %p %p %u\n", debug_b->head.task, debug_b, b, b->size&(~g_alloc_bit));
|
||||||
|
b = b->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_malloc_block(void *data)
|
||||||
|
{
|
||||||
|
os_block_t *b = (os_block_t*)data;
|
||||||
|
|
||||||
|
MEM_DEBUG("mem malloc block data=%p, size=%u\n", data, b->size&(~g_alloc_bit));
|
||||||
|
mem_debug_push(DEBUG_TYPE_MALLOC, data);
|
||||||
|
|
||||||
|
if (b){
|
||||||
|
b->next = g_malloc_list.next;
|
||||||
|
g_malloc_list.next = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_free_block(void *data)
|
||||||
|
{
|
||||||
|
os_block_t *del = (os_block_t*)data;
|
||||||
|
os_block_t *b = g_malloc_list.next;
|
||||||
|
os_block_t *pre = &g_malloc_list;
|
||||||
|
debug_block_t *debug_b;
|
||||||
|
|
||||||
|
MEM_DEBUG("mem free block data=%p, size=%d\n", data, del->size&(~g_alloc_bit));
|
||||||
|
mem_debug_push(DEBUG_TYPE_FREE, data);
|
||||||
|
|
||||||
|
if (!del) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (b){
|
||||||
|
if ( (del == b) ){
|
||||||
|
pre->next = b->next;
|
||||||
|
b->next = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pre = b;
|
||||||
|
b = b->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_b = DEBUG_BLOCK(del);
|
||||||
|
ets_printf("%s %p %p %u already free\n", debug_b->head.task, debug_b, del, del->size&(~g_alloc_bit));
|
||||||
|
mem_malloc_show();
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -188,8 +188,12 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef INCLUDE_pcTaskGetTaskName
|
#ifndef INCLUDE_pcTaskGetTaskName
|
||||||
|
#if ( configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
#define INCLUDE_pcTaskGetTaskName 1
|
||||||
|
#else
|
||||||
#define INCLUDE_pcTaskGetTaskName 0
|
#define INCLUDE_pcTaskGetTaskName 0
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef configUSE_APPLICATION_TASK_TAG
|
#ifndef configUSE_APPLICATION_TASK_TAG
|
||||||
#define configUSE_APPLICATION_TASK_TAG 0
|
#define configUSE_APPLICATION_TASK_TAG 0
|
||||||
|
@ -222,6 +222,10 @@
|
|||||||
#define INCLUDE_vTaskDelay 1
|
#define INCLUDE_vTaskDelay 1
|
||||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||||
|
|
||||||
|
#ifndef configENABLE_MEMORY_DEBUG
|
||||||
|
#define configENABLE_MEMORY_DEBUG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define INCLUDE_xSemaphoreGetMutexHolder 1
|
#define INCLUDE_xSemaphoreGetMutexHolder 1
|
||||||
|
|
||||||
/* The priority at which the tick interrupt runs. This should probably be
|
/* The priority at which the tick interrupt runs. This should probably be
|
||||||
|
78
components/freertos/include/freertos/heap_regions_debug.h
Normal file
78
components/freertos/include/freertos/heap_regions_debug.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#ifndef _HEAP_REGION_DEBUG_H
|
||||||
|
#define _HEAP_REGION_DEBUG_H
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
|
||||||
|
#define DEBUG_DOG_VALUE 0x1a2b3c4d
|
||||||
|
#define DEBUG_MAX_INFO_NUM 20
|
||||||
|
#define DEBUG_TYPE_MALLOC 1
|
||||||
|
#define DEBUG_TYPE_FREE 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int dog;
|
||||||
|
char task[4];
|
||||||
|
unsigned int pc;
|
||||||
|
}block_head_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int dog;
|
||||||
|
}block_tail_t;
|
||||||
|
|
||||||
|
/* Please keep this definition same as BlockLink_t */
|
||||||
|
typedef struct _os_block_t {
|
||||||
|
struct _os_block_t *next;
|
||||||
|
size_t size;
|
||||||
|
unsigned int xtag;
|
||||||
|
}os_block_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
block_head_t head;
|
||||||
|
os_block_t os_block;
|
||||||
|
}debug_block_t;
|
||||||
|
|
||||||
|
typedef struct _mem_dbg_info{
|
||||||
|
void *addr;
|
||||||
|
char *task;
|
||||||
|
uint32_t pc;
|
||||||
|
uint32_t time;
|
||||||
|
uint8_t type;
|
||||||
|
}mem_dbg_info_t;
|
||||||
|
|
||||||
|
typedef struct _mem_dbg_ctl{
|
||||||
|
mem_dbg_info_t info[DEBUG_MAX_INFO_NUM];
|
||||||
|
uint32_t cnt;
|
||||||
|
}mem_dbg_ctl_t;
|
||||||
|
|
||||||
|
#define BLOCK_HEAD_LEN sizeof(block_head_t)
|
||||||
|
#define BLOCK_TAIL_LEN sizeof(block_tail_t)
|
||||||
|
#define OS_BLOCK(_b) ((os_block_t*)((debug_block_t*)((char*)(_b) + BLOCK_HEAD_LEN)))
|
||||||
|
#define DEBUG_BLOCK(_b) ((debug_block_t*)((char*)(_b) - BLOCK_HEAD_LEN))
|
||||||
|
#define HEAD_DOG(_b) ((_b)->head.dog)
|
||||||
|
#define TAIL_DOG(_b) (*(unsigned int*)((char*)(_b) + (((_b)->os_block.size & (~g_alloc_bit) ) - BLOCK_TAIL_LEN)))
|
||||||
|
|
||||||
|
#define DOG_ASSERT()\
|
||||||
|
{\
|
||||||
|
mem_debug_show();\
|
||||||
|
abort();\
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void mem_check_block(void * data);
|
||||||
|
extern void mem_init_dog(void *data);
|
||||||
|
extern void mem_debug_init(size_t size, void *start, void *end, portMUX_TYPE *mutex, unsigned int alloc_bit);
|
||||||
|
extern void mem_malloc_block(void *data);
|
||||||
|
extern void mem_free_block(void *data);
|
||||||
|
extern void mem_check_all(void* pv);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define mem_check_block(...)
|
||||||
|
#define mem_init_dog(...)
|
||||||
|
|
||||||
|
#define BLOCK_HEAD_LEN 0
|
||||||
|
#define BLOCK_TAIL_LEN 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user