- 打卡等级:初来乍到
- 打卡总天数:5
- 最近打卡:2025-04-30 07:46:22
荣誉版主
- 积分
- 2319
|
发表于 2024-3-2 18:24:29
|
显示全部楼层
本帖最后由 tzz1983 于 2024-3-19 08:52 编辑
闲暇时间就来论坛发个贴玩玩,就当是业余休息了。
本贴接着讲 RTOS 基本原理 之 栈和任务栈,希望有人喜欢。本贴文继续叠加到1楼.
栈和RTOS中的任务栈
在RTOS领域,堆栈是一个不容忽视的概念,RTOS里的任务栈,是栈的一个分支,正确的理解栈,对学习RTOS有非常大的帮助。
堆栈分为堆和栈,这里只讲栈,为了不混淆概念,以下不管是堆栈还是栈,指的都是栈。
以下是栈概念的描述
1. 简单的来理解,栈就是一片内存,它的访问地址由栈顶指针SP给出。
2. SP是指向内存的一个指针,他永远指向最后写入数据的那个内存的地址.也就是当我们向栈内写入一字节数据后,相应的要操作SP+1,如果是拿出一字节数据,则SP-1.
3. 栈和普通的内存其实没什么区别,但是栈必须是SP指针能够访问的区域,例如,51内核的栈必须是在IDATA区, 251内核的栈必须是在EDATA区
4. 栈的另一个特征是和CPU内核指令,中断等硬件操作息息相关,比如子程序调用指令LCALL暗含栈操作,栈操作指令PUSH,POP在写入数据后同时也会操作SP增减。
栈还有一个重要特征是后入先出,这好比我们往一个小纸箱内不断的堆叠钞票,下次取钞票时,最先取出的是最后叠入的钞票。
用代码举例来说明后入先出特征:
void fc(void)
{
return;
}
void fb(void)
{
fc();
return;
}
void fa(void)
{
fb();
return;
}
上面的代码体现出函数调用链,即函数fa()调用了fb(),函数fb调用了fc(), 我们来分解一下这个调用过程即可体现出先入后出的特征,
执行语句fb()时, 编译器产生的汇编代码是 LCALL fb; 指令的具体操作是把当前(PC+3)的值写入栈,并且SP值自动加2 然后跳转到函数fb()并开始执行。
注意,在这里LCALL指令有隐含PC值入栈的操作。
接下来执行语句 fc(); 同样是把当前(PC+3)的值写入栈,并且SP值自动加2 然后跳转到函数fc()并开始执行。
此处也隐含PC值入栈的操作。
接下来执行fc()函数内return(RET)指令,RET指令从栈中读出两字数据写回PC,并使SP值-2,执行过后程序返回到fb()函数内return处
接下来执行fb()函数内return(RET)指令,RET指令从栈中读出两字数据写回PC,并使SP值-2,执行过后程序返回到fa()函数内return处
此时运行轨迹又回到了fa();
仔细分析上面的例子就可以发现,我们最后存入栈的数据(PC值)是被最先取出来的,这就是后入先出!
栈的几个作用:
1. 发生中断时硬件自动往栈内存储当前PC值(断点位置)和部分寄存器值并调整栈顶指针SP值,也就是自动保存中断发生时的程序运行断点位置,中断返回时,从堆栈中弹出PC值恢复PC , 并调整栈顶指针SP值。
2. 子程序(函数)调用时指令自动往栈内存储当前PC值(断点位置)并调整栈顶指针SP值,子程序返回时,从堆栈中弹出PC值恢复PC , 并调整栈顶指针SP值。
3. 编译器可以用堆栈传递函数形参,定义局部变量。
4. 如果用汇编语言编程,PUSH,POP栈操作指令可以对用户开放,用来存储临时数据。
栈容量大小需求的估算:了解了栈的几个作用以后,就可以大至估算出栈容量大小需求. 主要由中断嵌套层数,子程序调用深度,形参数量以及局部变量的多寡(如果编译器利用栈传递形参,把局部变量放在本内)几个因数决定。然而实际使用时却很难准确的计算出具体栈需求,原因是我们不断的在编辑代码,总不可能每改一次就去计算一次吧,并且这种计算本身也不容易,其次是中断是随机发生的,实际运行时最坏的情况短时间内可能体现不出来。所幸的是几乎所有成熟的RTOS都有堆栈检验功能,在RTOS自动检测的基础上我们只要稍为留些余量就可以轻易解决了。
如果没有使用RTOS,栈顶指针SP的初始化是由编绎器完成的,通常情况下,如果栈是向上增长的,除了我们代码已使用掉的内存外,剩下的内存都会自动成为栈。这也是为什么有些范例程序特别说明要留下多少RAM给堆栈使用的原因,如果你把内存用完了,那就等于没有堆栈了。
RTOS是一个多任务的系统,每个任务是相对独立的,每个任务都需要一个独立的堆栈。也就是说我们在运行这个任务的时候,使用这一片内存作为堆栈,切换到另一个任务后,需要使用另一片内存作为堆栈,只能这么做, 不让它们相互干扰. 切换堆栈很简单,只需改变栈顶指针SP的值就可以了。
RTOS在创建任务的时候,会为每一个任务指定堆栈区域和大小。
任务栈 就是 RTOS任务使用的堆栈
除此之外,RTOS中任务栈还有一个作用是用于保存上下文. 因为每一个任务运行都需要使用到寄存器组这种公共片上资源,当需要切换至另一个任务时,RTOS需要保存当前任务的寄存器组的数据,以备任务切换回来时,可以恢复这些数据,程序才能无差错的继续往后执行。
|
1
喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
-
+2
楼主威武~
|