Problem with Task Parameter pvParameters

rousea wrote on Tuesday, March 02, 2010:

I am developing a project on an STM32 ARM Cortex processor, using FreeRTOS.  My main.c module includes the following:

const u8 PortNo = {1, 2, 3};
int main(void){
xTaskCreate(vUSARTtask, “USARTtask”, 1000, (void*)&PortNo, tskIDLE_PRIORITY + 4, NULL);
xTaskCreate(vUSARTtask, “USARTtask”, 1000, (void*)&PortNo, tskIDLE_PRIORITY + 4, NULL);
xTaskCreate(vUSARTtask, “USARTtask”, 1000, (void*)&PortNo, tskIDLE_PRIORITY + 4, NULL);

and function vUSARTtask contains:

void vUSARTtask(void* pvParameters){
u8 Port;
Port = *(u8*)pvParameters;

I have inserted a break point at switch(Port) where I can examine the value of Port.  The function should be called 3 times, with Port = 1, 2 & 3 respectively.  However, it is only called twice, with Port = 1 & 2.

If I chage the order of the xTaskCreate() lines it is apparent that only the first two instances are invoked and the third is always ignored.  I can even chage the sequence of other xTaskCreate() line before and after those in question, and always only the first two instances of vUSARTtask are invoked.

Does this mean there is a limit of 2 on the number of instances of a given tasks?  Or am I missing something?

Alan Rouse

oahmad2 wrote on Tuesday, March 02, 2010:


I’m a total newbie to freertos; but if you look at the xtaskcreate function, you will see that it returns an error when something goes wrong during task creation; the examples do not illustrate this.  You might not have enough memory allocated to create more than one task or something like that; but if you look at the return value of type portBASE_TYPE from xtaskcreate and look the value of it for the third instance and compare it to the errors defined in projdefs.h, you may be able to tell what is wrong.

Good Luck

rousea wrote on Wednesday, March 03, 2010:

Thanks for that.  It has helped me home in on the problem, but not solve it.  The third xTaskCreate() does indeed return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY.  If I reduce the stack depth from 1000 to 500 it works correctly.

However, it doesn’t explain why the fault occurs.  The project map includes the following:
                0x200000f4       0x14 obj/tasks.o
                0x20000108        0x4 obj/heap_2.o
.bss.xHeap     0x2000010c     0x4400 obj/heap_2.o
.bss.xStart    0x2000450c        0x8 obj/heap_2.o
.bss.xEnd      0x20004514        0x8 obj/heap_2.o
.bss.x32.5833  0x2000451c        0x4 obj/display.o
.bss.x16.5850  0x20004520        0x2 obj/display.o
*fill*         0x20004522        0x2 00
                0x20004524        0x4 obj/Mega_Link.o

This suggests to me that the heap extends from 0x2000010c to 0x2000450c, so is  0x4400 or  17408 bytes.The sum of all the tasks I am creating is less than 5000 bytes, so I wouldn’t expect a problem.

17408 is (17 * 1024) which is the value of configTOTAL_HEAP_SIZE in my FreeRTOSConfig.h.  According to the manual configTOTAL_HEAP_SIZE is used if   configCHECK_FOR_STACK_OVERFLOW > 0.  In my FreeRTOSConfig.h it has a value of 2.

I am therefore still confused over why I see the fault.

rtel wrote on Wednesday, March 03, 2010:

The stack sizes are specified in words, not bytes, so if you specify 1000 then this will allocate as stack of 4000 bytes on a 32 bit machine.

I`m not sure of the relationship between configTOTAL_HEAP_SIZE and configCHECK_FOR_STACK_OVERFLOW, where did you read that?  configTOTAL_HEAP_SIZE is only used when heap_1.c or heap_2.c are used in the build.  It´s value has no effect if heap_3.c is being used.


rousea wrote on Wednesday, March 03, 2010:


Thanks for responding.  The correlation between words and bytes explains my problem.  It also highlights just how much memory is needed by FreeRTOS:

I have built my application around a FreeRTOS configuration derived from one of the example applications. It uses about 25KB of RAM for data storage, and previously ran on an 8-bit processor with 32KB of RAM.  My intention was to upgrade to a 32-bit processor with 64KB of RAM, assuming this would give ample capacity for future enhancements.  I then realised that FreeRTOS allocates 17KB for its heap, which is a significant amount of the available RAM space.  I assumed the default value of (17 * 1024) for configTOTAL_HEAP_SIZE was to allow up to 17 tasks, each with 1024 bytes of stack.  Most of the examples in the manual set the stack depth to 1000, but now I realise that this is words, not bytes, so only 4 of the example tasks could be implemented.

I have so far implemented 10 tasks, which I think is less than half of the total that will be needed.  As each new task is introduced I have initially allocated 1000 words of stack, but I have included uxTaskGetStackHighWaterMark(NULL) in each task.  When I feel that the task development is nearly complete I check the highwater and adjust the stack depth accordingly (leaving some spare in case the application is later modified).  I have found that even the smallest tasks need 100 words.  I will obviously have to be very careful with allocating stack to new tasks to ensure there is sufficient, but I don’t exceed the maximum size defined, or the maximum memory space of the processor.

Regarding configCHECK_FOR_STACK_OVERFLOW, section 6.2 of ‘A Practical Guide’ describes the implications.  My FreeRTOS configuration sets it to 2, so I assume vApplicationStackOverflowHook() will be called if any task ever exceeds the allocated stack size.  I have implemented  vApplicationStackOverflowHook() to include only a while(1); statement, on which I have set a break point, but I have never yet hit the break point.  It is obviously only of use while running on an emulator.  When running stand-alone the whole system will obviously crash.

Regarding configTOTAL_HEAP_SIZE, I had incorrectly assumed from  section 2.2 of ‘API Functions and Configuration Options’ that heap_2.c was included automatically if configCHECK_FOR_STACK_OVERFLOW = 2.  I now realised that they are independent.  However, the FreeRTOS configuration I am using obviously calls up heap_2.c, as evidenced by the map listing I included in my earlier post.  Can you explain the difference between heap_1.c, heap_2.c and heap_3.c?

oahmad2 wrote on Wednesday, March 03, 2010:


Do you have access to the ‘using the freertos real time kernel - a practical guide’ ebook?  Chapter 5 shows the difference between heap1, heap2 and heap3 in great detail.

Briefly, heap1 is the only one that is deterministic, uses an array of size configTOTAL_HEAP_SIZE and doesn’t allow ‘freeing’ of allocated memory for a task, queue or semaphore; heap3 uses the normal malloc() and free(); heap2 also uses an array as in heap1 but allows freeing of memory by deallocating used-memory blocks closest in size to the requested block.

Please note that I’m a newbie, so do take that into account when looking at my responses.


rousea wrote on Wednesday, March 03, 2010:


I realise the difference in description of the alternatives, but what are the implications of each?  I assume there must be some overhead in using, say, heap_3.c rather than heap_1.c, but what is it? What advantage is there in using heap_1.c rather than heap_3.c?

richard_damon wrote on Wednesday, March 03, 2010:

each step from heap1 to heap3 adds some overhead (time/space) as it adds capability.

heap1 can only really be used in an application that allocates memory (for tasks/queue) and then holds on to it, not wanting to release it back to the heap. With that restriction the heap has basically no overhead, and is very quick.

heap2 adds the ability to return a block back to the heap, but due to some simplifications in the algorithm compared to heap3, it is assumed that the type of block freed will be the type that is wanted in the future (the heap doesn’t merge blocks back together on a free). It will require a bit of overhead memory per memory block, and a bit more time to allocate a block than heap1.

heap3 uses the systems malloc/free functions, which should provide the most general heap operations, It probably requires similar memory overhead for the allocations, but has a bit higher time overhead than heap2 for allocations/freeing.

If the application is already using malloc/free for other memory allocations, heap3 has the advantage (at least it is normally an advantage) that FreeRTOS will share its memory pool with the rest of the application.

rousea wrote on Wednesday, March 03, 2010:

I can see that heap_2.c is very slightly bigger than heap_1.c.  In the map listing I gave in my earlier post heap_2.c only used 16 bytes over and above the heap itself.  Therefore the code and RAM overhead memory difference between heap_1.c and heap_2.c is negligible.

If the application doesn’t create or delete any tasks during normal operation (which it can’t if using heap_1.c) then the only speed difference is during initialisation, where it doesn’t matter anyway.


What is the benefit of using heap_1.c rather than heap_2.c?

richard_damon wrote on Wednesday, March 03, 2010:

heap2 adds an overhead to every allocation made of a “headSTRUCT_SIZE”, which is a struct holding a pointer and a size_t, probably 4-8 bytes per allocation.

heap1 adds no overhead to every allocation, just a few bytes to manage the heap itself (which heap2 also has, and probably a bit more of).

Thus, if heap1 works for your application you are saving the 4-8 bytes per task or queue in the system (and tasks actually use 2 allocations, 1 for the TCB and 1 for the stack). heap1 should also be slightly smaller in code space, as it is simpler.