Taming the stack usage of embedded applications

From TASTE
Revision as of 12:35, 21 November 2016 by Thanassis Tsiodras (talk)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

TASTE primarily addresses safety-critical on-board software. For embedded targets, it uses RTEMS.

A common theme that arises while supporting our TASTE users, is crashes or issues that relate to stack usage.

This article discusses how TASTE helps you to "tame" the stack requirements of your targets.

Note that as of Nov 21st, 2016, the TASTE build system reserves up-front the amount of stack space specified in the Concurrency View (set by default to 50K per thread, but can be modified on a per-thread basis via the Concurrency View editor taste-edit-concurrency-view). This should address most stack issues.

Iterate faster

To ease your debugging of stack issues, you should use the techniques we offer to execute under QEMU so you don't have to work on target (much faster executions, and therefore, iteration cycles - debug/run, debug/run, etc).

Check if your crashes reproduces there - if they don't, the crash is probably related to your HW setup.

Debugging

On startup

So you run your binary under QEMU, and it just crashes upon startup.

Your application may need more stack to bootstrap - i.e. your startup functions may be trying to reserve more stack space than available; which means you need to tell RTEMS to reserve more total stack for your application.

You can modify the runtime (PolyORB-HI-C) to tell it to use more stack space.

The relevant file is po_hi_common.h and is located in the TASTE VM in /home/assert/tool-src/po-hi-c/include. Open this file and uncomment the following line:


   --- po_hi_common.h      (revision 8033)
   +++ po_hi_common.h      (working copy)
   @@ -58,6 +58,7 @@
   
     */
   +   #define CONFIGURE_EXTRA_TASK_STACKS                   (__PO_HI_NB_TASKS * 30000 )
    #ifdef __PO_HI_NB_PORTS
       #define CONFIGURE_MAXIMUM_POSIX_MUTEXES              __PO_HI_NB_TASKS + 10 + __PO_HI_NB_PORTS
       #define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES  __PO_HI_NB_TASKS + 10 + __PO_HI_NB_PORTS


Then you need to recompile the runtime:

   $ cd ~/tool-src ; make

This modification would give you an additional 30K of stack for each of your configured tasks (__PO_HI_NB_TASKS is automatically set from your design, so don't worry about it). If you want you can of course add a specific number here, that doesn't depend on the number of tasks in your design.

At runtime

Or maybe one of your tasks appears to mysteriously die during runtime... could it be that it runs out of stack?

You have two tools to use here.

Monitoring

One is to augment your user code with something like this:

   extern void rtems_stack_checker_report_usage();
   rtems_stack_checker_report_usage();

At runtime, you will be able to see how close your tasks are to exhausting their stack allocation:

   Stack usage by thread
       ID      NAME    LOW          HIGH     CURRENT     AVAILABLE     USED
   0x09010001  IDLE 0040044620 - 004004561F 00400455C0      4080   Unavailable
   0x0B010001       0040045628 - 0040047627 00400472E8      8176   Unavailable
   0x0B010002       00400476C0 - 0040053A0F 00400536C8     49984   Unavailable

The first two lines will be RTEMS-related tasks - everything after them will show you numbers that won't exceed 50K; the default stack size of TASTE tasks (unless you edited your Concurrency view). The lower the "AVAILABLE" column goes, the closer your task is to exhausting its stack.

Stack canaries

RTEMS can also place stack canaries (magic values) at the top of each task's stack, and then check that these values are proper - if not, one task has exceeded its space and overflown. To enable this checker, go in po_hi_common.h and uncomment...

   #define CONFIGURE_STACK_CHECKER_ENABLED

Then rebuild POHIC and Ocarina (with "cd ~/tool-src ; make"). This will enable the checks, which will report back immediately the moment they detect a stack overrun.

What if I need more stack per task?

If you do, you'll need to edit your Concurrency view - spawn taste-edit-concurrency-view and edit the stack requirements to your needs.

Faster way to recompile POHIC and Ocarina

The "cd ~/tool-src ; make" rebuilds everything - if you need a faster rebuild cycle for POHIC and Ocarina, every time you change something in po_hi_common.h you can also selectively build these two only:

   $ cd ~/tool-src
   $ make configure-po-hi-c build-po-hi-c install-po-hi-c  \
          configure-po-hi-ada build-po-hi-ada install-po-hi-ada \
          configure-ocarina build-ocarina install-ocarina

Good luck with your bug hunting!