Reputation: 51
I have an opensource project (https://github.com/WhiteFossa/yiff-l), where I use STM32F103 MCU.
In firmware I have a lot of sprintf's with float parameters, for example:
char buffer[32];
sprintf(buffer, "Power: %.1fW", power);
I used to use pretty old arm-none-eabi xpack for a long time (IIRC it was 9.3.1 version) and everything was fine.
Then I had to reinstall my fedora, and of course I've got a newer version of arm-none-eabi. My project stopped to compile, I fixed some code and now it compiles again, but produces hardfaults on any sprintf with float.
If I exclude -u _printf-float linker flag, then hardfaults are gone, but of course I don't get float representations in my strings.
I'm pretty sure that problem is not in mine code, I've even tried to put sprintf as a first line in a main(), and still have the same problems.
What can cause such weird behaviour? How can I debug it? (never used to debug ARM disassembly).
P.s. I've tried to install older arm-none-eabi xpacks, but without any luck - the problem remains.
P.p.s. I've tried to play with optimization settings/changed release to debug and vice versa, set 4x more stack in sections.ld - everything without success.
Any help will be appreciated much.
Upvotes: 3
Views: 2042
Reputation: 51
Finally I was able to get my firmware running, with help of https://github.com/mpaland/printf
I.e. I've just get rid of Newlib's sprintf() in my code.
Upvotes: 2
Reputation: 395
Finding hardfaults is complex and might, very often, be frustrating. In most cases I've faced hardfaults I just jumped to using one hardware debugger. The one I use for Cortex-M devices is Segger's J-Tag Pro. There are other models, cheaper, much cheaper.
What can cause such weird behaviour? As you have identified your problem is masked-out when sprintf
is disabled. My best guess, it is more than likely caused by a buffer overrun in your output buffer or by a buggy library code. Some sprintf
implementations use heap memory allocations and don't check for NULL
returns. There are BSP implementations using Fee-RTOS that require some more tuning for enabling dynamic memory management.
If it hardfaults even using large buffers, then this might be caused by internal memory allocations in sprintf
. You can try to use another library. To my best understanding, newlib-nano
is known to cause this error in some scenarios.
In some cases it is a matter of increasing the stack size for the tasks where sprintf
/ snprintf
are called and the global heap size.
How can I debug it? Probably the only solution would be using one hardware debugger in combination with one full IDE like Eclipse. Here is a bit of information that will give you some guidelines. The J-Link Edu Mini hardware debugger is fairly affordable, yet there are more options around you would also find useful.
The solution I gave to this same problem with a similar CPU (Kinetis K22, from former Freescale now NxP) was to create my own float to string conversion function. It increased performance noticeably (no more malloc
s), hardfault errors were gone and I trimmed the per-task heap size to what I really needed.
Upvotes: 2
Reputation: 9763
Only thing I can think of while seeing this code is that the value of power is huge:
double power = 11111111111111111111111111111111111111111111.2;
char buffer[32];
sprintf(buffer, "Power: %.1fW", power);
printf("%s\n", buffer);
If that isn't the case there must be some UB somewhere else
Upvotes: 1