FreeRtos嵌入式操作系统学习1--操作系统原理初探

2023-05-16

这里由于是第一篇文章,不讲复杂的数据机构,也不进行代码分析,只讲嵌入式操作系统原理。

先看下面一个简单的程序:

void task1()
{

	while(1)
	{
		Led1(1);//(1)
		delay(500)
		Led1(0);//(2)
	}
}
void task2()
{
		while(1)
	{
		Led2(1);//(3)
		delay(100)
		Led2(0);//(4)
	}
}
void main()
{
	//硬件初始化
	//软件初始化
	//创建多任务
	//启动多任务
}

main函数首先进行硬件初始化(必须),之后进行软件初始化(可选),然后创建多任务,最后启动多任务。
task1和task2在操作系统的时间片上切换,给人一种错觉,他们在同时运行,但实际上,操作系统是在这两个任务之间来回切换,比如任务2要执行了,就将任务1的状态入栈(现场保护),任务2的状态出栈(现场恢复),任务1要执行也是同理。

小伙伴们看完上面这段可能会有疑问,任务之间到底是如何切换的呢?新任务创建与启动都需要做哪些工作呢?首先我们解决第一个问题。

1. 任务是如何切换的?

程序当前运行的状态

学过计算机原理的小伙伴应该都知道,CPU在执行程序的时候,不外乎取指、译码、执行这些过程,这些工作要依赖CPU内部的寄存器完成,比如STM32,他的内部有xPSR、PC、LR、R12、R0-R14寄存器,在任务task1的(1)、(2)时刻,任务task2的(3)、(4)时刻,xPSR、PC、LR、R12、R0-R14这些寄存器的值都不一样,这些寄存器就代表了当前任务的运行状态。
是这样吗?上面的表述只说明了CPU内部的寄存器,但是程序有全局变量,局部变量之分,这些分别位于内存的堆区和栈区,程序的堆栈难道就不是程序运行的状态了吗?

在这里插入图片描述
不得不说,内存里面保存的数据和CPU寄存器里面保存的值,都是当前任务的状态,在某一时刻,CPU只能为一个任务服务,而内存却能同时保存好多任务的数据,但是内存这东西只要不断电,他保存的数据就不丢失,除非人为去擦除哈!所以,对于任务的切换,我们目前暂且认为是CPU内部寄存器的值。对于STM32,就是xPSR、PC、LR、R12、R0-R14寄存器。

任务切换就是旧任务的状态保存与新任务的状态恢复

先看旧任务的状态保存。上面已经说过,状态就是CPU内部寄存器的值,对于STM32,就是xPSR、PC、LR、R12、R0-R14寄存器。保存在什么地方呢?如何保存这些值呢?
首先肯定是保存在内存里面(保存在硬盘里也行,如果你的硬盘够快哈)。
第二个问题,如何保存?对于搞C++,JAVA这些高级语言的同学,可能会想到,i=a这样的赋值语句,搞嵌入式的你应该知道一个叫的东西吧,不知道栈不能算得上一个合格的嵌入式工程师哈!,因为不知道栈也就意味着你不知道中断的运行机制!
好啦,废话不多说。旧任务的状态保存就是吧CPU内部这些寄存器的值压入栈中,那么聪明的你肯定也知道了,新任务的状态恢复就是从栈中依次将这些寄存器的值弹出。
入栈,出栈这些操作是用汇编语言完成的,当然,有些CPU可能会帮你完成一部分入栈出栈的工作。
在这里插入图片描述

2. 新任务是如何创建并启动的?

与任务相关的就是任务的状态,即CPU寄存器的值,创建任务就是要初始化这些寄存器的值,与一般的初始化不同,CPU内部寄存器的值都有特定的含义,比如R0一般作为函数的第一个参数(编译器这个规定的),PC表示程序在内存运行的地址。比如要创建一个名字为task1的任务,传入参数为888,那么R0的值为888,PC的值为task1函数在内存中的地址。
创建任务需写汇报代码区给CPU内部寄存器赋值吗?
直接赋值也可以,但这是一个笨办法,每个任务不是有他自身的栈吗?我们可以用C语言直接操作任务栈,然后将任务设置为就绪状态,下一个时钟周期到来后任务切换到新任务,新任务便开始运行。

想必小伙伴们看完之后基本原理已经清楚了,但是任然有一些疑问:
1 怎么表示一个任务?
这将涉及到与任务相关的数据结构
2 任务切换的时机是什么?

不同任务优先级之间如何切,同优先级之间如何切,多长时间切,这些我将在后面的博客中讲解。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRtos嵌入式操作系统学习1--操作系统原理初探 的相关文章

随机推荐