FREERTOS任务的理解(一)
以我自己个人的经历来说,我也是从单片机过来的(也非科班出身),一开始接触这个freertos感觉特别抽象,很难理解,所以我希望写一篇文章来解释清楚,同时也做个记录。在正式的代码分析之前,先写一些帮助理解的东西。
我们知道任务是一个无限循环的函数。我们先思考如何从一个函数切换到另一个函数。
如何切换呢?
我相信大家肯定在编写c语言时都用过函数调用,这个非常简单对吧。比如
int main()
{
func();
return 0;
}
这样就从一个主函数跳到另一个函数,但是这背后做了哪些事情呢?
实现上述步骤,最关键的部分是什么呢?我们知道函数在编译后,函数实际上是一段连续的空间,来存放指令,函数名呢就是这段空间的起始地址。两个函数实现跳转,最核心的就是使PC 指针指向新的函数名
我不知道上述大家能理解多少,需要有点微机原理的一些知识。好我们说完最核心的东西了,但是仅仅只有完成PC指针的转换,行不行呢?答案肯定是不行的。
我们正常的函数调用还会传递参数对不对?
int main()
{
func(1,2);
return 0;
}
函数是如何传递参数的呢,是通过栈来实现参数的传递。
这里我先调用一张我写过文章的图片,让大家知道,这里就不解释了。
通过上面知道,原来是一种叫栈的东西来帮助我们实现函数的调用,对吧。接下来重点来了,大佬前辈们设计任务的(或者叫线程)初衷我觉得是将一个程序分成若干个互不干扰的模块,然后让这些互不干扰的模块能按照某种机制运行起来。
那么在A任务中,有自己的调用,在B任务中也有自己的调用。那么为了实现他们自己的调用,就需要有一个自己的栈,那么任务切换时就需要切换栈。假设是位于同一个栈呢,那就跟普通的函数调用一样了,就不是那种互相隔离的感觉了。我不知道这么写能不能传达我想表达的意思。
所以说每个任务都有自己的栈,在任务切换时,不仅要切换PC指针,还要切换栈。
好,到这里我们知道任务切换需要切换指针,需要切换栈。具体如何切换呢?到具体代码时会讲解。
再以单片机的角度讲一个知识点。我们考虑一个中断的过程。一个中断我们需要配置寄存器,配置完了之后,我们在中断服务函数中写代码,然后中断触发时,就会中断当前的程序,去跑去执行中断服务函数。
这个过程大家都很熟悉。我相信很多学过微机原理的朋友知道,进入中断后不是有保护现场(PUSH)与恢复现场(POP)吗,但是以stm32 为例,在中断服务函数中是没有这个过程的。
现场保护不严谨的说,就说保存内部的寄存器的状态。恢复就是,恢复寄存器的状态
但是实际上是有这个过程的,只不过这个过程是由硬件来帮助你实现的,比如在中断发生时,硬件会帮你保护现场,保存放回地址之类的,然后结束时,恢复现场,弹出返回地址到PC 中,
说了这么多,想说明什么呢?
就是说从当前服务程序(一个过程),跳到中断(另一个过程),需要现场保护之类的。那为什么普通的C函数调用不需要保护现场呢,只需要保存返回地址,因为普通的函数调用它与被调用函数属于同一个过程,他们就不需要保护现场与恢复现场
而我们的目的是什么?是实现两个互相隔离任务的切换。所以说我们在任务切换的时候,需要进行现场保护。当然也需要恢复了。
总结
到这里我们知道了,我们要实现一个任务的切换,就需要切换PC指针,还要切换栈,在切换栈的同时需要进行现场保护与恢复之类的。
如果说能理解我所写的这些内容,我相信会进一步的理解源代码。
后续会解析源代码,当然我也是参考了大佬门的东西,然后用自己语言与理解来描述。奥利给!
|