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
Micrium Founder
Sharbel Bousemaan
Weston Embedded Solutions Co-founder