What is FPU and why does it cause assembler error?
Assembler error: FPU
I built a project on STM32F429 board in PlatformIO, and I got this error:
1
2
3
4
5
6
arm-none-eabi-gcc-ar rc .pio/build/disco_f429zi/libFrameworkCMSISDevice.a .pio/build/disco_f429zi/FrameworkCMSISDevice/gcc/startup_stm32f429xx.o .pio/build/disco_f429zi/FrameworkCMSISDevice/system_stm32f4xx.o
arm-none-eabi-gcc-ranlib .pio/build/disco_f429zi/libFrameworkCMSISDevice.a
/var/folders/w7/s2tyt4v54313_kmyn4cy499r0000gn/T//ccYSACNG.s: Assembler messages:
/var/folders/w7/s2tyt4v54313_kmyn4cy499r0000gn/T//ccYSACNG.s:6641: Error: selected processor does not support vstmdbeq r0!,{s16-s31}' in Thumb mode /var/folders/w7/s2tyt4v54313_kmyn4cy499r0000gn/T//ccYSACNG.s:6643: Error: instruction not allowed in IT block -- stmdb r0!,{r4-r11,r14}'
/var/folders/w7/s2tyt4v54313_kmyn4cy499r0000gn/T//ccYSACNG.s:6663: Error: selected processor does not support vldmiaeq r0!,{s16-s31}' in Thumb mode /var/folders/w7/s2tyt4v54313_kmyn4cy499r0000gn/T//ccYSACNG.s:6665: Error: instruction not allowed in IT block -- msr psp,r0'
*** [.pio/build/disco_f429zi/src/freertos_includes.o] Error 1
The error message was quite incomprehensible. Turns out it’s the assembler error (vstmdbeq/vldmiaeq/msr psp in IT block). But why did it happen? This was Copilot’s answer:
- The assembler errors you saw (vstmdbeq/vldmiaeq/msr psp in IT block) happen when assembler doesn’t expect VFP/FP instructions or the wrong float-ABI is used. The STM32F429 has an FPU; the ARM_CM4F FreeRTOS port emits VFP instructions and context-switch code that uses VFP registers. The compile flags above tell GCC/assembler to target the FPU and use the hard float ABI, and the __FPU_PRESENT macro enables FPU-specific code paths in the port headers.
There are some new, unheard keywords popping out.
- FPU
- VFP
- ABI
Let’s go over each term.
1. Floating-Point Unit (FPU)
Floating-point unit (FPU) is an actual hardware component; it is specialized in performing mathematical calculations on floating-point numbers.
Floating-point calculations require a lot of resources. If the processor doesn’t have a FPU, all the floating point operations are done by software through the C compiler library (but the performances are very low). On a processor having an FPU, all of the operations are entirely done by hardware in a single cycle, for most of the instructions. The C compiler does not use its own floating-point library but directly generates FPU native instructions.1
So does my board (STM32F429) support FPU? The answer is Yes.
The STM32F427xx and STM32F429xx devices are based on the high-performance Arm® Cortex®-M4 32-bit RISC core operating at a frequency of up to 180 MHz. The Cortex®-M4 core features a floating-point unit (FPU) single precision, which supports all Arm® single- precision data-processing instructions and data types.2
2. Vector Floating Point (VFP)
A Vector Floating-Point (VFP) instruction is a command for a floating-point coprocessor used in ARM architecture that performs arithmetic on floating-point numbers. VFP can be thought of as FPU or floating point instruction set. 34
3. Application Binary Interface (ABI)
Application Binary Interface (ABI) refers to the specification that defines how the parameters and the results of the floating-point calculations are transferred across function boundaries. 5
To make it simple, there are options for ABI and they affect whether the floating-point unit is used. In my case, STM32F429 board has a FPU and that is why I can set ABI option as -mfloat-abi=hard.
Hard ABI: This allows the compiled code to generate codes that directly accesss the FPU and use FPU-specific calling conventions when calling runtime library functions.5
VFP insturction in port.c
What did it mean by this?:
The ARM_CM4F FreeRTOS port emits VFP instructions and context-switch code that uses VFP registers.
Let’s look into the actual code. port.c is located under $HOMEPATH/.platformio/packages/framework-stm32cubef4/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/.
In line 372 of port.c,
1
2
/* Ensure the VFP is enabled - it should be anyway. */
vPortEnableVFP();
Also in line 431,
1
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
Conclusion
These need to be added to build_flags in platformio.ini:
-D__FPU_PRESENT=1-mfloat-abi=hard-mfpu=fpv4-sp-d16
References
-
https://www.st.com/resource/en/application_note/an4044-floating-point-unit-demonstration-on-stm32-microcontrollers-stmicroelectronics.pdf ↩
-
https://www.st.com/resource/en/datasheet/stm32f427vg.pdf ↩
-
https://stackoverflow.com/questions/66047684/what-is-vector-floating-point-vfp ↩
-
https://developer.arm.com/documentation/den0013/0400/Floating-Point/Floating-point-basics-and-the-IEEE-754-standard/ARM-VFP?lang=en ↩
-
https://developer.arm.com/documentation/107656/0101/Registers/Floating-point-registers/Using-Floating-point-extension/ABI-options ↩ ↩2