EmbDev.net

Forum: ARM programming with GCC/GNU tools hardfault when using snprintf


von Dennis E. (dempa)


Rate this post
useful
not useful
Im trying to use snprintf but with the following arguments
      char buf[100];
      char *wld = "WORLD";
      char buffer [100];
      int n = 10;
      snprintf(buffer, sizeof(buffer), "%i", n);
and it doesnt work.
I end up with hardfault on the stm32 that im using.

 If i use the below statement it works fine
snprintf(buf, sizeof(buf), "hello %s", wld);

Im quite new to programing so what could i have missed


/Dennis

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Dennis Eriksson wrote:
> Im trying to use snprintf but with the following arguments
>       char buf[100];
>       char *wld = "WORLD";
>       char buffer [100];
>       int n = 10;
>       snprintf(buffer, sizeof(buffer), "%i", n);
> and it doesnt work.
> I end up with hardfault on the stm32 that im using.

Maybe a problem with the heap-handling (sbrk implementation, 
heap-start-adress used by sbrk). Please create a minimal example with 
all source-codes and linker-script to reproduce this, pack them into a 
zip-archive and attach it to a message.

You may use this example, insert your snprintf code and try again:
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/#cm3_cpp1

>  If i use the below statement it works fine
> snprintf(buf, sizeof(buf), "hello %s", wld);

This may work since the compiler already replaces it by somthing like 
strcpy(buf,"hello WORLD") and there is no call to the libc's snprintf 
during runtime.

von Dennis E. (dempa)


Attached files:

Rate this post
useful
not useful
Hi Martin

First of all thank you for taking your time to help me. Attached you 
will find my project (stripped to the bare bone).

I tryed you project and i got it built, but i get in to problems when 
trying to get it in to my stm32. I will try some more on.

So please have a look on my files. (propobly its in the .ld file)

/Dennis

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Dennis Eriksson wrote:

> Attached you will find my project (stripped to the bare bone).
Not at all! "Bare bone" would be:
- one Makefile
- one Linkerscript
- Startup-Code in one file (either .c or .S)
- one C source file.

> I tryed you project and i got it built, but i get in to problems when
> trying to get it in to my stm32. I will try some more on.
>
> So please have a look on my files. (propobly its in the .ld file)

I just had a quick look into your files:

(1) don't use arm-*-ld for linking use the frontend (arm-*-gcc)
(2) pass the -mcpu -mthumb option too when using gcc for linking.
With this there is no need or hard-code pathes into the makefile or even 
copy files from the toolchains library-path into the project. Fix this 
first to make sure that the correct libc is linked.

(3) There is no need to add an output-section for the heap into the 
linker-script as long as you keep the stack-placement as is (starting 
from top of RAM). There should be no need to modify the linker-script.
(4) using _end, __end or _ebss for heap-start (in sbrk) should do, they 
all should have the same value. No need to add an additional variable 
...HEAP_START...

von Clifford S. (clifford)


Rate this post
useful
not useful
Martin Thomas wrote:
> Maybe a problem with the heap-handling (sbrk implementation,
> heap-start-adress used by sbrk).

I don't see where the heap would be used in the posted code.

>>  If i use the below statement it works fine
>> snprintf(buf, sizeof(buf), "hello %s", wld);
>
> This may work since the compiler already replaces it by somthing like
> strcpy(buf,"hello WORLD") and there is no call to the libc's snprintf
> during runtime.

The compiler cannot do that!  That would require the compiler to 
understand the semantics of the library, and that does not happen - even 
for functions in the standard library.


The code creates large arrays on the stack, and the formatted I/O 
functions themselves require a significant amount of stack (4 kbytes 
would not be unusual).  My guess would be that there is insufficient 
stack allocation.  The linker script sets __Stack_Size to 1024 and 
_Minimum_Stack_Size to 0x100, I suggest that these are too small to 
support the formatted I/O functions.

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> Martin Thomas wrote:
>> Maybe a problem with the heap-handling (sbrk implementation,
>> heap-start-adress used by sbrk).
>
> I don't see where the heap would be used in the posted code.
Implicitly by snprintf? When using newlib's printf different syscalls 
are "requested" by the linker. Among them sbrk with is used for dynamic 
memory allocation.

>>>  If i use the below statement it works fine
>>> snprintf(buf, sizeof(buf), "hello %s", wld);
>>
>> This may work since the compiler already replaces it by somthing like
>> strcpy(buf,"hello WORLD") and there is no call to the libc's snprintf
>> during runtime.
>
> The compiler cannot do that!  That would require the compiler to
> understand the semantics of the library, and that does not happen - even
> for functions in the standard library.
As far is I understand the gcc builtins are made to "understand the 
sematics" of some standard-library-functions.
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#Other-Builtins
At least I have seen that a printf with all constant parameters has been 
replaced by puts. During "single-stepping" there has been no call to the 
libc's printf, puts has been called directly. So far I did not care too 
much about this so this is just a remark, please correct me if I'm 
wrong.

> The code creates large arrays on the stack, and the formatted I/O
> functions themselves require a significant amount of stack (4 kbytes
> would not be unusual).  My guess would be that there is insufficient
> stack allocation.  The linker script sets __Stack_Size to 1024 and
> _Minimum_Stack_Size to 0x100, I suggest that these are too small to
> support the formatted I/O functions.
In this special case - a ld-script and startup-code based on the 
templates that come with the STM32 library - the value does not set the 
real stack size but is just used to create a "dummy" output-section so 
the linker will thow an error message is there is not enough space left. 
As far as I have seen the start of stack (stack-pointer value at 0x0) is 
set to the top of RAM so there should(?!) be enough free RAM for an 
application with just a few init-functions and a single call to 
snprintf.

von Clifford S. (clifford)


Rate this post
useful
not useful
Martin Thomas wrote:
> Clifford Slocombe wrote:
>> Martin Thomas wrote:
>> I don't see where the heap would be used in the posted code.
> Implicitly by snprintf?

I'd be very disturbed is snprintf() required dynamic memory allocation 
or that a non-standard function would be optimised away.

On all else I bow to your more extensive knowledge.

von Dennis E. (dempa)


Rate this post
useful
not useful
Thank you Thomas

After fixing the linking as you suggested i got it to work.

Now i only need to do some clean up in my makefile.

/Dennis

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> I'd be very disturbed is snprintf() required dynamic memory allocation

This is actually quite common in certain C libraries. Some 
optimized-for-µC libs provide limited stack-only variants of standard 
functions. Exotic functionality is often omitted. Popular candidates in 
printf-type functions are format specifiers for floats.

> or that a non-standard function would be optimised away.

http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Other-Builtins.html#Other-Builtins

Besides, why would snprintf() be non-standard (ISO C99, B.18)?

Regards
Marcus
http://www.doulos.com/arm/

von Clifford S. (clifford)


Rate this post
useful
not useful
Marcus Harnisch wrote:
> Clifford Slocombe wrote:
>> I'd be very disturbed is snprintf() required dynamic memory allocation
>
> This is actually quite common in certain C libraries. Some
> optimized-for-µC libs provide limited stack-only variants of standard
> functions.

Is that not what we are talking about here? WinARM uses Newlib which is 
exactly an "optimized-for-µC" library.

>
> Besides, why would snprintf() be non-standard (ISO C99, B.18)?
>
Doh!? Where have I been!?

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.