cancel
Showing results for 
Search instead for 
Did you mean: 

[SOLVED] Sprintf with floating point number crashing into hard fault on STM32L476, working fine with STM32F091

jaromir sukuba
Associate II

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

0693W00000GYFKSQA5.pngbut 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.

0693W00000GYFJyQAP.pngI 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"

0693W00000GYFMYQA5.pngI 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.

1 ACCEPTED SOLUTION

Accepted Solutions

Yes, those are valid points, thanks. I tried to examine the MCU state at the fault state.

0693W00000GYGsHQAX.pngBit 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.

View solution in original post

21 REPLIES 21

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?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
MM..1
Chief II

You are not first that report sprintf problem with float. Maybe try

char arr[500];
int var_int;
float var_float=0.0;

TDK
Guru

Read VECTACTIVE bits in SCB->ICSR to determine what interrupt it is in. As Tesla says, that is not the hardfault handler.

If you feel a post has answered your question, please click "Accept as Solution".

VECTACTIVE bits in SCB->ICSR read as 0x03, therefore it should be indeed hard fault vector.

0693W00000GYGVqQAP.png

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.

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.

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Yes, those are valid points, thanks. I tried to examine the MCU state at the fault state.

0693W00000GYGsHQAX.pngBit 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.

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..