一.学习目的
近期学习FreeRtos是因为工作需要而FreeRtos的学习路程漫漫,学习的过程也是很枯燥的,所以写了这个学习日记,一方面是为了督促自己的学习,另一方面同时也是为了给大家提供一个机会交流学习。FreeRtos的学习不像单片机的裸机编程,在这个学习过程中会设计到很多新的概念,像消息队列,阻塞态,就绪态,挂起态以及各种概念名词,我发表这篇博客的时候,学习已经到了后期,所以写的这篇文章也能对我前期的学习进行巩固。
二.学习基础概念
(一).FreeRtos与普通裸机编程代码的差别
老生常谈的FreeRtos和普通的裸机编程的区别就在于,一个能快速的切换任务执行,一个需要一个一个的任务执行下去,FreeRtos的任务运行并不是说同步运行,反而是因为他切换的够快,所以让用户能感觉到他是一个能够同时运行的系统任务,这就涉及到后期所需要说的各种状态了,通过唤醒不同的任务控制模块来达到快速切换的功能。
怎么理解上面的概念呢,先讲裸机编程的逻辑吧,这里以点灯举例,我们设红灯代号为1,绿灯代号为2,裸机伪代码程序如下
LED1,LED2进行初始化操作
while(1)//这是一个死循环
{
LED1亮;
Delay(300)//延时300ms
LED1灭;
LED2亮;
Delay(300)//延时300ms
LED2灭;
}
那么这段代码的现象是什么样子的?
没错,就是LED1亮一下,300毫秒后LED1灭了,注意这里紧接着LED2亮了,300毫秒后LED2又灭掉了。我们注意到这个LED1灭了之后,LED2才会亮起来,接着又过了300毫秒后,LED2灭了进入到一个死循环当中,这就是一个流水灯。
提出一个问题,如果我需要两个灯分开,同时亮同时灭怎么解决?
裸机的程序也可以完成,就是我在LED1亮和LED2亮同时进行,但是这只是个简单的程序你的代码量不会很大,如果是面对一个任务块呢,那么工程量就会很大了,这个时候就要引进我们的FreeRtos了,FreeRtos的优点也体现出来了,以下以代码的形式呈现。
Task1
{
LED1亮;
Delay(300);
LED1灭;
}
Task2
{
LED2亮;
Delay(300);
LED2灭;
}
void main
{
Task1;
Task2;
//启动任务调度器
start_task
}
上段代码中的两个逻辑就是Task1执行一会到Task2,Task2执行一会又到Task1,这样快速的两个任务切换,给用户的感觉就是两个任务在同时进行,相当于将原本的繁杂代码,我们进行分块,分完块之后,我们把打开一个任务调度器,这个任务调度器就管理这我们这些任务,更通俗一点的理解就是我们电脑的任务管理器功能,对不同的任务运行进程进行管控。
二.平台化的概念
在学习操作系统的时候,我们经常会听到移植这个词,那么这个词我们该如何去理解?
假设你现在写了一个很棒的代码工程,但是你是裸机写的代码,你不具备任何操作系统的接口,你原本用的是stm32的芯片,现在我要移植到其他芯片里面,库函数很多都不一样的。那请问我要为这个芯片再去创建个工程然后再去修改吗?
可想而知这个代码的工程量不亚于去重新写这个工程的工作量,这就涉及到我们平台化的概念,假设你在写这个代码工程的时候,我给了所有函数都留有接口,相当于只要你在我的接口里面去定义其他芯片的类似定义就可以使用这个函数,答案显而易见了,你只需要把其他系统或者芯片的类似定义给移动到我预留的接口里面,那么你就无需再去修改其他的逻辑,直接就可以使用这个工程,Rtos的好处就在这里了,注意这里是Rtos,因为各家操作系统大部分都会留出接口。
我们FreeRtos的优点在这里又体现出来了,接口函数的作用是什么?
接口函数:面对不同的操作系统时,统一接口创建任务函数。
下面是FreeRtos的接口函数代码:
BaseType_t xTaskCreate(
TaskFunction_t pxTaskCode, // 函数指针, 任务函数
const char * const pcName, // 任务的名字
const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节
void * const pvParameters, // 调用任务函数时传入的参数
UBaseType_t uxPriority, // 优先级
TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务
本次文章就先介绍这些基础概念,下次文章继续介绍堆和栈的概念。