FreeRTOS学习笔记
一 、 FreeRTOS中断配置和临界段
1、Cortex-M中断
Cotex-M3的NVIC最多支持240个IRQ(中断请求)、1个不可屏蔽中断(NMI)、
1个Systick(滴答定时器)定时器中断和多个系统异常。
在NVIC和系统控制块(SCB)中,有多个用于中断和异常的可编程寄存器。
应用程序中断及复位控制寄存器(AIRCR)中PRIGROUP位段用于定义优先级分组。stm32只有16个可用的优先级。
FessRTOS没有配置亚优先级,组4.
每个外部中断都有一个一一对应的优先级寄存器,每个8位。FreeRTOS设置中断优先级直接操作4个一组32位寄存器的首地址。
中断屏蔽寄存器:PRIMASK、FAULTMASK、BASEPRI
PRIMASK:禁止除reset、NMI、HardFault以外的中断。写1使能禁止中断功能。
FAULTMASK:禁止除reset、NMI以外的中断。写1使能禁止中断功能。
BASEPRI:写入某个阀值到寄存器,屏蔽优先级不高于阀值的中断。FreeRTOS就是用这个。
2、FreeRTOS中断配置
stm32使用4位优先级,PendSV和Systick优先级为最低15;FreeRTOS配置BASEPRI的值,优先级高于此值表示的中断,FreeRTOS不能禁止,不可以调用FreeRTOS的API函数。
低于此值的可以安全调用FreeRTOS的API函数。
FreeRTOS开关中断实际是操作BASEPRI的值。
临界段代码保护实际也是操作BASEPRI的值。
二、FreeRTOS任务基础知识
FreeRTOS使用抢占式内核,每个任务都有自己的优先级,每个任务都拥有堆栈,导致RAM使用量增大。任务调度器保证任何时间段至少有一个任务
在运行,职责是确保一个任务开始执行时上下文环境(寄存器值,堆栈内容)和上一次退出一致。
FreeRTOS任务优先级数值越大,优先级越大。同一个优先级下可以有多个任务。
每个任务都有一个独有的任务控制块,任务句柄就是控制块首地址。
每个任务独有的任务堆栈用来在任务切换和下次运行时保存和恢复现场。
三、FreeRTOS列表和列表项
FreeRTOS 使用不同的列表表示任务的不同状态,在文件tasks.c 中就定义了多个列表来完成不同的功能,这些列表如下:
PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];
PRIVILEGED_DATA static List_t xDelayedTaskList1;
PRIVILEGED_DATA static List_t xDelayedTaskList2;
PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;
PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;
PRIVILEGED_DATA static List_t xPendingReadyList;
通过操作这些列表来管理任务。
每个列表项都会记录此列表项属于哪个任务,又处于哪个列表中(用于辨别任务状态)。
任务控制块中有两个列表项,分别用来描述任务状态(xStateListItem)和等待的事件(xEventListItem)。
eg://将任务从就绪或者延时列表中删除,并且放到挂起将任务
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
//任务是否还在等待其他事件
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
列表的本质是双向循环链表。
四、FreeRTOS调度器开启过程和任务相关函数
1、任务调度函数
main()中首先调用vTaskStartScheduler().创建空闲任务和定时器任务,变量xSchedulerRunning设置为pdTRUE,表示调度器开始运行。 configGENERATE_RUN_TIME_STATS为1时运行时间统计功能。