xQueueCreate() returns invalid handler

nex12345 wrote on Wednesday, December 28, 2016:

I’m facing an error within vSemaphoreCreateBinary(…). The macro looks like this:

#define vSemaphoreCreateBinary( xSemaphore ){														\
		( xSemaphore ) = xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH );	\
		if( ( xSemaphore ) != NULL )																	\
		{																								\
                xSemaphoreGive( ( xSemaphore ) );								  							\
		}																								\
}

The application runs into a hardfault within xSemaphoreGive(). xSemaphore, which is a pointer, is pointing to the address 0xc18f04f. This is not a valid address and accessing it leads to a hardfault.
I used the debugger to step through xQueueCreate() line by line but wasn’t able to detect sth abnormally.
Here is a screenshot which shows that the pointer pxNewQueue points to address 0x20001130. This is a valid address.
ScreenShot

I do not understand why the address changes to 0xc18f04f? Any hint is highly appreciated.

I’m using FreeRTOS V6.1.1 with Atollic TrueSTUDIO 7.0.1 on a STM32F205.

nex12345 wrote on Wednesday, December 28, 2016:

I was able to reproduce the same behaviour in an other project where FreeRTOS isn’t used at all. The issue is not related to FreeRTOS.

nex12345 wrote on Thursday, December 29, 2016:

I spent another day looking at this issue. The issue is caused by a collision of heap and stack. TrueSTUDIO comes with two options: Dynamic heap size (default) and Fixed heap size. In projects where no RTOS is used Atollic recommends to use the dynamic option. This worked fine and I was able to solve above issue by this change for projects where FreeRTOS is not used.
However, for projects with FreeRTOS a dynamic heap size doesn’t seem to be an option. Out of the user guide:

If using an RTOS, it is recommended to generate a system calls file, and select
the Fixed Heap size option. This option requires that the _Min_Heap_Size
symbol is defined in the linker script .ld file. The .ld file is stored in the root
directory of the currently selected project. The heap size defined by
_Min_Heap_Size must meet the heap size required by the application.

The IDE automatically created a linker and a syscalls file. For the linker file it makes no difference whether dynamic or fix heap size has been selected - it looks the same in both cases. Here the interessting lines of the linker script:

/* Highest address of the user mode stack */
_estack = 0x2001c000;    /* end of 112K RAM */

/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 768K
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 112K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

Heap size is 0 and stack size is 1K. Is it somehow possible to calculate those values before building the application? Shall the minimal heap size be equal to the FreeRTOS config value configTOTAL_HEAP_SIZE?

The second auto generated file is the syscalls file. This file changes completely when you compare projects with dynamic heap size and fix heap size. I think the central part of this file is the implementation of the function sbrk(int32t incr):

caddr_t _sbrk(int32_t incr)
{
  extern uint32_t _Min_Heap_Size; /* _Min_Heap_Size symbol defined in the linker script. */
  extern uint8_t end asm("end");
  const uint8_t *max_heap = (uint8_t*)((uint32_t)&end + (uint32_t)&_Min_Heap_Size);
  static uint8_t *heap_end;
  uint8_t *prev_heap_end;

  if (heap_end == 0)
    heap_end = &end;

  prev_heap_end = heap_end;
  if (heap_end + incr > max_heap)
  {
//    write(1, "Heap and stack collision\n", 25);
//    abort();
    errno = ENOMEM;
    return (caddr_t) -1;
  }

  heap_end += incr;

  return (caddr_t) prev_heap_end;
}

The collision detection fails obviously as _Min_Heap_Size is 0. Unfortunately the application does not abort at this point but continues to run. The consequence was in my case that the pointer of a queue was overridden and invalid. I would prefer to enter an endless loop if application runs out of heap. What do you think - does this make sense? Does the function itself make sense when used with FreeRTOS??

Thanks in advance for any help.

richard_damon wrote on Thursday, December 29, 2016:

The function looks like it would make sense (but maybe not with Min_Heap_Size == 0) to provide a seperate malloc heap. It should return -1 to signal that there isn’t more memory, and maybe the heap functions can’t handle that on the initial allocation. The proper value of Min Heap will depend on how much heap memory is needed from this heap.