[SOLVED] Sprintf with floating point number crashing into hard fault on STM32L476, working fine with STM32F091
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 8:10 AM
I'm trying to use this C code
#include <stdio.h>
char arr[50];
int var_int;
float var_float;
int main (void)
{
while (1)
{
var_int++;
sprintf (arr,"RES 1 %d",var_int);
var_float = var_float + 0.1;
sprintf (arr,"RES2 %d %f",var_int,var_float);
}
}
on STM32L476 nucleo kit, with STM32CubeIDE (Version: 1.5.0 Build: 8698_20201117_1050 (UTC)), I'm using debugger, stepping the code and observing variables in expression window, however the code always fails at second sprintf call (the one with float variable). Before trying to execute second sprintf call I can see proper output from first sprintf call, as well as float variable with proper value
but after second sprintf call I find the MCU executing endless loop after fault. The second sprintf managed to print output up to the floating point part.
I started fresh project for this, didn't modify linker file nor any project settings, with exception of ticking "Use float with with printf from newlib-nano"
I suppose hard fault from sprintf is not desired outcome, but I can't find any obvious way to fix this.
For sake of completeness, due to size, map file is pasted here https://pastebin.com/CeyVYpEP and build output follows.
12:32:09 **** Incremental Build of configuration Debug for project test476 ****
make -j2 all
arm-none-eabi-gcc "../Src/main.c" -mcpu=cortex-m4 -std=gnu11 -g3 -DSTM32L4 -DSTM32 -DNUCLEO_L476RG -DDEBUG -DSTM32L476RGTx -c -I../Inc -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -MMD -MP -MF"Src/main.d" -MT"Src/main.o" --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -o "Src/main.o"
arm-none-eabi-gcc -o "test476.elf" @"objects.list" -mcpu=cortex-m4 -T"/home/jarin/STM32CubeIDE/workspace_1.5.0/test476/STM32L476RGTX_FLASH.ld" --specs=nosys.specs -Wl,-Map="test476.map" -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -u _printf_float -Wl,--start-group -lc -lm -Wl,--end-group
Finished building target: test476.elf
arm-none-eabi-objdump -h -S test476.elf > "test476.list"
arm-none-eabi-objcopy -O binary test476.elf "test476.bin"
Finished building: test476.bin
Finished building: test476.list
arm-none-eabi-size test476.elf
text data bss dec hex filename
12520 472 1640 14632 3928 test476.elf
Finished building: default.size.stdout
12:32:10 Build Finished. 0 errors, 0 warnings. (took 830ms)
I tried the same source, with the same project setup modification (single checkbox to use float functions) on STM32F091 nucleo kit, where it works as I expect (second printf doesn't crash and prints desired output to char array).
Perhaps I'm overlooking something very obvious, but I can't see where the problem is.
Also, I'm aware of printf and similar functions not being the most fitting for small embedded systems, but this is probably not the topic here.
Solved! Go to Solution.
- Labels:
-
STM32CubeIDE
-
STM32L4 series
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 2:12 PM
Yes, those are valid points, thanks. I tried to examine the MCU state at the fault state.
Bit 2 in LR is 0, therefore main stack was active at the exception moment, SP points to 0x20017e58, examining this part of memory reveals PC at address SP+0x18, that is 0x0800100A. Disassembly window shows 'vmov d0, r8, r9' instruction at this address, inside _printf_float function.
vmov makes sense in this context - moving between VFP and registers. R8 and R9 values looked benign to me. While I was at it, I checked CPACR
register and found it's all zeroes, so that FPU wasn't even enabled. I was apparently using wrong version of startup code. After enabling the FPU code works as expected.
Thanks for pushing me to the right direction.
For now I consider this problem as solved.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 9:14 AM
You're showing it in the Default Handler
Get a proper Hard Fault handler, and look at what's actually faulting, the processor registers at the fault, and the immediate and preceding instructions.
Are you sure it's not a Division by Zero, Usage Fault?
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 10:05 AM
You are not first that report sprintf problem with float. Maybe try
char arr[500];
int var_int;
float var_float=0.0;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 10:37 AM
Read VECTACTIVE bits in SCB->ICSR to determine what interrupt it is in. As Tesla says, that is not the hardfault handler.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 11:09 AM
VECTACTIVE bits in SCB->ICSR read as 0x03, therefore it should be indeed hard fault vector.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 11:18 AM
I tried to increase arr size as you suggested, explicitly initialize both variables, with no effect on the result. Sprintf code shouldn't fail with any value of integer of float variable anyway.
Also, I tried to increase minimal stack and heap size from default 0x400 and 0x200 respectively (as set in supplied linker file) to somehow absurd 0x2000 bytes, with no effect as well.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 12:01 PM
That is good observation, I was a bit too quick and didn't show VECTACTIVE bits in SCB->ICSR, set to 0x03, pointing indeed to Hard fault.
I have no sources for library *printf functions in my project to step into and take a look at offending piece of code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 12:09 PM
It doesn't matter if you have the source, the processor is executing machine instructions, not your C code.
You can look at a disassembly view, or generate a listing file of ALL the code.
With some context for the Fault you can determine if it is an issue with parameters, alignment, FPU settings, bugs in the library, etc.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 2:12 PM
Yes, those are valid points, thanks. I tried to examine the MCU state at the fault state.
Bit 2 in LR is 0, therefore main stack was active at the exception moment, SP points to 0x20017e58, examining this part of memory reveals PC at address SP+0x18, that is 0x0800100A. Disassembly window shows 'vmov d0, r8, r9' instruction at this address, inside _printf_float function.
vmov makes sense in this context - moving between VFP and registers. R8 and R9 values looked benign to me. While I was at it, I checked CPACR
register and found it's all zeroes, so that FPU wasn't even enabled. I was apparently using wrong version of startup code. After enabling the FPU code works as expected.
Thanks for pushing me to the right direction.
For now I consider this problem as solved.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-11-19 5:51 PM
Frequently FPU code in startup.s or SystemInit()
Needs to occur prior to calling main(), as that might VPUSH on entry if floats used within.
Glad you were able to pin it down.
Up vote any posts that you find helpful, it shows what's working..
