UCOS操作系统堆栈浅谈

发布者:雅致书香最新更新时间:2015-05-06 来源: 51hei关键字:UCOS  操作系统  堆栈 手机看文章 扫描二维码
随时随地手机看文章
1 声明堆栈大小
在uc/os-ii操作系统的任务切换和中断处理过程中,需要保存处理器的内部寄存器和变量的值,这就
要求每个任务都有自己的堆栈空间。堆栈必须声明为OS_STK类型,并且由连续的内存空间组成,可以静态
分配空间(在编译时分配),也可以动态分配堆栈空间(在运行时分配)。由于采用动态分配方式,会导致
内存中含有大量内存碎片,因此不推荐使用动态分配方式。其两种声明方式如下:
静态分配方式:
static OS_STK TaskStk[StkSize];
或者
OS_STK TaskStk[StkSize];
动态分配方式:
OS_STK *pstk; 
pstk = (OS_STK*)malloc(StkSize);
if(pstk != (OS_STK*)0) //判断堆栈分配是否成功
{
printf("Create TaskStk Success");
}
2 设置堆栈生产方向
uc/os-ii操作系统支持2中堆栈生长方向。即可从高地址往低地址生长,也可以由低地址往高地址生长。
在调用OSTaskCreate()或者OSTaskCreateExt()创建任务的时候由于必须知道堆栈的生长方向,所以要在OS_CPU.H
文件中设置任务堆栈的生长方向。
#define OS_STK_GROWTH 1 //设置堆栈是从上往下长的 
OSTaskCreate(Task,pdata,&TaskStk[StkSize - 1],prio);
或者
#define OS_STK_GROWTH 0 //设置堆栈是从下往上长的
OSTaskCreate(Task,pdata,&TaskStk[0],prio);
当然也可以这样编写创建任务的以支持堆栈的从上往下和从下往上生长
#if OS_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"
 
/* size of each task's stacks (# of WORDs) */
#define TASK_START_STK_SIZE 128
#define BUZZER_STK_SIZE 128
#define CTRLMSG_STK_SIZE 128
#define STORDEV_MOUNT_STK_SIZE 512
#define MODE_SWITCH_STK_SIZE 512
#define MODE_EXE_STK_SIZE 2000
#define TWO_CHANNEL_REC_SIZE 512
#define ALARM_STK_SIZE 128
#define TASK_STK_SIZE 512
 
/* application tasks */
#define TASK_START_ID 0
#define TASK_1_ID 1
#define TASK_2_ID 2
#define TASK_3_ID 3
#define TASK_4_ID 4
#define TASK_5_ID 5
#define TASK_6_ID 6
#define TASK_7_ID 7
#define TASK_8_ID 8
#define TASK_9_ID 9
#define TASK_10_ID 10
#define TASK_11_ID 11
#define TASK_12_ID 12
#define TASK_13_ID 13
#define TASK_14_ID 14
#define TASK_15_ID 15
 
/* application tasks priorities */
#define TASK_START_PRIO 0
#define TASK_1_PRIO 1
#define TASK_2_PRIO 2
#define TASK_3_PRIO 3
#define TASK_4_PRIO 4
#define TASK_5_PRIO 5
#define TASK_6_PRIO 6
#define TASK_7_PRIO 7
#define TASK_8_PRIO 8
#define TASK_9_PRIO 9
#define TASK_10_PRIO 10
#define TASK_11_PRIO 11
#define TASK_12_PRIO 12
#define TASK_13_PRIO 13
#define TASK_14_PRIO 14
#define TASK_15_PRIO 15
 
/*see task stacks*/
OS_STK TaskStartStk[TASK_START_STK_SIZE]; 
OS_STK BuzzerStk[BUZZER_STK_SIZE]; 
OS_STK CtrlmsgStk[CTRLMSG_STK_SIZE]; 
OS_STK StorDevStk[STORDEV_MOUNT_STK_SIZE]; 
OS_STK ModeSwitchStk[MODE_SWITCH_STK_SIZE]; 
OS_STK ModeExeStk[MODE_EXE_STK_SIZE];
 
static void TaskStart(void *p_arg); //函数声明
static void TaskStartCreateTasks(void);
void InitStackMark(void);
//************************************************************************************
//* 函数名 :main
//* 返回值 :N/A
//* 参数 :N/A
//* 函数说明:主函数
//* 作 者:啊呆
//***********************************************************************************
void main(void)
{
  INT8U err;
  // initialize uC/OS-II
  OSInit();
  // install uC/OS-II's context switch vector
  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, "Start Task", &err);
  // start multitasking
  OSStart();
}[page]
//*********************************************************************************
//* 函数名 :TaskStart
//* 返回值 :N/A
//* 参数 :void *p_arg
//* 函数说明:创建TaskStart任务
//* 作 者:啊呆
//********************************************************************************
static void TaskStart(void *p_arg)
{
  #if OS_CRITICAL_METHOD == 3
   OS_CPU_SR cpu_sr;
  #endif
  // prevent compiler warning
  p_arg = p_arg;
  // install uC/OS-II's clock tick ISR
  OS_ENTER_CRITICAL();
  IRQSetVect(TMR1_VEC, OSTickISR);
  OSSetTickRate(lc_clk_get_freq(CLK_SYS_SEL), OS_TICKS_PER_SEC);
  OS_EXIT_CRITICAL();
  // initialize uC/OS-II's statistics
  OSStatInit();
  TaskStartCreateTasks();
  for (;;) 
  {
  // clear the context switch counter
  OSCtxSwCtr = 0;
  // wait one second
  OSTimeDly(OS_TICKS_PER_SEC);
  }
}
//*******************************************************************************
//* 函数名 :TaskStartCreateTasks
//* 返回值 :N/A
//* 参数 :N/A
//* 函数说明:创建任务
//* 作 者:啊呆
//******************************************************************************
static void TaskStartCreateTasks(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
//* 函数说明:初始化堆栈栈顶
//* 作 者:啊呆
//**************************************************************************
void InitStackMark(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
//* 参数 :INT8U TaskName
//* 函数说明:初检测堆栈溢出
//* 作 者:啊呆
//******************************************************************************
BOOLEAN CheckStkOverFlow(INT8U TaskName)
{
//判断是否堆栈溢出
  if(TaskName==buzzer)
  {
      if(BuzzerStk[0]==0x5153 && BuzzerStk[1]==0xAA55)
         return FALSE;
  }
  else if(TaskName==ctrlmsg)
  {
     if(CtrlmsgStk[0]==0x5153 && CtrlmsgStk[1]==0xAA55)
        return FALSE;
  }
  else if(TaskName==stordev_mount)
  {
     if(StorDevStk[0]==0x5153 && StorDevStk[1]==0xAA55)
        return FALSE;
  }
  else if(TaskName==mode_switch)
  {
     if(ModeSwitchStk[0]==0x5153 && ModeSwitchStk[1]==0xAA55)
        return FALSE;
  }
  else if(TaskName==ModeEXE)
  {
     if(ModeExeStk[0]==0x5153 && ModeExeStk[1]==0xAA55)
        return FALSE;
   }
   return TRUE;
}
关键字:UCOS  操作系统  堆栈 引用地址:UCOS操作系统堆栈浅谈

上一篇:C语言函数调用分析
下一篇:uC/OS II的任务切换机理及中断调度优化

推荐阅读最新更新时间:2024-03-16 14:00

arm堆栈操作
arm堆栈的组织结构是 满栈降 的形式,满栈即sp是要停留在最后一个进栈元素,降:就是堆栈的增长方向是从高地址向低地址发展。 arm对于堆栈的操作一般采用 LDMFD(pop)和STMFD (push) 两个命令。 以前困惑的就是STMFD 命令 对于操作数 是按照什么顺序压栈的 比如:STMFD sp!{R0-R5,LR} 进栈顺序是: 高地址(1方式) LR R5 R4 ``````` R0 -sp 低地址 还是: 高地址(2方式) R0 R1 ``` R5 LR -sp 低地址 现在通过下表,可以轻松的解决这个问题: 寻址方式 说明 pop =LDM
[单片机]
主频仅16M的STM8有必要跑操作系统吗?
一、STM8有必要使用操作系统吗? 很多初学者好奇:STM8有必要使用操作系统吗? 这个问题其实没有标准答案,我用STM8裸机开发过项目,也在STM8的项目上跑过RTOS。 使用RTOS优点很多:多任务、方便项目功能扩展、代码维护等。缺点就是代码占用资源,如果运行任务较多,对于低频MCU实时性不是那么好。 具体要看项目实际情况:MCU资源情况、功能复杂程度、实时性等。 比如:通过UART通信,简单控制几个IO口,这种或许没必要跑RTOS。 当然,使用RTOS有哪些好处,可以参看我之前分享的文章: 到底该不该用RTOS,看完你就有答案了 二、STM8都支持哪些RTOS操作系统? 我找了下官方资料,共列举4种: 1.AtomT
[单片机]
主频仅16M的STM8有必要跑<font color='red'>操作系统</font>吗?
加深初学者对单片机堆栈的理解--分析
  看关于单片机方面的书籍的时候,总是能看到别人说的一些堆栈啊什么的操作,之前看到这个术语就直接跳过,没想到去探究单片机内部的原理。但是最近课程学习微机原理这门课,需要我们写汇编程序,汇编里面经常遇到堆栈这个东西,所以就找了个时间把堆栈给彻底的搞一下。   如果了解一点汇编编程话,就可以知道,堆栈是内存中一段连续的存储区域,用来保存一些临时数据。通常用来保存CALL指令调用子程序时的返回地址,RET指令从堆栈中获取返回地址。中断指令INT调用中断程序时,将标志寄存器值、代码段寄存器CS值、指令指针寄存器IP值保存在堆栈中。   堆栈也可以用来保存其他数据。   堆栈操作由PUSH,POP两条指令来完成;   堆栈操作的操作
[单片机]
华为操作系统专利解密
美国政府不断动用国家机器制裁华为公司,导致华为的海外发展压力增大。与此同时,华为的新技术如鸿蒙操作系统等,也不断出现在大众面前。前不久,华为的全新台式电脑产品疑似曝光,采用ARM架构的鲲鹏处理器,并运行UOS操作系统,完全实现了国产化。 为提高生产效率,现有的许多大型系统(如区块链)通常使用分布式结构实现,即通过众多计算机节点构成庞大的网络。由于所有的节点上都运行有操作系统,当设备出现故障,常需要重新启动操作系统。系统的启动通常需要执行BIOS检查外围设备,启动操作系统的加载盘,加载主引导扇区引导内容、内核、设备驱动等,并初始化操作系统。 然而,由于现有的操作系统启动过程需要加载各种信息,如MBR、GRUB、内核等,同时还需要进行
[手机便携]
华为<font color='red'>操作系统</font>专利解密
详细解析STM32中的堆栈机制
刚拿到STM32时,你只编写一个死循环 编译后,就会发现这么个程序已用了1600多的RAM,这要是在51单片机上,会心疼死了,这1600多的RAM跑哪儿去了,分析.map文件,你会发现是堆和栈占用的 在startup_stm32f10x_md.s文件中,它的前面几行就有以下定义: 这下明白了吧,STM32在启动的时候,RAM首先分配给使用到的全局变量,还有调用库占用的一些数据(不太清楚是什么数据),然后再将剩余的空间分配给Heap和Stack。由于内存空间是启动时实现分配好的,所以当动态分配内存的需求过多的时候,就会产生堆栈空间不足的问题。 查阅网上的资料,理解堆和栈的区别: - (1)栈区(stack):由编译器自动
[单片机]
详细解析STM32中的<font color='red'>堆栈</font>机制
QNX Karimi:为什么说未来汽车将由软件定义?
近日,BlackBerry技术解决方案部销售与营销高级副总裁Kaivan Karimi在一年一度的QNX技术研讨会之际,语出惊人地表示:“尽管目前汽车市场中的操作系统有6-8家,但未来可能会只存在两至三家,而就我个人预测,未来五年车用Linux将完全消失。” 此次发布会,Karimi从汽车电子发展的未来需求分析,阐述了车用电子软件未来的重要性,“甚至是整车都要从软件定义开始。” BlackBerry技术解决方案部销售与营销高级副总裁Kaivan Karimi 从汽车行业遇到的挑战说起 Karimi表示,目前自动驾驶、数字化、出行共享车、以及电动化四大趋势带来第一个影响是汽车电子架构的改变。随着系统越来越复杂,
[汽车电子]
QNX Karimi:为什么说未来汽车将由软件定义?
S3C2410快速启动的实现
  嵌入式 系统 对功能、可靠性、成本、体积、功耗等均有严格要求,以ARM体系结构为基础的各种RISC微处理器具有灵活的特性和强大的性能,在嵌入式系统中得到了广泛的应用。---S3C2410是三星公司基于ARM920T设计的一款处理器,在开发基于S3C2410的系统的过程中,如何让系统快速稳定地启动是一个重要问题。嵌入式系统的资源有限, 程序 通常都是固化在ROM中运行。但在实际应用中,为提高系统的实时性,加快代码的执行速度,系统启动后程序往往要被搬移到 RAM 中,因为RAM的存取速度要比ROM快得多,这样大大提升系统的性能。启动程序要完成的任务包括:硬件初始化,系统存储系统的配置,复制二级 中断 向量表。
[应用]
三星Samsung Pay更新:支持安卓8.0操作系统
      星正在对旗下的旗舰手机进行安卓8.0系统升级的准备,在系统升级之前,三星的系统App已经开始测试兼容最新的安卓8.0系统。   据sammobile报道,位于瑞典的三星S8手机已经开始接收到三星旗下支付服务Samsung Pay的更新,本次更新主要内容是支持安卓8.0操作系统,通常三星都会在欧洲以及韩国率先对软件进行更新,随后扩大到其他国家去。   目前三星S8以及三星S8+基于安卓8.0的跑分数据已经在GeekBench现身,三星看来正在为系统更新做准备,在系统正式公测之前可能会有更多的系统软件获得更新支持新系统。
[手机便携]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved