HardFault_Handler() is called if I try and format a float with sprintf

Rating:
 
Vote for this:
Good  -  Bad

Answer

Error handler HardFault_Handler() is called if your try to format a float as below:

sprintf(my_string,"%2.2f",(float)12.33);

A small clarification first, the current implementation for sprintf and %f requires using the heap.

The reason it hard faults is because of the heap, or rather, the heap doesn't get allocated as the ld file is written. I guess it this isn't as clear as it could be, but the start of the heap allocation is based on the symbol 'end' in the linker script.


The most likely cause of the error handler-call if due to lack of memory when using floats. Try reducing the page-size.

The page-size-setting can be found if you right-click on your project, then select 'Properties'.
Expand the 'C/C++ Build' - entry in the left column and select 'Settings'.
Select the 'Tool Setting'-tab and then look under 'C Linker' for 'Optimization'.
If you select that, you will see a drop down list for different page-sizes.

Select 'Small' and then Apply.


The other solutions are related to where how heap and stack are located in the memories.

In your linker script, 'end' gets set to _ebss which is located in the external ram.

Now, the problem comes down to the logic that implements the _sbrk() which is the memory pool allocator. It follows the very simple logic of:

Is the new heap pointer located below the stack pointer ? Then return memory : otherwise return out of memory.

Since the stack in your script is in the internal ram and the heap wants to be located in the external ram on a higher address, the _sbrk won't ever give out memory.

So you have at least three choices here,

1. Make sure the heap is located in the internal ram below the stack

2. Place the stack in the external ram as well

3. Re-implement the _sbrk() memory allocation logic. (you can look at the current _sbrk() implementation by right-clicking on your project, select new -> Other, then expand "System Calls" and generate the Minimal system calls file somewhere into your project)


The simplest way is to go for number 1.

Remove the PROVIDE(end = _ebss) from your linker scripts bss section.

And then you can place a new statement directly after the _estack = 0x2001000;, specifying for example:

end = 0x20000000; /* Place the heap at start of internal RAM */


Since the heap grows upwards, you don't want to place valuable data directly after the 'end' symbol as it might get overwritten.


Tags for this item