Float and double cause hardfault handler on STM32F417

Hi, I’m working on IAR. I’m using FreeRTOS v9.0.0 on a STM32F417 microcontroller. I encounter problems when I declare and use float variables and double variables. The following code causes an Hardfault Handler. ~~~ void vTestTask(void *pvParameters) { for(;;) { float test; test = (float)(0x22); vTaskDelay(2000U); } } ~~~ Some details: * I use heap 4. * MCU frequency 16MHz * Operating system used the systick * FPU is activated. * The heap is located in the RTOS_RESERVED region, which is located in the CCRAM (see the linker file above). * The hardfault doesn’t occur when I write this code outside the task. * The hardfault occurs when vTaskDelay function ends, so it seems it’s when the context task is restored. Could you give me some hint please ? Please find abovemy FreeRTOSConfig.h file and the linker file. Regards, Ophélie Linker file: /###ICF### Section handled by ICF editor, don’t touch! ****/ /-Editor annotation file-/ / IcfEditorFile=”$TOOLKITDIR$configideIcfEditorcortexv1_0.xml” */ /*-Specials-*/ define symbol ICFEDIT_intvec_start = 0x08000000; /*-Memory Regions-*/ define symbol ICFEDIT_region_ROM_start = 0x08000000; define symbol ICFEDIT_region_ROM_end = 0x080DFFFF; define symbol ICFEDIT_region_RAM_start = 0x20000000; define symbol ICFEDIT_region_RAM_end = 0x2001FAFF; define symbol ICFEDIT_region_CCMRAM_start = 0x10000000; define symbol ICFEDIT_region_CCMRAM_end = 0x1000FFFF; /*-Sizes-*/ define symbol ICFEDIT_size_cstack = 0x500;
define symbol ICFEDIT_size_heap = 0x00;
/**** End of ICF editor section. ###ICF###*/ define memory mem with size = 4G; define region ROMregion = mem:[from ICFEDIT_region_ROM_start to ICFEDIT_region_ROM_end]; define region RAMregion = mem:[from ICFEDITregionRAM_start to ICFEDITregionRAM_end]; define region CCMRAM_region = mem:[from ICFEDIT_region_CCMRAM_start to ICFEDIT_region_CCMRAM_end]; define block CSTACK with alignment = 8, size = ICFEDITsizecstack { }; define block HEAP with alignment = 8, size = ICFEDITsizeheap { }; initialize by copy { readwrite }; do not initialize { section .noinit }; place at address mem:ICFEDITintvecstart { readonly section .intvec }; place in ROMregion { readonly }; place in CCMRAMregion { readwrite data section RTOSRESERVEDRAM }; place in RAM_region { readwrite, block CSTACK, block HEAP}; FreeRTOSCongig.h: ~~~

ifdef ICCARM

include “system_stm32f4xx.h”

extern void assertfailed(uint8t* file, uint32_t line); /* Function prototype defined in errorUtils.h */

endif

define configUSE_PREEMPTION 1

define configUSEPORTOPTIMISEDTASKSELECTION 1

define configUSETICKLESSIDLE 1

define configEXPECTEDIDLETIMEBEFORESLEEP 5

define configCPUCLOCKHZ SystemCoreClock

define configTICKRATEHZ 100

ifdef NDEBUG

/* TODO : remove NDEBUG once we have real board : if we remove it we lost debug, but with right SWD connection it should work */

define configSYSTICKCLOCKHZ SystemCoreClock/8

endif

define configMAX_PRIORITIES 10

define configMINIMALSTACKSIZE 128

define configMAXTASKNAME_LEN 16

define configUSE16BIT_TICKS 0

define configIDLESHOULDYIELD 1

define configUSETASKNOTIFICATIONS 1

define configUSE_MUTEXES 1

define configUSERECURSIVEMUTEXES 0

define configUSECOUNTINGSEMAPHORES 1

define configUSEALTERNATIVEAPI 0 /* Deprecated! */

define configQUEUEREGISTRYSIZE 40

define configUSEQUEUESETS 1

define configUSETIMESLICING 0

define configUSENEWLIBREENTRANT 0

define configENABLEBACKWARDCOMPATIBILITY 1

define configNUMTHREADLOCALSTORAGEPOINTERS 5

define configUSEAPPLICATIONTASK_TAG 0

/* Memory allocation related definitions. */

define configSUPPORTSTATICALLOCATION 0

define configSUPPORTDYNAMICALLOCATION 1

define configTOTALHEAPSIZE (17 * 1024)

define configAPPLICATIONALLOCATEDHEAP 1

/* Hook function related definitions. */

define configUSEIDLEHOOK 0

define configUSETICKHOOK 0

ifndef NDEBUG

define configCHECKFORSTACK_OVERFLOW 2

else

define configCHECKFORSTACK_OVERFLOW 0

endif

define configUSEMALLOCFAILED_HOOK 0

define configUSEDAEMONTASKSTARTUPHOOK 0

/* Run time and task stats gathering related definitions. */

define configGENERATERUNTIME_STATS 0

define configUSETRACEFACILITY 0

define configUSESTATSFORMATTING_FUNCTIONS 0

/* Co-routine related definitions. */

define configUSECOROUTINES 0

define configMAXCOROUTINE_PRIORITIES 2

/* Software timer related definitions. */

define configUSE_TIMERS 1

define configTIMERTASKPRIORITY 5

define configTIMERQUEUELENGTH 5

define configTIMERTASKSTACKDEPTH configMINIMALSTACK_SIZE

/* The lowest interrupt priority that can be used in a call to a “set priority” function. */

define configLIBRARYLOWESTINTERRUPT_PRIORITY 15

/* The highest interrupt priority that can be used by any interrupt service routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER PRIORITY THAN THIS! (higher priorities are lower numeric values. */

define configLIBRARYMAXSYSCALLINTERRUPTPRIORITY 5

/* Interrupt nesting behaviour configuration. / / Cortex-M specific definitions. */

ifdef __NVICPRIOBITS

/* __NVICPRIOBITS will be specified when CMSIS is being used. */

define configPRIO_BITS __NVIC_PRIO_BITS

else

define configPRIO_BITS 4 /* 15 priority levels – __NVIC_PRIO_BITS value is 4 */

endif

define configKERNELINTERRUPTPRIORITY ( configLIBRARYLOWESTINTERRUPTPRIORITY << (8 – configPRIOBITS) )

define configMAXSYSCALLINTERRUPTPRIORITY ( configLIBRARYMAXSYSCALLINTERRUPTPRIORITY << (8 – configPRIOBITS) )

/* Define to trap errors during development. */

define configASSERT( x ) if( ( x ) == 0 ) { assert_failed(FILE, LINE); }

/* Optional functions – most linkers will remove unused functions anyway. */

define INCLUDE_vTaskPrioritySet 1

define INCLUDE_uxTaskPriorityGet 1

define INCLUDE_vTaskDelete 1

define INCLUDE_vTaskSuspend 1

define INCLUDE_xResumeFromISR 1

define INCLUDE_vTaskDelayUntil 1

define INCLUDE_vTaskDelay 1

define INCLUDE_xTaskGetSchedulerState 1

define INCLUDE_xTaskGetCurrentTaskHandle 1

define INCLUDE_uxTaskGetStackHighWaterMark 0

define INCLUDE_xTaskGetIdleTaskHandle 0

define INCLUDE_eTaskGetState 0

define INCLUDE_xEventGroupSetBitFromISR 1

define INCLUDE_xTimerPendFunctionCall 0

define INCLUDE_xTaskAbortDelay 0

define INCLUDE_xTaskGetHandle 0

define INCLUDE_xTaskResumeFromISR 1

~~~

Float and double cause hardfault handler on STM32F417

Thanks for providing so much detail. In this case there are two things that will effect how floating point variables are handled, first is the port are using and second is the compiler’s command line (where the MCU to build for and the floating point unit the MCU has must be specified). Can you please ensure you are using the code from the FreeRTOS/Source/portable/[compiler]/ARMCM4F directory and not the ARMCM3 directory, and also show the command line you are using.

Float and double cause hardfault handler on STM32F417

We are using the code from the ARM_CM4F directory. We work on IAR so we don’t use command line. We set VFPv4 (FPU) on the project settings. Floating point variables were working with the FreeRTOS version 8.3.2.

Float and double cause hardfault handler on STM32F417

Put a break point on the first line of the function that implements the task – before anything has been pushed onto the stack – normally putting a break point on the opening bracket ‘{‘ does the trick (you can view the asm code when the break point has been it to ensure the stack has not been modified) – then let me know the value of the stack pointer.

Float and double cause hardfault handler on STM32F417

Please find attached a view from IAR. My task is LoRaManagerTask and you can see the start of stack and the top of stack. Is the stack of a task filled from the top to the start ? I realize these addresses were 4 bytes aligned. It might be a problem in my case.

Float and double cause hardfault handler on STM32F417

Any news ?

Float and double cause hardfault handler on STM32F417

Sorry – didn’t realise you had posted again. Unfortunately the screen shot does not provide the information required as it shows the top of the stack at the time the screen shot was taken. I need to see the stack pointer when it enters the task function, before the stack pointer has been moved to accomodate any stack used by the task itself.

Float and double cause hardfault handler on STM32F417

Which variable should I study to get the stack pointer value ?

Float and double cause hardfault handler on STM32F417

You need to view the stack pointer register in the debugger. Put a break point on the opening bracket of a task function, as below: void MyTask( void *pvParameters ) { // << Put the break point here int32_t MyVariable; When the break point is hit open the registers view in IAR and tell me the value of R13.

Float and double cause hardfault handler on STM32F417

The value of R13 is 0x20000EB8.

Float and double cause hardfault handler on STM32F417

That value is as it should be, divisible by 8, so I’m afraid I don’t know why the floats are not working, but it doesn’t seem to be related to the code executing in a task.

Float and double cause hardfault handler on STM32F417

Hello, I am Maximiliano, I am having the same issue as Tlemsani Ophélie. Is any news on this. I checked the stack pointer an is divisible by 8. My project is based on stm32f334, also a cortexm4

Float and double cause hardfault handler on STM32F417

Well, I think I got my problem, I double checked if my compiler was understanding I wanted to use the fpu unit, and found out it was one flag missing, in my case was “-mfpu=fpv4-sp-d16” I hope it also solves your project. Regards

Float and double cause hardfault handler on STM32F417

Hello Maximiliano. I have already activated VFPv4 on my IAR project. I have attached a view of IAR. Is it the same as the flag you are talking about ?

Float and double cause hardfault handler on STM32F417

And where did you add the missing flag ?

Float and double cause hardfault handler on STM32F417

I added the flag but I still have the problem. I have tried on another IAR project. The error is the same. I have tried the same code on the last IAR version (32Kbyte Kickstart, ARM 8.11.1) with the last version of the compiler but I still have an hardfault handler. Do you have a workspace example on IAR working on a Cortex M4?

Float and double cause hardfault handler on STM32F417

Are you actually enabling the floating point unit? The first post in this thread said is FPU was active, but it is worth double checking. I have used the floating point unit extensively in all our testing and the only problem I have ever had was when sprintf()’ing a floating point value when the stack was misaligned (4-byte instead of 8-byte).

Float and double cause hardfault handler on STM32F417

Yes I have enabled the floating point unit. We have used FreeRTOS for 4 years. Floating point unit were working on FreeRTOS version 8.2.0 and when we decided to use FreeRTOS version 9.0.0 we had this problem. Do you have a workspace example on IAR working on a Cortex M4? I can also send you my IAR worspace.

Float and double cause hardfault handler on STM32F417

Probably the closest for you as its using an ST part, albeit an M7, is in the following directory (same as the M4F port barring a silicon bug fix unrelated to the FPU): FreeRTOS/Demo/CORTEXM7STM32F7STM32756G-EVALIAR_Keil There are non ST IAR M4F projects in the following directories: FreeRTOS/demo/CORTEXM4FInfineonXMC4000IAR FreeRTOS/demo/CORTEXM4FMSP432LaunchPadIARCCSKeil and probably others. All of these test the floating point unit.

Float and double cause hardfault handler on STM32F417

Hi, I found the root cause but I don’t really get it. The problem is linked with the xPortPendSVHandler. If I specify in startupstm32f417xx.s that I want to use xPortPendSVHandler instead of PendSVHandler, everything works correclty. But if I want to use instead PendSVHandler and call xPortPendSVHandler inside the handler (that’s what I was doing) the programm crashes. I found there http://www.freertos.org/FreeRTOSSupportForumArchive/February2012/freertosSTM32F2hardfault5015439.html that we can’t do that way for PendSVHandler, but can you explain why ? I was using this method because I want to have special treatment in SysTickHandler (in addition with calling xPortSysTickHandler) so to have an unified way to handle things I did it for the 3 handlers (SysTickHandler, PendSVHandler and SVCHandler). Thanks,

Float and double cause hardfault handler on STM32F417

It would have been really helpful if you had said that to start with. If vPortPendSVHandler() was not the first thing to execute on interrupt entry then I’m surprised it worked at all as that is the function that performs the switch from one task to another – that means it must save a task’s context exactly as it was when the interrupt was entered, and performing any processing in between entering the interrupt and saving the context that changes the context will be problematic when the task next runs.

Float and double cause hardfault handler on STM32F417

I didn’t know it was the root cause. Otherwise, I would have noticed you. Please find below my code for the interrupt. Why is it not working? ~~~ void PendSV_Handler(void) { xPortPendSVHandler(); } ~~~

Float and double cause hardfault handler on STM32F417

xPortPendSVHandler() saves the context of the task that was interrupted – the context being (in part) the values held in CPU registers. Entering PendSV_Handler() will change the register values before xPortPendSVHandler() is executed, with the possibility that the register values saved within xPortPendSVHandler() are already corrupt.

Float and double cause hardfault handler on STM32F417

Thanks for the answer. But, why is it working without floating point ?

Float and double cause hardfault handler on STM32F417

When you use floating point instructions a bit gets set in one of the control registers, which in turn changes the stack frame when you enter interrupts. I would have to study the code output by the compiler to see exactly why you were getting the symptoms you were, but it is likely you actually have a problem in all cases but were only noticing when the stack frame was different and/or when floating point registers corruptions were causing faults.

Float and double cause hardfault handler on STM32F417

Ok, thanks for your response. I fixed my problem.