Recovering the C Stack in a Micrium RTOS‑Based Application

When using the Micrium kernels, it’s possible for the C startup stack to be lost, thus reducing the amount of RAM available to your embedded application. This note shows how you can completely recover this valuable RAM for use as one of your task stacks.

Most embedded applications are written in C, and upon reset, the CPU is provided the address of the startup code (i.e., boot code) from the default vector table. On a Cortex-M, the vector table also contains the initial value of the stack pointer and is automatically assigned to the CPU’s main stack pointer (MSP). For the IAR toolchain (i.e., EWARM), the storage area for the initial stack is set up by the linker command file, and the stack space itself is called the CSTACK. Once the startup code completes, the MSP is generally left untouched and the CSTACK is thus used to process interrupt service routines (ISRs).

In EWARM, the size (in bytes) and storage for the CSTACK is defined in the linker command script as shown in the following statements (see your MCU’s .icf file for your project):

define symbol __ICFEDIT_size_cstack__  = 0x400;
define block  CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__ { };

The default is 1 Kbytes and is generally sufficient for typical startup code. However, if your startup code ever requires more (or less), you can simply change the above value to accommodate your needs.

As a side note, it’s worth mentioning that the Cortex-M contains an additional stack pointer called the process stack pointer (PSP) which is used for task level code.

Micrium RTOSes provide the ability to use an internal ISR stack instead of the default CSTACK. This is usually done for two reasons: first to allow the application code to control the ISR stack size; and second, to allow the RTOS to compute and possibly display ISR stack usage at run-time. For µC/OS-III, the ISR stack is called OSCfg_ISRStk[] and is often set to less than 512 bytes. Unfortunately, the side effect of allocating a separate stack for ISRs is that the CSTACK is left unused and thus lost.

As shown in the code snippet below (again, using IAR’s EWARM), it’s quite easy to recover the storage area used for the CSTACK, and in fact, assign it to one of the application tasks. It’s important, however, that the CSTACK be used for a task that is created after multitasking has started, and thus not while the CSTACK is still being used as part of the initialization process of your application.

#pragma section = “CSTACK”

OS_TCB  MyTaskTCB;


static  void  AppTaskCreate (void)
{
    OS_ERR       err;
    CPU_STK     *cstack_base_addr;
    CPU_INT32U   cstack_size;

 
    cstack_base_addr = (CPU_STK *)__segment_begin("CSTACK");  // Example of CSTACK reuse                        
    cstack_size      = (CPU_INT32U)__segment_size("CSTACK") 
                     / sizeof(CPU_STK);                       // Convert to stack units instead of bytes
     
    OSTaskCreate(&MyTaskTCB,                                  // Create the task                                
                 “My Task”,
                  MyTask,
                  0u,
                  MY_TASK_PRIO,
                  cstack_base_addr,                           // The CSTACK base address
                  0u,
                  cstack_size,                                // The size of the CSTACK
                  0u,
                  0u,
                  0u,
                 (OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 &err);
    // Check ‘err’ for possible errors
}

Jean J. Labrosse
Software Architect, Silicon Labs

Sharbel Bousemaan
Software Engineer, Silicon Labs

Tags: , , , ,

Questions or Comments?

Have a question or a suggestion for a future article?
Don't hesitate to contact us and let us know!
All comments and ideas are welcome.