UCOS操作系统堆栈浅谈.docx
《UCOS操作系统堆栈浅谈.docx》由会员分享,可在线阅读,更多相关《UCOS操作系统堆栈浅谈.docx(7页珍藏版)》请在冰豆网上搜索。
![UCOS操作系统堆栈浅谈.docx](https://file1.bdocx.com/fileroot1/2023-1/24/35439f50-6011-4ed2-823d-4ddbf6bf6de1/35439f50-6011-4ed2-823d-4ddbf6bf6de11.gif)
UCOS操作系统堆栈浅谈
UCOS操作系统堆栈浅谈
1声明堆栈大小
在uc/os-ii操作系统的任务切换和中断处理过程中,需要保存处理器的内部寄存器和变量的值,这就
要求每个任务都有自己的堆栈空间。
堆栈必须声明为OS_STK类型,并且由连续的内存空间组成,可以静态
分配空间(在编译时分配),也可以动态分配堆栈空间(在运行时分配)。
由于采用动态分配方式,会导致
内存中含有大量内存碎片,因此不推荐使用动态分配方式。
其两种声明方式如下:
静态分配方式:
staticOS_STKTaskStk[StkSize];
或者
OS_STKTaskStk[StkSize];
动态分配方式:
OS_STK*pstk;
pstk=(OS_STK*)malloc(StkSize);
if(pstk!
=(OS_STK*)0)//判断堆栈分配是否成功
{
printf("CreateTaskStkSuccess");
}
2设置堆栈生产方向
uc/os-ii操作系统支持2中堆栈生长方向。
即可从高地址往低地址生长,也可以由低地址往高地址生长。
在调用OSTaskCreate()或者OSTaskCreateExt()创建任务的时候由于必须知道堆栈的生长方向,所以要在OS_CPU.H
文件中设置任务堆栈的生长方向。
#defineOS_STK_GROWTH1//设置堆栈是从上往下长的
OSTaskCreate(Task,pdata,&TaskStk[StkSize-1],prio);
或者
#defineOS_STK_GROWTH0//设置堆栈是从下往上长的
OSTaskCreate(Task,pdata,&TaskStk[0],prio);
当然也可以这样编写创建任务的以支持堆栈的从上往下和从下往上生长
#ifOS_STK_GROWTH==1
OSTaskCreate(Task,pdata,&TaskStk[StkSize-1],prio);
#else
OSTaskCreate(Task,pdata,&TaskStk[0],prio);
#endif
3堆栈检验
为控制产品成本,有时需要确定任务实际需要的堆栈空间的大小,避免为任务分配过多的对战空间,从而
减少应用程序代码所需的RAM数量。
uc/os-ii系统提供OSTaskStkChk()函数用以确定任务实际需要的堆栈空间。
使用堆栈检验功能必须做一下几点:
1.在OS_CFG.H文件中设置OS_TASK_CREATE_EXT为1
2.使用OSTaskCreateExt()创建任务,并且赋予任务比实际需要多一点的空间。
可以在任何任务中调用STaskStkChk()函数,对任何用OSTaskCreateExt()建立的任务进行堆栈检验。
3.在OSTaskCreateExt()中,将参数opt设置为:
OS_TASK_OPT_STK_CHK+OS_TASK_OPT_STK_CLR
4.把需要进行检测的任务的优先级作为OSTaskStkChk()的参数并调用
应使自己的应用程序运行足够长的时间,并且经历最坏的堆栈使用情况,这样才能得到正确的树木。
一旦得到所需要的对单需求,就可以重新设置堆栈的最终大小了。
在堆栈检验中,所得到的只是一个大智的堆栈使用情况,并不能说明堆栈的使用全部实际情况。
4堆栈溢出
在实际的项目中,由于产品的升级需要可能一个任务会经常修改,所需要的实际堆栈大小并不能很好的确定,即便使用堆栈检验功能后,在后续产品的升级过程中变量的增加会导致堆栈不够用。
而在调试的过程中,如果没有堆栈溢出的报警机制,一旦堆栈出现溢出,这个问题是很难一时被发现的。
在这里,我建议在系统开始运行前,把每个任务的堆栈栈顶初始化一个值,每次出现任务切换的时候就读取对应栈顶的值,如果和初始化栈顶值相同的话就说明没有问题,如果值出现改变的话那么出现堆栈溢出的概率至少达到90%以上,这样可以避免出现堆栈溢出而不能发现的尴尬。
下面是个项目的一部分,删了一些,可供参考。
#include"user/lc_sqce_aj.h"
#include"include_all.h"
/*sizeofeachtask'sstacks(#ofWORDs)*/
#defineTASK_START_STK_SIZE128
#defineBUZZER_STK_SIZE128
#defineCTRLMSG_STK_SIZE128
#defineSTORDEV_MOUNT_STK_SIZE512
#defineMODE_SWITCH_STK_SIZE512
#defineMODE_EXE_STK_SIZE2000
#defineTWO_CHANNEL_REC_SIZE512
#defineALARM_STK_SIZE128
#defineTASK_STK_SIZE512
/*applicationtasks*/
#defineTASK_START_ID0
#defineTASK_1_ID1
#defineTASK_2_ID2
#defineTASK_3_ID3
#defineTASK_4_ID4
#defineTASK_5_ID5
#defineTASK_6_ID6
#defineTASK_7_ID7
#defineTASK_8_ID8
#defineTASK_9_ID9
#defineTASK_10_ID10
#defineTASK_11_ID11
#defineTASK_12_ID12
#defineTASK_13_ID13
#defineTASK_14_ID14
#defineTASK_15_ID15
/*applicationtaskspriorities*/
#defineTASK_START_PRIO0
#defineTASK_1_PRIO1
#defineTASK_2_PRIO2
#defineTASK_3_PRIO3
#defineTASK_4_PRIO4
#defineTASK_5_PRIO5
#defineTASK_6_PRIO6
#defineTASK_7_PRIO7
#defineTASK_8_PRIO8
#defineTASK_9_PRIO9
#defineTASK_10_PRIO10
#defineTASK_11_PRIO11
#defineTASK_12_PRIO12
#defineTASK_13_PRIO13
#defineTASK_14_PRIO14
#defineTASK_15_PRIO15
/*seetaskstacks*/
OS_STKTaskStartStk[TASK_START_STK_SIZE];
OS_STKBuzzerStk[BUZZER_STK_SIZE];
OS_STKCtrlmsgStk[CTRLMSG_STK_SIZE];
OS_STKStorDevStk[STORDEV_MOUNT_STK_SIZE];
OS_STKModeSwitchStk[MODE_SWITCH_STK_SIZE];
OS_STKModeExeStk[MODE_EXE_STK_SIZE];
staticvoidTaskStart(void*p_arg);//函数声明
staticvoidTaskStartCreateTasks(void);
voidInitStackMark(void);
//************************************************************************************
//*函数名:
main
//*返回值:
N/A
//*参数:
N/A
//*函数说明:
主函数
//*作者:
啊呆
//***********************************************************************************
voidmain(void)
{
INT8Uerr;
//initializeuC/OS-II
OSInit();
//installuC/OS-II'scontextswitchvector
IRQSetVect(uCOS,OSCtxSw);
OSTaskCreateExt(TaskStart,
(void*)0,
&TaskStartStk[TASK_START_STK_SIZE-1],
TASK_START_PRIO,
TASK_START_ID,
&TaskStartStk[0],
TASK_START_STK_SIZE,
(void*)0,
OS_TASK_OPT_STK_CLR+OS_TASK_OPT_STK_CHK);
OSTaskNameSet(TASK_START_PRIO,"StartTask",&err);
//startmultitasking
OSStart();
}
//*********************************************************************************
//*函数名:
TaskStart
//*返回值:
N/A
//*参数:
void*p_arg
//*函数说明:
创建TaskStart任务
//*作者:
啊呆
//********************************************************************************
staticvoidTaskStart(void*p_arg)
{
#ifOS_CRITICAL_METHOD==3
OS_CPU_SRcpu_sr;
#endif
//preventcompilerwarning
p_arg=p_arg;
//installuC/OS-II'sclocktickISR
OS_ENTER_CRITICAL();
IRQSetVect(TMR1_VEC,OSTickISR);
OSSetTickRate(lc_clk_get_freq(CLK_SYS_SEL),OS_TICKS_PER_SEC);
OS_EXIT_CRITICAL();
//initializeuC/OS-II'sstatistics
OSStatInit();
TaskStartCreateTasks();
for(;;)
{
//clearthecontextswitchcounter
OSCtxSwCtr=0;
//waitonesecond
OSTimeDly(OS_TICKS_PER_SEC);
}
}
//*******************************************************************************
//*函数名:
TaskStartCreateTasks
//*返回值:
N/A
//*参数:
N/A
//*函数说明:
创建任务
//*作者:
啊呆
//******************************************************************************
staticvoidTaskStartCreateTasks(void)
{
//初始化,创建每个任务对应需要的信号量
init_buzzer_proc();
init_ModeEXE_proc();
init_ctrlmsg_get_proc();
init_twoChRec_proc();
InitStackMark();
//创建任务
OSTaskCreate(buzzer_proc,(void*)0,&BuzzerStk[BUZZER_STK_SIZE-1],TASK_3_PRIO);
OSTaskCreate(ctrlmsg_get_proc,(void*)0,&CtrlmsgStk[CTRLMSG_STK_SIZE-1],TASK_5_PRIO);
OSTaskCreate(stordev_mount_proc,(void*)0,&StorDevStk[STORDEV_MOUNT_STK_SIZE-1],TASK_6_PRIO);
OSTaskCreate(mode_switch_proc,(void*)0,&ModeSwitchStk[MODE_SWITCH_STK_SIZE-1],TASK_7_PRIO);
OSTaskCreate(ModeEXE_proc,(void*)0,&ModeExeStk[MODE_EXE_STK_SIZE-1],TASK_11_PRIO);
}
//**************************************************************************
//*函数名:
InitStackMark
//*返回值:
N/A
//*参数:
N/A
//*函数说明:
初始化堆栈栈顶
//*作者:
啊呆
//**************************************************************************
voidInitStackMark(void)
{
//初始化每个堆栈栈顶
BuzzerStk[0]=0x5153;
BuzzerStk[1]=0xAA55;
CtrlmsgStk[0]=0x5153;
CtrlmsgStk[1]=0xAA55;
StorDevStk[0]=0x5153;
StorDevStk[1]=0xAA55;
ModeSwitchStk[0]=0x5153;
ModeSwitchStk[1]=0xAA55;
ModeExeStk[0]=0x5153;
ModeExeStk[1]=0xAA55;
}
//*****************************************************************************
//*函数名:
CheckStkOverFlow
//*返回值:
BOOLEAN
//*参数:
INT8UTaskName
//*函数说明:
初检测堆栈溢出
//*作者:
啊呆
//******************************************************************************
BOOLEANCheckStkOverFlow(INT8UTaskName)
{
//判断是否堆栈溢出
if(TaskName==buzzer)
{
if(BuzzerStk[0]==0x5153&&BuzzerStk[1]==0xAA55)
returnFALSE;
}
elseif(TaskName==ctrlmsg)
{
if(CtrlmsgStk[0]==0x5153&&CtrlmsgStk[1]==0xAA55)
returnFALSE;
}
elseif(TaskName==stordev_mount)
{
if(StorDevStk[0]==0x5153&&StorDevStk[1]==0xAA55)
returnFALSE;
}
elseif(TaskName==mode_switch)
{
if(ModeSwitchStk[0]==0x5153&&ModeSwitchStk[1]==0xAA55)
returnFALSE;
}
elseif(TaskName==ModeEXE)
{
if(ModeExeStk[0]==0x5153&&ModeExeStk[1]==0xAA55)
returnFALSE;
}
returnTRUE;
}