2021-11-19 08: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.
2021-11-19 02: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.
2021-11-19 09: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?
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;
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.
2021-11-19 11:09 AM
VECTACTIVE bits in SCB->ICSR read as 0x03, therefore it should be indeed hard fault vector.
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.
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.
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.
2021-11-19 02: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.
2021-11-19 05: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.