在uC/OS-II系统中,创建任务的时候除了需要配置任务的优先级以外,还需要对任务堆栈大小进行分配。而对于单片机这种RAM并不是非常大的微控制器来说,RAM显得格外珍贵,如果任务堆栈分配大了,会导致RAM不够用,分配小了任务运行又会受到影响,甚至系统的崩溃,所以在创建任务的时候合适的堆栈大小分配很重要。

uC/OS-II中任务堆栈的作用主要有两个,一是在任务运行的时候保存任务的一些局部变量,二是当任务挂起时,保存任务现场,也就是CPU寄存器的值。uC/OS-II系统是在OSTaskCreate();中的OSTaskStkInit();来确定堆栈地址的。虽然任务堆栈大小也可以通过设计者认为去测算出来,但是要考虑的东西太多,而且也不能十分精确。

实际上uC/OS-II在OS_TASK.C中提供了很多有关任务管理的功能函数,包括:
建立任务OSTaskCreate()、建立扩展任务OSTaskCreateExt()、删除任务OSTaskDel()等,其中还有一个关于堆栈的函数就是堆栈检验OSTaskStkChk(),这个函数的检测原理就是顺着堆栈的栈底开始计算空闲的堆栈空间大小,实现方法是统计存储值为0的连续堆栈入口的数量,直到发现存储值不为0的堆栈入口,这样就可以知道实际占用的堆栈大小了。
该函数的调用和运行需要将OS_TASK_STAT_STK_CHK_EN和OS_TASK_CREATE_EXT_EN进行使能,而检测的任务对象是通过任务的优先级来获取的,即:INT8U prio,并且需要定义一个OS_STK_DATA的结构体变量来存放堆栈情况的值,
其中的:
INT32U OSFree 就是剩余的堆栈大小
INT32U OSUsed 是已经使用的堆栈大小。
OSTaskStkChk()源码:
INT8U OSTaskStkChk (INT8U prio,OS_STK_DATA *p_stk_data){OS_TCB *ptcb;OS_STK *pchk;INT32U nfree;INT32U size;#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;#endif#if OS_ARG_CHK_EN > 0uif (prio > OS_LOWEST_PRIO) { /* Make sure task priority is valid */if (prio != OS_PRIO_SELF) {return (OS_ERR_PRIO_INVALID);}}if (p_stk_data == (OS_STK_DATA *)0) { /* Validate 'p_stk_data' */return (OS_ERR_PDATA_NULL);}#endifp_stk_data->OSFree = 0u; /* Assume failure, set to 0 size */p_stk_data->OSUsed = 0u;OS_ENTER_CRITICAL();if (prio == OS_PRIO_SELF) { /* See if check for SELF */prio = OSTCBCur->OSTCBPrio;}ptcb = OSTCBPrioTbl[prio];if (ptcb == (OS_TCB *)0) { /* Make sure task exist */OS_EXIT_CRITICAL();return (OS_ERR_TASK_NOT_EXIST);}if (ptcb == OS_TCB_RESERVED) {OS_EXIT_CRITICAL();return (OS_ERR_TASK_NOT_EXIST);}if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0u) { /* Make sure stack checking option is set */OS_EXIT_CRITICAL();return (OS_ERR_TASK_OPT);}nfree = 0u;size = ptcb->OSTCBStkSize;pchk = ptcb->OSTCBStkBottom;OS_EXIT_CRITICAL();#if OS_STK_GROWTH == 1uwhile (*pchk++ == (OS_STK)0) { /* Compute the number of zero entries on the stk */nfree++;}#elsewhile (*pchk-- == (OS_STK)0) {nfree++;}#endifp_stk_data->OSFree = nfree * sizeof(OS_STK); /* Compute number of free bytes on the stack */p_stk_data->OSUsed = (size - nfree) * sizeof(OS_STK); /* Compute number of bytes used on the stack */return (OS_ERR_NONE);}
INT8U OSTaskCreateExt (void (*task)(void *p_arg),void *p_arg,OS_STK *ptos,INT8U prio,INT16U id,OS_STK *pbos,INT32U stk_size,void *pext,INT16U opt){OS_STK *psp;INT8U err;#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICAL_IEC61508if (OSSafetyCriticalStartFlag == OS_TRUE) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#if OS_ARG_CHK_EN > 0uif (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */return (OS_ERR_PRIO_INVALID);}#endifOS_ENTER_CRITICAL();if (OSIntNesting > 0u) { /* Make sure we don't create the task from within an ISR */OS_EXIT_CRITICAL();return (OS_ERR_TASK_CREATE_ISR);}if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... *//* ... the same thing until task is created. */OS_EXIT_CRITICAL();#if (OS_TASK_STAT_STK_CHK_EN > 0u)OS_TaskStkClr(pbos, stk_size, opt); /* Clear the task stack (if needed) */#endifpsp = OSTaskStkInit(task, p_arg, ptos, opt); /* Initialize the task's stack */err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);if (err == OS_ERR_NONE) {if (OSRunning == OS_TRUE) { /* Find HPT if multitasking has started */OS_Sched();}} else {OS_ENTER_CRITICAL();OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Make this priority avail. to others */OS_EXIT_CRITICAL();}return (err);}OS_EXIT_CRITICAL();return (OS_ERR_PRIO_EXIST);}
---------------------
作者:forgot
链接:https://bbs.21ic.com/icview-3285474-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。













![[pascal入门]数组](https://dn-anything-about-doc.qbox.me/c/7-13.jpg)



