2012-04-10 02:05 PM
Hi all,
With Keil MDK-ARM I had a random hard fault when I change the optimization level of the compiler. The reason is a VPUSH.64 assembler instruction that tries to use the FPU. This instruction is added by the compiler before entering the main() function, so, at this point, the PFU is not enable. I found a solution at http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/471/t/155025.aspx?PageIndex=2 Edit startup_stm32f4xx.s file and add the following code in the Reset_handler ; CPACR is located at address 0xE000ED88 LDR.W R0, =0xE000ED88 ; Read CPACR LDR R1, [R0] ; Set bits 20-23 to enable CP10 and CP11 coprocessors ORR R1, R1, ♯(0xF << 20) ; Write back the modified value to the CPACR STR R1, [R0]; wait for store to complete DSB ;reset pipeline now the FPU is enabled ISB Regrds, �ngel #semihosting2012-04-11 06:35 AM
Keil has this code in the startup file since at least v4.22, and it has been working fine for me. Basically if you expect the FPU co-processor to be working you have to enable it.
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
;FPU settings
LDR R0, =0xE000ED88 ; Enable CP10,CP11
LDR R1,[R0]
ORR R1,R1,#(0xF << 20)
STR R1,[R0]
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
How exactly are the Hard Fault's random, I think it would pretty predictably fail if the FPU were not enabled? And wouldn't a branch succeed in breaking the pipeline? How close to the enabling point would an FPU instruction need to be to induce ''random'' failure?
2012-04-11 03:23 PM
http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f4discovery_fw.zip
and Keil MDK-ARM 4.50 (I tried to upgraded it from 4.23 in order to solve this issue, but no luck). The projects in the firmware package utilize the startup_stm32f4xx.s in this path: STM32F4-Discovery_FW_V1.1.0/Libraries/CMSIS/ST/STM32F4xx/Source/Templates/arm/starttup_stm32f4xx.s Head of the file and reset handler are showed bellow. The FPU IS NOT ENABLED HERE.;******************** (C) COPYRIGHT 2011 STMicroelectronics ********************
;* File Name : startup_stm32f4xx.s
;* Author : MCD Application Team
;* Version : V1.0.0
;* Date : 30-September-2011
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
I tested now the same file distributed with Keil MDK-ARM 4. The head is older than the previous one, but, as clive1 states, the FPU is enabled here.
;******************** (C) COPYRIGHT 2011 STMicroelectronics ********************
;* File Name : startup_stm32f4xx.s
;* Author : MCD Application Team
;* Version : V1.0.0RC1
;* Date : 25-August-2011
So the problem is with the starttup_stm32f4xx.s file distributed with the discovery.
Well, now about the term “random�?. When I put the compiler at optimizing level -O3, all worked well. But I prefer to disable optimization when I debug. In this case, the compiler generates FPU instructions before I have the opportunity for enabling the FPU from C code.
See image bellow.
I don't know the reason for that. But it seems highly dependent on the code of the project. You change some parts of the code, and these offending instructions disappear.
Regards,
Àngel
2012-04-11 04:46 PM
The package you cite is ST's own release
Keil has some of their own variants preinstalled, see \Keil\ARM\Boards\ST\STM32F4-Discovery\Blinky I'd have to look at the optimization, do you have some float code in your application? I'll have to try something like #include <stdio.h> #include <math.h> void test(float x, float y) { printf(''%f\n'', (x / y)); } int main() { test(22.0, 7.0); while(1); }2012-04-12 08:52 AM
Hi,
I tried to find the reason for the generation of V* instruction, but without fortune. I removed all my modules that use floating point and played with optimisations. Bellow is an image of C optimization level -O0 generating V* instructions (bellow the PUSH instruction). This happened in a call to a USB initialisation: If I increase the optimization level (-O3). The V* instructions disappear. So no hard faults. It seems that it happen in calls to complex functions with lots of parameters. In any case, enabling the FPU its the workaround for me. Regards, Àngel2012-05-15 08:31 AM
I agree. Enabling the FPU is not a solution. It's a workaround. I think its reasonable for us to expect a solution.
When I hit this problem I resorted back to the ''STM32F4-Discovery_FW_v1.10'' example firmware from st.com, changed the optimisation level to 0 and ran it on the STM32F4 Discovery board. That was all that was needed to reproduce the problem. It's either a compiler bug or there is some problem with the example firmware. Until I can be confident that its not a compiler bug, I can't move forward. I can't waste any more time chasing problems like this.2012-05-15 09:47 AM
Don't want it generating FPU instructions, and/or don't want to enable the FPU, make sure the project sets the ''Floating Point Hardware'' option to ''Not Used'' instead of ''Use FPU''.
If you think there is a compiler bug, go discuss/submit that to your Keil support contact.
2012-05-15 05:13 PM
in the system_stm32f4xx.c
void SystemInit(void) uses /* FPU settings ------------------------------------------------------------*/ #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ #endif2013-02-21 03:34 PM
i dont understand but mcu not jumping to hard faulthandler after ticking
Use MicroLİB at code generation tab is there some one who can explain that ?2013-02-21 04:39 PM
i dont understand but mcu not jumping to hard faulthandler after ticking Use MicroLİB at code generation tab is there some one who can explain that ?
Yeah, without the MicroLIB the code you link in to support printf, scanf, etc generates a SWI (Software Interrupt) for some OS level code, and you don't have any code to support it and implement the functions. Examine the code at the faulting address.