1

Overview

I'm having a weird issue with my STM32F407ZGT6 when attemting any operation with float variables. The Infinite_Loop Default Handler gets called and I get stuck. I'm using the STM32CubeIDE. The following is enough to make the STM32CubeIDE crash:

int main(void)
{
    float my_float = 2.5;

    for(;;)
    {
        my_float += 1; //Crashes here
    }
}

Details

At failure, the debugging stack shows:

Thread #1 [main] 1 [core: 0] (Suspended : Step) 
    WWDG_IRQHandler() at C:\~\Documents\stm32\LM_STM32\Startup\startup_stm32f407zgtx.s:115 0x8000f80    
    <signal handler called>() at 0xfffffff9 
    main() at C:\Users\Pesquisa2\Documents\stm32\LM_STM32\Src\main.c:60 0x8000d8e   
arm-none-eabi-gdb (10.2.90.20210621)    
ST-LINK (ST-LINK GDB server)    

and the disassembly error message appears to accuse stack overflow (?):

fffffff9:   Failed to execute MI command:
          -data-disassemble -s 4294967289 -e 4294967437 -- 3
          Error message from debugger back end:
          Cannot access memory at address 0xfffffffe

I tried looking at the STM Floating point demonstration, but the examples don't do anything particular before using float variables... At first, I thought it was only when attempting to printf like others have experienced [2][3][4][5][6][7][8], but now it's evident the problem is with float itself.

What am I not doing properly? Do I need a library or something???


Settings

MCU Settings:

Floating-point uinit: FPv4-SP-D16
Floating-point ABI: Hardware implementation (-mfloat-abi=hard)
Instruction set: Thumb2
Runtime library: Reduced C (--specs=nano.specs)
[x] -u_printf_float
[x] -u_scanf_float

GCC Assembler options:

-mcpu=cortex-m4 -g3 -DDEBUG -c -x assembler-with-cpp --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb

GCC Compiler options:

--mcpu=cortex-m4 -std=gnu11 -g3 -DDEBUG -DSTM32 -DSTM32F4 -DSTM32F407ZGTx -c -I"C:\Users\Pesquisa2\STM32Cube\Repository\STM32Cube_FW_F4_V1.27.0\Drivers\CMSIS\Include" -I"C:\Users\Pesquisa2\STM32Cube\Repository\STM32Cube_FW_F4_V1.27.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include" -I"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\Inc\App" -I"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\Inc\HAL" -I"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\Inc\Midware" -I"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\Src\App" -I"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\Src\HAL" -I"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\Src\Midware" -I"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\Inc" -I"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\FATFS" -I"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\mma845x_inc" -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb

GCC Linker options:

-mcpu=cortex-m4 -T"C:\Users\Pesquisa2\Documents\stm32\LM_STM32\STM32F407ZGTX_FLASH.ld" --specs=nosys.specs -Wl,-Map="${BuildArtifactFileBaseName}.map" -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -u _printf_float -u _scanf_float -Wl,--start-group -lc -lm -Wl,--end-group
mgmussi
  • 520
  • 1
  • 4
  • 19
  • Your code results in a infinite loop. There is no condition for the FOR LOOP to break. So it continue running till you run out of memory – Maxwell D. Dorliea Jul 26 '22 at 20:22
  • 1
    What if you perform any FP operation not in a loop? What if you replace `float` with `unsigned`? – Eugene Sh. Jul 26 '22 at 20:22
  • Have you enabled the watchdog timer in CubeMx? Or maybe on that part it is enabled by default and you need to turn it off. Or maybe your startup code enable it. That’s what it looks like it has happened and your `for(;;)` loop is infinite so eventually the timer expires. – tinman Jul 26 '22 at 20:24
  • 2
    @tinman `WWDG_IRQHandler` is probably misleading: https://stackoverflow.com/questions/27623885/stm32-wwdg-interrupt-firing-when-not-configured – Eugene Sh. Jul 26 '22 at 20:25
  • 1
    @EugeneSh. it is the usual beginner trap. FPU is disabled by default (it consumes power) and has to be enabled by the programmer. Otherwise the FPU instructions will be treated as invalid and exception raised. – 0___________ Jul 26 '22 at 20:31
  • @MaxwellD.Dorliea what in your opinion will cause the "out of memory" ? – 0___________ Jul 26 '22 at 20:38
  • You say I think erroneously that STM32CubeIDE is crashing. Clarify. – Clifford Jul 27 '22 at 12:39
  • @Clifford I meant to say I get stuck in `Infinite_Loop` – mgmussi Jul 27 '22 at 14:01
  • Rather than _where it ends up_ you need to consider _how it got there_. No doubt it is a `UsageFault` exception (which will show as a `HardFault` if you have not enabled separate exceptions). You should consider implementing separate and more informative exception handlers rather then relying on some "infinite loop" common to multiple exception and interrupt events - this sort of issue will then be far easier to debug. The point is nothing "called" the infinite loop, it is a basic and default exception handler - you really should replace it. – Clifford Jul 27 '22 at 21:16

1 Answers1

5

It is very simple. You need to enable the FPU before doing any FP operations. Otherwise you will rise the HardFault and you will end up in the empty exception handler. As you probably did not write distinct handlers you will have only one handler (identical will be discarded by the compiler and the name of the handler will be misleading).

If you use Cube set __FPU_PRESENT nad __FPU_USED macros to 1

or simply enable the FPU

    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  

BTW your code executes only because you have not enabled any optimizations. I would advise for debugging -Og.

int main(void)
{
    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  
    volatile float my_float;

    my_float = 2.5f;
    for(;;)
    {
        my_float += 1; //Crashes here
    }
}

Also remember that 2.5 is not float only double. You need to use 'f' suffix, otherwise the compiler will call the conversion code.

float my_float = 2.5f;
0___________
  • 60,014
  • 4
  • 34
  • 74
  • Thanks for the reply! It worked when I did `SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));`. I was already using the `stm32f407xx.h`, which already had `#define __FPU_PRESENT 1U` and that enabled `__FPU_USED` on `core_cm4.h`, so I'm wondering why did I have to manually set it for it to work? – mgmussi Jul 27 '22 at 11:06
  • Also, I remember I had this commented out `#if !defined(__SOFT_FP__) && defined(__ARM_FP) #warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use." #endif` because I always got that warning. Maybe I need the `__SOFT_FP__`? – mgmussi Jul 27 '22 at 11:51
  • @mgmussi no, you do not need, you have FPU – 0___________ Jul 27 '22 at 14:05