How to use SystemView Heap Monitoring - Custom Heap

From SEGGER Wiki
Jump to navigation Jump to search

Intro

This article assumes a working SystemView setup. To gain some more info on this subject, please consult either the main article (How to use SystemView Heap_Monitoring) or the SystemView documentation.

Heap Initialization

A typical heap organization would look like this:

heap organization.svg

...where metadata holds the information about the size of the chunk and pointers to other chunks. This information needs to be provided during the initialization of the SystemView interface through the following function:

void SEGGER_SYSVIEW_HeapDefine(void         * pHeap,
                               void         * pBase,
                               unsigned int   HeapSize,
                               unsigned int   MetadataSize);

The __heap_start__ and __heap_size__ are symbols that are defined if a region named heap is specified in the linker script. E.g. to define a heap which has the metadata holding a size of the chunk and a pointer to the next chunk:

SEGGER_SYSVIEW_HeapDefine(__heap_start__, __heap_start__, (unsigned int)__heap_size__, sizeof(unsigned) + sizeof(void*));

Reporting Heap Data To SystemView

The size reported to SystemView should be the internally allocated size excluding the metadata, and not the size requested by a user. Therefore, an internal utility function for obtaining the size to be reported to SystemView, which also observers alignment, might look like this:

#define HEAP_CHUNK_SIZE 8

static U32 _GetAllocBlockSize(U32 ReqSize) {
  return (ReqSize + sizeof(unsigned) + HEAP_CHUNK_SIZE - 1) & (unsigned)(-HEAP_CHUNK_SIZE);
}

Allocating the memory should be accompanied by a call to SEGGER_SYSVIEW_HeapAlloc:

static void* _MyMalloc(size_t size) {
  void* p = ... // allocate a block
  // SystemView needs the real internal heap block size, not the amount requested by the user
  SEGGER_SYSVIEW_HeapAlloc(__heap_start__, p, _GetAllocBlockSize(size));
  return p;
}

Freeing the memory should be accompanied by a call to SEGGER_SYSVIEW_HeapFree:

static void _MyFree(void* p) {
  ... // freeing procedure
  SEGGER_SYSVIEW_HeapFree(__heap_start__, p);
}

Since there is no dedicated realloc SystemView API function, a combination of SEGGER_SYSVIEW_HeapFree and SEGGER_SYSVIEW_HeapAlloc is needed:

static void* _MyRealloc(void* p, size_t size) {
  ... // reallocation procedure
  SEGGER_SYSVIEW_HeapFree(__heap_start__, p);
  // SystemView needs the real internal heap block size, not the amount requested by the user
  SEGGER_SYSVIEW_HeapAlloc(__heap_start__, rp, _GetAllocBlockSize(size));
  return rp;
}