当前位置: 首页 > wzjs >正文

网站官网建设上海最新政策

网站官网建设,上海最新政策,意识形态网站建设,网站建设前准备freertos入门—栈的概念 1 栈的概念 栈也是一块内存空间,CPU的SP寄存器指向它,它可以用于函数调用、局部变量、多任务系统里保存现场。栈对于多任务系统非常的重要,每个任务都有自己的栈,我们只有深入理解栈的作用,才…

freertos入门—栈的概念

1 栈的概念

  栈也是一块内存空间,CPU的SP寄存器指向它,它可以用于函数调用、局部变量、多任务系统里保存现场。栈对于多任务系统非常的重要,每个任务都有自己的栈,我们只有深入理解栈的作用,才能深入理解多任务系统。

2 函数调用

  我们首先编写一个程序,程序流程为:在主函数中调用函数a_func(),在a_func()中调用b_func()与c_func()。

#include "stm32f10x.h" int g_cnt;int b_func(volatile int a)
{a += 2;return a;
}int c_func(volatile int a)
{a += 3;return a;
}void a_func(volatile int a)
{g_cnt = b_func(a);g_cnt = c_func(g_cnt);
}int main(void)
{char ch = 65;volatile int i = 99;a_func(i);return 0;
}

  接着利用下述方法生成反汇编码:
在这里插入图片描述
在这里插入图片描述

fromelf --text -a -c --output=test.dis  .\Objects\点亮一个LED灯.axf

  打开生成的反汇编码,将反汇编码显示如下:
在这里插入图片描述
  函数调用的本质就是使用 BL 指令,但是我们main函数调用 a_func 函数时,我们设置了LR。然后我们在 a_func 函数里调用 b_func 函数时,又使用同样的 BL 指令设置 LR 等于另外一个值,那么我们的 LR 不就是被覆盖了吗?由此我们引出以下问题:

  1. LR被覆盖了,怎么办?
  2. 局部变量在栈中如何分配?
  3. 为何每个RTOS任务中都有自己的栈?

  在函数调用过程中,我们调用函数a,我们设置了 LR 等于函数 a 执行完后的返回地址,在函数 a 中我们马上去调用函数 b,BL 指令同时会去设置 LR,会把之前的 LR 覆盖掉,那么显然在 LR 被覆盖前会去保存 LR。
在这里插入图片描述
  同样在函数 b 中,我们不管三七二十一,也是先把 LR 保存下来,后面我们可能不会去修改 LR ,但是为了以防万一,或者说编译器为了统一处理,在函数入口处会保存 LR。
在这里插入图片描述
  接着我们把函数调用时栈的分配具体讲解:

  1. 假设一开始,寄存器指向某一位置,我们调用 main 函数,保存 r3 以及 lr 。
    在这里插入图片描述

  2. main 函数调用函数 a,会去保存 lr 和 r0。
    在这里插入图片描述

  3. 函数 a 调用函数 b ,函数 b 里也去保存两个寄存器。
    在这里插入图片描述

  4. 接着我们调用函数 c ,那么函数 c 的栈是在 函数 b 的栈下面吗?答案是否定的,我们调用完函数 b 后,函数 b 的栈就被回收了,所以当函数 b 的栈被回收后,我们才开始分配函数 c 的栈。
    在这里插入图片描述

  所以,在每一个c函数的入口,会划分出自己的栈,保存 LR 进栈里,保存局部变量。

2 局部变量

  对于局部变量的讲解,我们从下面 main 函数中的局部变量开始分析:
在这里插入图片描述
  一进入 main 函数时,就入栈了若干个寄存器:
在这里插入图片描述
  我们分析 MOVS r2,#0x41 ,0x41是65,那么我们的 r2 寄存器其实就是局部变量 ch ,所以说局部变量有可能保存寄存器中,不一定保存在内存里,当我们加上 volatile 后它就保存在内存里了,或者说寄存器不够用时也保存在内存里。
在这里插入图片描述
  继续分析 MOVS r0,#0x63 , 0X63 是99,那么 r0 是 i 变量,接着将 r0 写入[sp,#0]中,所以变量i是保存在栈中。
在这里插入图片描述
  所以 main 函数一进来的时候他就划分了栈,在栈中保存了一些寄存器,它使用保持寄存器的方式给我们划分出了一块空间,这块空间在后面代码我们分析了知道 [sp,#0] 对应的是 i 。
  我们继续分析 MOVS r4,#0xc8 ,0xc8 是 200 ,那么 r4 是 uch 变量。该变量保存在寄存器中而不是内存中。
在这里插入图片描述

3 RTOS如何使用栈

  为什么每一个 RTOS 任务都要有一个属于自己的栈?我们以下面函数 b 为例,在函数中它会将变量 a 加 2 ,然后返回这个新的值。
在这里插入图片描述
  现在假设有两个任务,Task_A 中定义一个变量 cnt ,然后定义一个死循环,在这个死循环中不断的去累加这个 cnt ,任务 b 也是一样。
在这里插入图片描述
  那么这两个任务如何运行呢?任务A运行一阵子发生切换,然后任务B运行一阵子再发生切换,接着再发生切换,这个切换在哪发生我们根本无法控制。
在这里插入图片描述
  我们来看下面一个场景,函数 a 调用函数 b ,他可能辛辛苦苦才执行到 ADDS r0,r0,#2 ,这个数值还未返回就发生了切换:
在这里插入图片描述
  在任务A发生切换时会先保存A的现场然后恢复B,任务B发生切换时会先保存B的现场然后恢复A。
在这里插入图片描述
&emsps; 以人为例,这个人要看两本书,一本是语文一本是数学。他的脑子只有一个,只能先读语文再读数学,学腻之后再看语文再看数学。一开始的时候语文读到了100页,读累了想看数学了,那得在100页加入书签。看了200页数学也看累了,那得在200页处加入书签,然后从前面语文100页处继续看。这加书签就是保存现场,从书签那里继续看就是恢复现场。
在这里插入图片描述
  任务A运行到黑线这个位置,辛辛苦苦把 r0 加上了2,但是很不幸在这里我们还没有使用这个新结果呢,我就被切换出去了,那怎么办?我们辛辛苦苦算出的结果不能够浪费,在这个场景里是 r0 ,在其他的场景里可能是 r1 或者 r2 ,所以干脆把所有的寄存器都保存下来。那么这些寄存器保存在什么位置,我们分析下处理器架构。
在这里插入图片描述
  保存的寄存器只能保存在内存里。假设任务A一开始的时候我们给它分配了一块内存,我们让sp寄存器指向addr a,分配 Task_A 函数的栈,接着 Task_A 函数调用 b 函数,分配 b 函数的栈,任务 A 发生切换时是被内核的定时器中断函数来切换,定时器中断函数需要保存任务 A 的现场,保存切换瞬间所有的寄存器到任务A的栈里面。
在这里插入图片描述
  当保存现场完成后sp指向最后,并且将sp记录到任务A的结构体中。为什么需要在任务A的结构体中记录sp,因为以后切换的时候我们需要先找到任务A的结构体,从这结构体中我们才可以找到sp,把sp赋给硬件的寄存器。
  接着我们应该讲解任务 B 的恢复,但是任务 B 的恢复与任务 A 的恢复一样,因此我们以任务 A 的恢复进行讲解。恢复任务 A 首先找到任务 A 的结构体得到 A 的sp。得到任务 A 的sp后我们就可以把保存的寄存器值全部恢复到硬件上,恢复到 cpu 里。这样虽然在 ADDS r0,r0,#2 发生了切换,但是恢复现场后寄存器的值都能被恢复到cpu中,因此可以继续执行下面的程序。
  所以RTOS中每个任务有不同的栈是因为:1.有不同的调用关系  2.有自己的局部变量  3.保存现场

http://www.dtcms.com/wzjs/358704.html

相关文章:

  • 大连龙彩科技的网站在谁家做seo做得比较好的公司
  • 一级 做爰免费网站百度总部投诉电话
  • 正规的手游代理平台济南网络优化厂家
  • 企业 手机门户网站图片外链
  • 网站接广告平台快速优化工具
  • 色情做受网站seo引擎优化专员
  • 售后服务网点建设是指网站我是做推广的怎么找客户
  • 专业网站建设电话想在百度做推广怎么做
  • 做招聘网站需要资质吗济南网站优化
  • 响应式购物网站网页设计软件
  • wordpress添加邮箱北京seo设计公司
  • 南京网站如何制作上海站群优化
  • wordpress 如何发布文章抖音seo公司
  • 湛江哪里有建网站链接提交
  • 网站自然排名怎么优化百度用户服务中心官网电话
  • 做英文网站常用的字体最近刚发生的新闻
  • 忘记网站后台用户名跨境电商seo是什么意思
  • 昆明网站建设哪家好上海搜索seo
  • 今天郑州最新通告重庆seo技术分享
  • 网站制作软件排行榜优化公司结构
  • 香港建设网站首页专业模板建站
  • 学校网站制作价格网络营销的方式与手段
  • 宁波方正建设监理网站怎样推广公司的网站
  • 在哪个网站可以做酒店预定单短视频平台推广
  • wordpress嵌入qq群seo的英文全称是什么
  • 做IT的需要别人打开网站吗seo技术团队
  • 网站建设平台网站设计网络营销师证书有用吗
  • 毕业设计某网站开发的开题报告范文百度排名
  • 网站打开慢的原因东莞网站建设平台
  • 惠州seo管理深圳网站seo推广