基于STM32创建FreeRTOS系统的详细流程
1、Freertos中任务顺序
通常把程序设计为前后台系统,主要分为两部分:前台系统和后台系统。这样的程序包括一个死循环和若干个中断服务程序(应用程序是一个无限循环,循环中调用API函数完成所需的操作,这个大循环就叫做后台系统;中断服务程序用于处理系统的异步事件,也就是前台系统),前台是中断级,后台是任务级。引入操作系统的任务调度之后,就会让系统响应更具有实时性。
前后台机制
2、RTOS任务属于多线程
对于目前主流的RTOS,freeRTOS属于并发的线程,表示的就是实时的线程。
1.首先对于MCU上的资源每个任务都是共享的,可以认为是单进程多线程模型。
2.MCU一般没有内存管理模块MMU等等,这样无法很好的实现进程的安全,如果用软件实现,开销太大,对于MCU没有太多的必要,这也是为什么我们当个任务程序跑飞会导致整个程序无法运行的原因。
3、可剥夺型内核与不可剥夺型内核
不可剥夺型:
异步事件还是由中断服务来处理。中断服务可以使一个高优先级的任务由挂起状态变为就绪状态。但中断服务以后控制权还是回到原来被中断了的那个任务,直到该任务主动放弃CPU 的使用权时,那个高优先级的任务才能获得CPU的使用权。运行着的任务占有CPU,而不必担心被别的任务抢占。
可剥夺型:
当一个运行着的任务使一个比它优先级高的任务进入了就绪态,当前任务的CPU 使用权就被剥夺了,或者说被挂起了,那个高优先级的任务立刻得到了CPU 的控制权。如果是中断服务子程序使一个高优先级的任务进入就绪态,中断完成时,中断了的任务被挂起,优先级高的那个任务开始运行。
4、FreeRTOSConfig.h的作用
FreeRTOSConfig.h 文件是 FreeRTOS 的工程配置文件,因为 FreeRTOS 是可以裁剪的实时操作内核,应用于不同的处理器平台, 用户可以通过修改这个 FreeRTOS 内核的配置头文件来裁剪 FreeRTOS 的功能。
FreeRTOS – The Free RTOS configuration constants and configuration options – FREE Open Source RTOS for small real time embedded systems
FreeRTOSConfig.h中一些关键宏定义的解释
5、Freertos任务创建
每个任务都是一个死循环,如果没有死循环,且任务执行到最后没有删除自身就退出了,就会卡到错误退出的代码里
6、Freertos任务删除
7、FreeRTOS的任务状态(4种)
1.运行态(Running) 2.就绪态(Ready) 3.阻塞态(Blocked) 4.挂起态(Suspended)
Running—运行态
当任务处于实际运行状态被称之为运行态,即 CPU 的使用权被这个任务占用。
Ready—就绪态
处于就绪态的任务是指那些能够运行(没有被阻塞和挂起),但是当前没有运行的任务,因为同优先级或更高优先级的任务正在运行。
Blocked—阻塞态
由于等待信号量,消息队列,事件标志组等而处于的状态被称之为阻塞态,另外任务调用延迟函数也会处于阻塞态。
Suspended—挂起态
类似阻塞态,通过调用函数 vTaskSuspend()对指定任务进行挂起,挂起后这个任务将不被执行,只有调用函数 xTaskResume()才可以将这个任务从挂起态恢复。
8、FreeRTOS的任务创建流程分两种
1.动态创建
1.定义任务句柄,配置句柄静态创建,需要在FreeRTOSConfig.h
配置文件中设置相关宏。
/* 在`FreeRTOSConfig.h`配置文件添加以下内容: */
#define configSUPPORT_STATIC_ALLOCATION 1 /* 设置为1,即开启静态支持 */
2.定义任务与任务句柄
/* 定义任务与任务句柄:TaskHandle_t就是`void*` */
static TaskHandle_t AppTaskCreate_Handle = NULL;
static TaskHandle_t LEDTask_Handle = NULL;
static void AppTaskCreate(void* pvParameters);
static void LEDTask(void* pvParameters);
static void AppTaskCreate(void* pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
BaseType_t xReturn = pdPASS;
xReturn = xTaskCreate(LEDTask,"LEDTask",512,NULL,3,LEDTask_Handle);
if(xReturn == pdPASS)
vTaskDelete(AppTaskCreate_Handle); /* 创建任务完成,任务App就已经结束使命了,删除以释放内存 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
static void LEDTask(void* pvParameters)
{
while(1){
GPIO_SetBits(GPIOC, GPIO_Pin_13);
vTaskDelay(1500);
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
vTaskDelay(1500);
}
}
3.任务创建和FreeRTOS的启动
/* GPIO初始化 */
static void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
int main(void){
LED_Init();
BaseType_t xReturn = pdPASS;
xReturn = xTaskCreate(AppTaskCreate, "AppTaskCreate",512,NULL,2,AppTaskCreate_Handle);
if(xReturn == pdPASS)
vTaskStartScheduler();
else
return -1;
while(1);
}
2. 静态创建
1.定义任务句柄,配置句柄静态创建,需要在FreeRTOSConfig.h
配置文件中设置相关宏。
/* 在`FreeRTOSConfig.h`配置文件添加以下内容: */
#define configSUPPORT_STATIC_ALLOCATION 1 /* 设置为1,即开启静态支持 */
2.创建任务函数
3.任务函数编写
4.任务创建函数编写
5.主函数创建任务函数调度器
主函数内容
9、FreeRTOS的二值信号量
1.进行二值信号中断先进行对应信号量句柄的定义
2.在App里的函数进行对应函数对应信号量句柄进行对应信号值的获取
3.进行对应信号一收一发
10、FreeRTOS的计数信号量
进入临界区通过关闭中断来避免任务发生切换
作者:许方平