This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/CC2650: HeapBuff block size question

Part Number: CC2650


Tool/software: TI-RTOS

Hello,

I am have read the Kernel User Guide - HeapBuff section. It reads"Be careful when specifying these runtime parameters. The blocksize needs to be a multiple of the worst-case structure alignment size. And bufSize should be equal to blockSize * numBlocks. The worst-case structure alignment is target dependent. On devices with a 32-bit architecture, the 8-byte alignment is used. The base address of the buffer  should also be aligned to this same size."

I am running on a CC2650, and assume that it also uses the "8-byte alignment" [Please comment on the truth of this]. As I understand it, the MCU will user a character array as the heap, and in this case it will be 1280 bytes wide (see code below). I do not understand why a block size must be chosen, but I take it to mean that this particular code was written by a user who expects to write 10 objects of 128 bytes in size - I assume this since we are speaking of HeapBuf in which we must already know the size of data we will be writing (which should correspond to the block size?). If I am incorrect in this assumption, please explain me, as I do not understand why the number of blocks must be allocated to begin with.

Finally, to account for "worst-case structure alignment", should we create block sizes that are multiples of 8 for the CC2650 system? Thank you for your help!

HeapBuf_Params prms;
static char buf[1280];
HeapBuf_Handle heap;
Error_Block eb;

Error_init(&eb);
HeapBuf_Params_init(&prms);
prms.blockSize = 128;
prms.numBlocks = 10;
prms.buf = (Ptr)buf;
prms.bufSize = 1280;
heap = HeapBuf_create(&prms, &eb);
if (heap == NULL) {
System_abort("HeapBuf create failed");
}

  • Hi Anthony,

    HeapBuf manages N fixed-size buffers of size M. Internally we just do a linked list of free blocks. This allows for fast allocation and freeing. It also eliminate external fragmentation. There might have internal fragmentation (e.g. fixed size blocks are 32 bytes and you request 24 bytes). So for creation you must specify the # of blocks and the size. Then the create will take the buffer supplied and slice the blocks up and stick them on a linked list.

    HeapMem (which is the type of heap that is created by default for you and used in malloc and Memory_alloc(NULL,...)) is a variable-size heap. With this heap, you just give a buffer and the size of the buffer.

    On the CC26xx (and all CortexM devices), the worst-case data type alignment is 8 bytes (e.g. double, long double and long long). Since HeapBuf does not know what you are going to put in the allocated buffer, it assumes the worse and requires an alignment that will handle everything.

    We do have the Memory_getMaxDefaultTypeAlign() API. You can use this instead of hard-coded value for runtime code.

    Note: HeapBuf should only be used when the allocated blocks are going to be roughly the same size (e.g. 64, 48, 54, etc.). You would not use it if you are having varying sizes. In this case, I'd recommend HeapMem (or the default heap) or HeapMultiBuf (it manages N pools of fixed-size blocks).

    Note: we highly recommend you do not call HeapBuf_alloc directly. You should go through the Memory module. It does some parameter checking and alignment adjusting. For example you'd call Memory_alloc(myHeapHandle, ...).

    I hope this helped and did not just confuse everything:)

    Todd
  • Hello,

    Thanks for the thorough answer. I would like to run something by you. I am implementing a linked list of my own using c (using HeapBuf), and the struct that acts as a node contains 2 long data types and a pointer to the next value. This amounts to a size of 14 bytes. Since the system is 8-byte aligned, would it be safe to create a buffer with M blocks of size 16, and within each block i will only ever use 14 of the 16 bytes. This, as you have mentioned, will cause internal fragmentation of a block, but i feel that it is irrelevant because when i free a block it will deallocate the 16 bytes (including the 14 bytes) and leave me with the 16 free bytes to re-write to. Does that make sense?

  • That would be fine. Note 2 longs and a pointer is 12 bytes for ARM devices. Also, we have a Queue module in the kernel. It is a doubly linked-list (next and prev pointers).