I am trying to use the RTC of LPC2378 and the RTX kernel of
The below is the code of one of my tasks.
void job3 (void) __task
snprintf(FMTstring, 29, "%04d-%02d-%02d Y%03d-W%01d %02d:%02d:%02d\r",
RTC_YEAR, RTC_MONTH, RTC_DOM,
RTC_HOUR, RTC_MIN, RTC_SEC );
UART0sbWRITE( (BYTE *)FMTstring, 29 );
I found that, I need to set the "Task stack size" to 348 bytes,
otherwise I will get a stack overflow. Since I do not declare any
variable in this task, why it needs so large stack?
maybe you can learn something using uv3's static call graph that
can be generated for your binary? it indicated stack sizes, too.
task1 (ARM, 40 bytes, Stack size 8 bytes, main.o(.text))
* Max Depth = 168
* Call Chain = task1 â‡' timer_poll â‡' software_warning â‡' debug_message â‡' __c89vsprintf
* >> timer_poll
* >> debug_message
Stack space is not just a question of your local variables. It is
the variables and return addresses of the full call chain.
Formatted output is always quite complex, so you should be
carefull about how many threads you allow to print (unless you can
afford enough stack space to all threads).
Many thanks to your help.
As per your suggestion, I found the below url, and also generated
my static-call-graph.html, I am studying it.
I went back to read some articles about Stack/Heap, seems that the
parameters of a function call also consume the stack space. I think
this is why my small task needs a large stack.
Looks like, it is still a mystery to me about the Stack/heap.
"I went back to read some articles about Stack/Heap, seems that
the parameters of a function call also consume the stack space."
More than that. When you call snprintf() that is a single function
with the parameters that you supply. But snprintf() has a complex
task to do, so snprintf() will perform its job by calling a large
number of other functions, several of which may call yet other
functions. Because of this, you need stack space for local variables,
parameters and return addresses for all these function calls too,
even if their calls are hidden in the run-time-library black-box.
Some RTL functions are cheap to call. Some are expensive.
Formatted output are quite expensive functions to call, which is why
I recommend that you keep down the number of threads that needs to
use them, unless you have RAM enough to allocate big enough stacks to
all your threads.
-> which is why I recommend that you keep down
-> the number of threads that needs to use them
I am not so sure about the meaning of "threads" here. Does
"threads" mean the parameters of a function call? (Sorry for my
According to the callgraph:
job3 (ARM, 100 bytes, Stack size 40 bytes, c-main.o(.text), UNUSED)
* >> os_dly_wait (via Veneer)
* >> UART0sendKICK
* >> UART0sbWRITE
* >> __1snprintf (via Veneer)
job2 (ARM, 20 bytes, Stack size 0 bytes, c-main.o(.text), UNUSED)
job1 (ARM, 156 bytes, Stack size 16 bytes, c-main.o(.text), UNUSED)
* >> os_tsk_self (via Veneer)
* >> os_tsk_create_user (via Veneer)
* >> UART0sendKICK
* >> UART0sbWRITE
* >> UART0rbREAD
* >> strlen (via Veneer)
* >> __aeabi_memclr4
job3 only needs 100 bytes stack, but I have to set 348 bytes for
it. After reading your reply, now I realize the cause.
Is there any documentation that can help me to totally understand
the call-graph and the image-map?
__main (ARM, 8 bytes, Stack size 0 bytes, __main.o(!!!main))
* Max Depth = 64 + Unknown Stack Size
* Call Chain = __main â‡' __rt_entry â‡' __rt_lib_init â‡' _fp_init
What does the "Max Depth = 64 + Unknown Stack Size" mean?
And what does 'UNUSED' in "job3 (ARM, 100 bytes, del, del,
A thread is what your OS calls a task. It runs concurrently with
other threads in shared memory, i.e. all threads has a common set of
global variables. This is very light-weight, which is the reason why
RTOS in embedded environments implements threads. On the other hand,
it means that the developer must be very careful when accessing
common variables so one thread doesn't overwrite the output of
another thread, or reads data that has been only half-way
Many thanks to your explanation.
Tasks/Threads of RTX kernel sounds different from what I heard
about the threads on X86 platform. Looks like RTX's thread does not
belong to any process.
Thread is also a mystery to me.
In this case, you don't have a GUI or command line to handle
programs that ends or to send in parameters to main().
So in this case, you can see your application as a single process
where the tasks are almost identical to the threads inside a process
I written a small tool (now ready for STM32 G0, F1 and F4) that using Stack Walker, generate a .h with size of all stack! Try it!
View all questions in Keil forum