**
文章大部分内容摘抄至B站的韦东山老师的深入了解FreeRTOS操作系统教程,若有不理解的地方,可点击链接学习韦老师的视频。
**
目的
这篇文章主要是用来记录自己深入了解操作系统内部函数实现原理的记录,如有错误,请批评指正,感谢不尽!!
了解FreeRTOS和裸机之间的差别
FreeRTOS是一个开源的实时操作系统内核,它提供了线程、信号量、定时器等实时操作系统所需的基础函数和服务,可以帮助开发者管理系统资源、提高系统响应能力、提高代码的可读性和可移植性。
而裸机编程是指开发者直接使用裸机环境提供的硬件资源和指令集进行开发,没有操作系统的支持。在裸机开发中,需要开发者自己编写代码管理硬件资源和处理复杂的中断处理程序。由于没有操作系统的支持,裸机开发需要开发者自己处理各种问题,如任务调度、中断处理等问题。
相比而言,FreeRTOS在管理系统任务和资源方面更加方便和高效,而裸机编程更加自由和灵活,但也需要开发者自己处理更多的底层细节和操作系统相关问题。实际使用中还需要根据具体的需求和应用场景选择适合的开发方式。
任务运行环境
任务不仅仅是一段代码,它存储在flash上,代码和运行位置,运行环境组合成一段运行的代码,这就是任务的意义所在。现在先来了解一下任务的运行环境是什么样的:
这里定义了一个添加函数,结果就是*pa=*pa+*pb
void add_value(int *pa , int *pb)
{
volatile int temp;
temp = *pa;
temp = temp + *pb;
*pa = temp;
}
int main()
{
int a = 1;
int b = 2;
add_value(&a,&b);
return 0;
}
我们需要查看c语言的反汇编代码:
CPU内部怎么完成函数功能
举例一下32中常用的f103系列,内部有多种模块,比如CPU,RAM,FLASH,UART等多种模块,程序运行的时候,数据存储在RAM中,代码存储在FLASH中,可以通过JLink,STlink烧写代码到FLASH中。现在想要完成刚刚的函数功能,CPU就需要先从内存读出来a的值,在读出b的值,然后在cpu内部进行运算,然后cpu在将结果存回内存中。
CPU内部结构
需要知道的是CPU内部有R0-R15个寄存器,在栈中高位寄存器占据高位,低位寄存器占据低位,常用的R0,R1,R2用来存储函数的形参,如果有多个形参变量,可使用后面的寄存器来存取,需要注意的是要记得恢复寄存器的值。其中R13,R14和R15非常常用,也叫做sp,LR和PC寄存器。那么CPU是怎么知道要执行什么指令的呢?是要怎么执行呢?这就要说到指令集了,一般指令集都是厂商存在Flash中的,CPU会固定读取Flash得到指令,要想彻底了解,就必须要了解一下汇编指令。
注意:sp表示栈,LR表示返回地址,PC表示当前指令地址。
汇编指令
汇编指令我们需要掌握最基本的常用的指令:比如LDR--------Load 加载,这个指令是读取的意思,
写法是LDR R0,[addr] 这条指令是从内存中addr中读取数据存储在R0寄存器中。
下面详细介绍一下常用的指令:
指令 | 详解 |
---|---|
LDR R0,[addr] | 从内存中addr中读取数据存储在R0寄存器 |
STR R0,[addr] | 把R0寄存器的值存入地址为addr |
ADD R0,R1,R2 | 表示R0=R1+R2 |
SUB R0,R1,R2 | 表示R0=R1-R2 |
PUSH {R3,LR} | 把R3,LR寄存器的值写入内存 |
POP {R3,LR} | 把R3,LR寄存器的值从内存中取出 |
– | – |
注意:其中的PUSH,POP指令存取的位置是根据sp来指定的,其存储是是根据寄存器编号来确定位置的,高标位寄存器存储在高位,低标位寄存器存储在低位。每Push一个寄存器,sp=sp-4,POP相反,sp=sp+4。 |
现场
程序运行的时候,如果突然因为外界原因程序中断了,那么程序是如何保存现场的??我们要知道这个过程,我们就需要了解什么是现场,可以粗略的认为现场就是CPU内部当前运行时的被打断的瞬间所有寄存器的值。要想保存好现场,那么保存在哪里呢?应该将需要保存的寄存器(现场)保存在栈空间内存。在中断结束后,需要通过恢复现场来保证一些局部变量的值不被改变。
链接
学习资料来自b站的韦东山老师的深入了解freeRTOS教程