你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。
chrome
firefox
safari
ie8及以上
ST
意法半导体官网
STM32
中文官网
ST
全球论坛
登录/注册
首页
技术问答
话题
资源
创客秀
视频
标签
积分商城
每日签到
ucos的任务堆栈如何保存局部变量?
[复制链接]
我要上自习
提问时间:2018-3-18 22:49 /
keil+uC/OS,是如何实现在任务的堆栈中操作局部变量的?比如在程序中建立了一个任务TASK1,任务中定义了几个局部变量a,b,c,在任务建立的时候,分配的堆栈是arrStask[128]。
那么程序执行到TASK1的时候,是如何保证把几个局部变量分配到对应的堆栈中的呢?
因为我看任务调度函数,只保存R0到R14、PC、PSW、SP等一些寄存器的值,并没有体现保存这些临时数据a,b,c,那么在上下文切换时,这些临时数据a,b,c是怎么处理的?
赞
0
收藏
0
评论
2
分享
发布时间:2018-3-18 22:49
举报
请先
登录
后回复
2个回答
MrJiu
回答时间:2018-3-19 10:03:41
a0a.1 32b0c
首先你要知道,局部变量的位置是在哪里的,全局变量的位置是哪里的。。。局部变量是放在堆栈(MCU硬件)里面,OS切换的时候,除了会保存寄存器,还会把堆栈里面的数据直接也保存下来。。。会有堆栈PC指令的。。。
评分
参与人数
1
蝴蝶豆
+3
收起
理由
zero99
+ 3
查看全部评分
赞
0
评论
回复
支持
反对
琦子
回答时间:2018-3-19 10:14:11
a4a.1 32b0c
楼主 这个问题我自己说的不好,给你粘来了一个别人的描述,请你参考:
堆栈作用的就是用来保存局部变量,从本质上讲也就是将CPU寄存器的值保存到RAM中。在uCOS中,每一个任务都有一个独立的任务堆栈。为了深入理解任务堆栈的作用,不妨分析任务从“出生”到“消亡”的整个过程,具体就是分析任务的建立,运行,挂起几种状态中任务堆栈的变化情况。
现在假设系统运行着一个由用户创建的用以完成打印工作的任务TPrint。TPrint最初通过OSTaskCreate()函数创建,在该函数中与任务堆栈有关的第一段代码是大家比较熟悉的函数OSTaskStkInit(),这个函数是在uCOS移植过程中必须实现的,其作用是“初始化堆栈”,其实就是预先在RAM中的一块区域中把任务将来运行开始时CPU寄存器应处的状态(正确值)准备好,之后,任务第一次被内核调度器调度运行时,将这些准备好的数据(寄存器的值)推到CPU的寄存器中,如果数据设计的合理,CPU便会按照我们预先设计好的思路运行。所以,“初始化堆栈”实际上是做了一个“未雨绸缪”的工作。这个过程中有两点是必须慎重考虑的,一是PC该如何定位,二是CPU的其它寄存器(除PC之外)该怎么处理。先说第一点,因为任务是第一次运行,而任务从本质上将就是一段代码,所以PC指针应该定位到这段代码的第一行处,即所谓的入口地址(Entry Point)处,这个地址由任务指针保存着,所以把该指针值赋给PC即可。第二,这段代码还未被执行过,所以代码中的变量与CPU的其它寄存器一点关系也没有,因此R0-R12,R14可随便给值,或者不赋值也可,让这些寄存器保持原来的值,显然后者更为简单。最后再给CPSR赋值,用户可以根据实际需要使系统运行于系统模式或管理模式。经过入栈和出栈,此时SP指向任务堆栈的最底端(就是已经定义好的任务堆栈数组的最后一个元素)。
之后任务代码开始正式运行,因为CPU的寄存器是有限的,所以在运行时不可避免地要把一些临时变量暂时保存到堆栈中。具体应保存到哪个地址呢,不用担心,SP知道(任务第一次运行时,这个地址就是任务堆栈数组的最后一个元素的地址)。任务堆栈的大小和任务代码中临时变量的数目有关,如果这段代码临变量特别多,堆栈就应设计的大一些。
然后,TPrint任务由于某种原因将要被挂起,所以应把任务的运行现场放到堆栈里保护起来,TPrint任务再次运行时再把这个现场还原,任务就能从上次断点处紧接着运行。那么,这个现场是什么呢?从本质上讲,TPrint任务的运行过程就是CPU在执行一段特定的代码,所以这个现场就是CPU的现场,也就是寄存器的值。这些寄存器的值包含了代码执行时的所有信息,包括当前运行到了这段代码的哪个位置处(由PC值指明)。因此,把CPU的寄存器的值推入堆栈,然后记住栈顶指针的位置(SP由OSTCBCur->OSTCBStkPtr保存),当任务再次将要运行前,从SP指向的地址处依次把先前保存的CPU寄存器的值放到CPU的寄存器中,任务就可以从上次中断的地方准确无误地执行。这个过程就像突然把任务冻结了,与任务有关的任何东西都不能动了,一段时间之后又把任务解冻,与它有关的东西又变得可用,于是任务又可以活蹦乱跳地跑起来了。
评分
参与人数
1
蝴蝶豆
+3
收起
理由
zero99
+ 3
查看全部评分
赞
0
评论
回复
支持
反对
所属标签
相似问题
关于
意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号
手机版
快速回复
返回顶部
返回列表
评分
查看全部评分
堆栈作用的就是用来保存局部变量,从本质上讲也就是将CPU寄存器的值保存到RAM中。在uCOS中,每一个任务都有一个独立的任务堆栈。为了深入理解任务堆栈的作用,不妨分析任务从“出生”到“消亡”的整个过程,具体就是分析任务的建立,运行,挂起几种状态中任务堆栈的变化情况。
现在假设系统运行着一个由用户创建的用以完成打印工作的任务TPrint。TPrint最初通过OSTaskCreate()函数创建,在该函数中与任务堆栈有关的第一段代码是大家比较熟悉的函数OSTaskStkInit(),这个函数是在uCOS移植过程中必须实现的,其作用是“初始化堆栈”,其实就是预先在RAM中的一块区域中把任务将来运行开始时CPU寄存器应处的状态(正确值)准备好,之后,任务第一次被内核调度器调度运行时,将这些准备好的数据(寄存器的值)推到CPU的寄存器中,如果数据设计的合理,CPU便会按照我们预先设计好的思路运行。所以,“初始化堆栈”实际上是做了一个“未雨绸缪”的工作。这个过程中有两点是必须慎重考虑的,一是PC该如何定位,二是CPU的其它寄存器(除PC之外)该怎么处理。先说第一点,因为任务是第一次运行,而任务从本质上将就是一段代码,所以PC指针应该定位到这段代码的第一行处,即所谓的入口地址(Entry Point)处,这个地址由任务指针保存着,所以把该指针值赋给PC即可。第二,这段代码还未被执行过,所以代码中的变量与CPU的其它寄存器一点关系也没有,因此R0-R12,R14可随便给值,或者不赋值也可,让这些寄存器保持原来的值,显然后者更为简单。最后再给CPSR赋值,用户可以根据实际需要使系统运行于系统模式或管理模式。经过入栈和出栈,此时SP指向任务堆栈的最底端(就是已经定义好的任务堆栈数组的最后一个元素)。
之后任务代码开始正式运行,因为CPU的寄存器是有限的,所以在运行时不可避免地要把一些临时变量暂时保存到堆栈中。具体应保存到哪个地址呢,不用担心,SP知道(任务第一次运行时,这个地址就是任务堆栈数组的最后一个元素的地址)。任务堆栈的大小和任务代码中临时变量的数目有关,如果这段代码临变量特别多,堆栈就应设计的大一些。
然后,TPrint任务由于某种原因将要被挂起,所以应把任务的运行现场放到堆栈里保护起来,TPrint任务再次运行时再把这个现场还原,任务就能从上次断点处紧接着运行。那么,这个现场是什么呢?从本质上讲,TPrint任务的运行过程就是CPU在执行一段特定的代码,所以这个现场就是CPU的现场,也就是寄存器的值。这些寄存器的值包含了代码执行时的所有信息,包括当前运行到了这段代码的哪个位置处(由PC值指明)。因此,把CPU的寄存器的值推入堆栈,然后记住栈顶指针的位置(SP由OSTCBCur->OSTCBStkPtr保存),当任务再次将要运行前,从SP指向的地址处依次把先前保存的CPU寄存器的值放到CPU的寄存器中,任务就可以从上次中断的地方准确无误地执行。这个过程就像突然把任务冻结了,与任务有关的任何东西都不能动了,一段时间之后又把任务解冻,与它有关的东西又变得可用,于是任务又可以活蹦乱跳地跑起来了。
评分
查看全部评分