Stack sizes: STM32L-Discovery
Hi,
I am having a bit of difficulty setting the stack size to allow me to have mutiple tasks running on the STM32L-Discovery.
At present, I have STACKSIZE = 32 and the following as part of the main task:
---------
static CTL_TASK_t main_task; // Main task
CTL_TASK_t new_task1; // First task
CTL_TASK_t new_task2; // Second task
static unsigned task1Stack[ STACKSIZE ]; // Stack for task 1
static unsigned task2Stack[ STACKSIZE ]; // Stack for task 2
...
memset(task1Stack, 0xb1, sizeof(task1Stack));
memset(task2Stack, 0xb2, sizeof(task2Stack));
task1Stack[ 0 ] = task1Stack[ 1 + STACKSIZE ] = 0xfacefeed;
task2Stack[ 0 ] = task2Stack[ 1 + STACKSIZE ] = 0xfacef000;
ctl_task_run( &new_task1, 1, task1, 0, "task1", STACKSIZE, task1Stack + 1, CALLSTACKSIZE );
ctl_task_run( &new_task2, 2, task2, 0, "task2", STACKSIZE, task2Stack + 1, CALLSTACKSIZE );
---------
This works fine but if I add a third task, in exactly the same manner, I get the hardfault handler and the board screws up. If I reduce the stack size to 16, then adding a third task works ok. Note, the tasks are relatively simple such as simply incrementing a variable, or waiting for an event.
How do I correctly define the stack size for this device/my tasks? There must be a more definitive approach than simply increasing or decreasing STACKSIZE. Can I make more use of the debug tools?
Thanks in advance
-
task1Stack[ 0 ] = task1Stack[ 1 + STACKSIZE ] = 0xfacefeed;
This is out of array range by 8 bytes, array index in C is from 0 (included) to ElementCount (excluded). Next lines same problem.
task1Stack[ 0 ] = task1Stack[ STACKSIZE - 1] = 0xfacefeed;
ctl_task_run( &new_task1, 1, task1, 0, "task1", STACKSIZE-1, task1Stack + 1, CALLSTACKSIZE );
-
The Rowley Guys use the definition:
unsigned someStack[1+STACKSIZE+1];
when making allocations for task stack space. The 1+ and +1 additions to stack size in the definition account for the 8 bytes you identified as out of bounds. The actual stack used by the CTL tasking system will start at address someStack[1] and continue to someStack[STACKSIZE]. someStack[0] and someStack[STACKSIZE + 1] are effectively reserved addresses.
Go look at their examples, particularly where the array is declared that will later house the task stack. The arrangement Crossworks uses for defining the stack has a several benefits.
- You can at the application layer (or task layer) deal with stack size in units of memory that are comfortable for your program, using only the STACKSIZE macro. This allows the hiding of implementation details of the task from the application.
- You can check for stack overrun and underrun errors by checking the contents of the array (someStack[] in this example) at address 0 and address STACKSIZE+1, and verifying that the value 0xfacefeed is at those addresses.
The assumption is that an underrun or overrun will write some value other than 0xfacefeed into the addresses at someStack[0] or someStack[STACKSIZE + 1]. In my experience with CTL, this assumption has always held true.
Our company has a kernel that is based on the Rowley CTL. The Kernel actively checks the stack boundaries and asserts if there is an overrun or underrun detected. It is quite handy.
Change your definitions for:
static unsigned task1Stack[ STACKSIZE ]; // Stack for task 1 static unsigned task2Stack[ STACKSIZE ]; // Stack for task 2
to:
static unsigned task1Stack[ 1 + STACKSIZE + 1]; // Stack for task 1 static unsigned task2Stack[ 1 + STACKSIZE + 1]; // Stack for task 2
Please sign in to leave a comment.
Comments
3 comments