Thursday, August 7, 2008

Checking Task Stack Overflow in DSP/BIOS

For embedded system, reliability is of great importance. At the later stage of development, with all functionality are tested working, we are left with this challenging work of optimizing speed and memory consumptions of each process thread in our system. Of course we all want to have freedom in assigning stack size to ensure that there is no overflow even when there are certain unfavorable events happen to our system. Yet, unfortunately, the nature of our work requires us to work in a box.
How can we check the task overflow?
In DSP/BIOS, we can make use of task-specific API to check Stack overflow for each task thread.
Firstly, How Task Specific Stacks are used for context switching and function Calling?

at Calling Function
1. Content of RETA to Stack Pointer’s TOS. Content of CFCT to System Stack Pointer’s TOS.
2. Return address (PC+1) to RETA. Loop Context to CFCT.

at Returning Function
1. Content RETA to PC. Content of CFCT to Loop Context bit.
2. TOS of Stack and SysStack to RETA and CFCT respectively.

Note:

TOS – Top of Stack
RETA – Return address register
CFCT – Control flow context Register
PC – Program Counter

Context Switch for DSP/BIOS threads

DSP/BIOS has 4 types of threads as arranged in the following in the order of highest priority to lowest.
1. HWI ( hardware Interrupt )
2. SWI ( software Interrupt )
3. TSK ( Task) and
4. IDL(System Task) – Inaccessible lowest priority system thread.

HWIs and SWIs use DSP/BIOS general Stack and SysStack as these threads will not be blocked until the processing is done. On the other hand, each task uses its dedicated task-specific Stack and SysStack. This is because tasks are blocking threads (can be suspended and preempted by higher priority threads) and it is needed to preserve context information for preemption context switch as well as its own function callings.

Allocation of Stack size and SysStack size for each task requires us to ensure that the stack doesn’t overflow while making the stack size (and thus the memory usage ) to be minimum.

DSP/BIOS Object Task_statistic can be used to determine the actual usage of stack, by reading the statistics at the end of thread before exiting. After observing the actual usage, the stack size can be adjusted. For detailed example, Refer to [ Ref: SPRU 432F DSP/BIOS User Guide, Chapter 4 Thread Scheduling ]

TSK_Stat statbuf; /* declare buffer */
TSK_stat(TSK_self(), &statbuf); /* call func to get status */
if (statbuf.used > (statbuf.attrs.stacksize * 9 / 10)) {
LOG_printf(&trace, "Over 90% of task's stack is in use.\n")
}

1 comment:

Ricardo said...

Nice description of RETA and TOS, etc. Have you tried resuming a DSP/BIOS task at its entry point (i.e. not a previous position of task program counter). Due to resource constraints we are trying to avoid task delete/ create pattern...I assume this would require some manual manipulation of task RETA and stack...Any guidance in this regard will be appreciated.