目录
2、FreeRTOS如何配置PendSV和Systick中断优先级
3、初始化列表项函数vListInitialiseItem()
1、开启任务调度器函数vTaskStartScheduler()
2、配置硬件架构及启动第一个任务函数xPortStartScheduler()
6、prvStartFirstTask()为什么要操作0XE00ED08
8、当多个任务写入消息给一个 “满队列” 时,这些任务都会进入阻塞状态,也就是说有多个任务在等待同一个队列的空间。那当队列有空间时,哪个任务会进入就绪态?
官网:FreeRTOS™ - FreeRTOS™
01基础
一、任务调度简介(熟悉)
1、什么是任务调度器
答:任务调度器就是使用相关的调度算法来决定当前需要执行的哪个任务。
2、FreeRTOS的任务调度方式
答:FreeRTOS一共支持三种任务调度方式:
- 抢占式调度 :主要是针对优先级不同的任务,每一个任务都有一个任务优先级,优先级高的任务可以抢占低优先级的任务的CPU使用权。
- 时间片调度 :主要针对相同优先级的任务,当多个任务的优先级相同时,任务调度器会在每个时钟节拍到来的时候切换任务。
- 协程式调度 :其实就是轮询,当前执行任务将会一直运行,同时高优先级的任务不会抢占低优先级任务。FreeRTOS现在虽然还在支持,但官方已经明确表示不再更新协程式调度。
3、抢占式调度过程
答:
运行过程如下:
- 首先Task1在运行中,在这个过程中Task2就绪了,在抢占式调度器的作用下,Task2会抢占Task1的运行。
- Task2运行过程中,Task3就绪了,在抢占式调度器的作用下Task3会抢占Task2的运行。
- Task3运行过程中,Task3阻塞了(系统延时或者等待信号等),此时就绪中,优先级最高的任务Task2执行。
- Task3阻塞解除了(延时到了或者接收到信号量),此时Task3恢复到就绪态中,抢占Task2的运行。
总结:
- 高优先级任务,优先执行。
- 高优先级任务不停止,低优先级任务无法执行。
- 被抢占的任务将会进去就绪态。
4、什么是时间片
答:同等优先级任务轮流享有相同的CPU时间(可设置),叫做时间片,在FreeRTOS中,一个时间片等于SysTick中断周期。
5、时间片调度过程
答:
运行过程如下:
- 首先Task1运行完一个时间片后,切换至Task2运行。
- Task2运行完一个时间片后,切换至Task3运行。
- Task3运行过程中(还不到一个时间片),Task3阻塞了(系统延时或者等待信号量等),此时直接切换到下一个任务Task1执行。
- Task1运行完一个时间片后,切换至Task2运行。
总结:
- 同等优先级任务,轮流执行。
- 一个时间片大小,取决滴答定时器中断周期。
- 没有用完的时间片不会再使用,任务Task3下次得到执行时间还是按照一个时间片的时钟节拍运行。
二、任务状态( 熟悉)
1、FreeRTOS的任务状态
答:FreeRTOS中任务存在4种状态:
- 运行态 :正在执行的任务,该任务就处于运行状态(注意:在STM32中,同一时间仅一个任务处于运行态)。
- 就绪态 :如果该任务已经能够被执行,但当前还未被执行,那么该任务处于就绪态。
- 阻塞态 :如果一个任务因为延时或者等待外部事件发生,那么这个任务就处于阻塞态。
- 挂起态 :类似于暂停,调用函数vTaskSuspend()进入挂起态,需要调用解挂函数vTaskResume()才可以进入就绪态。
2、四种任务状态之间的转换关系
答:
总结:
- 仅就绪态可以转换成运行态。
- 其他状态的任务想要运行,必须先转换成就绪态。
3、任务状态列表
答:任务的四种状态中,除了运行态,其他三种任务状态的任务都有其对应的任务状态列表。
- 就绪列表 : pxReadyTasksLists[x],其中x代表人物优先级数值。
- 阻塞列表 :pxDelayedTaskList
- 挂起列表 :xSuspendedTaskList
32位计算机:1字=32位=4字节
中断,数字越小优先级越高;任务,数字越大优先级越高
一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc_堆大小可以看做栈大小吗-CSDN博客
02文件系统详解
1、FreeRTOSConfig.h配置文件作用
答:对FreeRTOS进行功能配置和裁剪,以及API函数的使能。
2、学习途径
- 官方的在线文档中有详细说的说明:https://www.freertos.org/a00110.html 。
- 正点原子《FreeRTOS开发指南》第三章的内容---FreeRTOS系统配置。
3、配置文件中相关宏的分类
答:相关宏大致可以分为三类。
- ‘INCLUDE’开头 --- 配置FreeRTOS中可选的API函数。
- ’config‘开头 --- 完成FreeRTOS的功能配置和裁剪(如调度方式、使能信号量功能等)。
- 其他配置 --- PendSV宏定义、SVC宏定义。
03任务创建和删除
一、任务创建和删除API函数(熟悉)
1、任务创建和删除的本质
答:任务创建和删除的本质就是调用FreeRTOS的API函数。
2、任务动态创建和静态创建的区别
答:
- 动态创建任务 :任务的任务控制块以及任务的栈空间所需的内存,均由FreeRTOS从FreeRTOS管理的堆中分配。
- 静态创建任务 :任务的任务控制块以及任务的栈空间所需的内存,需要用户分配提供。
3、任务控制块结构体成员介绍
答:
总结:
- 任务栈栈顶,在任务切换时的任务上下文保存、任务恢复息息相关。
- 每个任务都有属于自己的任务控制块,类似身份证。
4、什么是临界区保护
答:临界区保护,保护那些不想被打断的程序段,关闭freertos所管理的中断,中断无法打断,滴答中断和PendSV中断无法进行不能实现任务调度 。
5、动态创建优点
答:动态创建使用起来相对简单。在实际的应用中,动态方式创建任务是比较常用的,除非有特殊的需求,一般都会使用动态方式创建任务 。
6、静态创建优点
答:静态创建可将任务堆栈放置在特定的内存位置,并且无需关心对内存分配失败的处理 。
7、创建任务时任务堆栈所存内容
答:
- 寄存器下PSR被初始为0x01000000,其中bit24被置1,表示使用Thumb指令。
- 寄存器PC被初始化为任务函数指针(任务A,即我们写的任务函数的地址),这样当某次任务切换后,任务A获得CPU控制权,任务函数(任务A)被出栈到PC寄存器,之后会执行任务A的代码。
- LR寄存器初始化为函数指针prvTaskExitError,这个函数是FreeRTOS提供的,是一个出错处理函数。
- 子函数的调用通过寄存器R0~R3传递参数,创建任务时,我们传入的参数被保存到R0中,用来向任务传递参数。
二、任务创建---动态方法(掌握)
1、动态任务创建函数
答:
函数参数:
函数返回值:
2、实现静态创建任务流程
答:用起来只需三步。
- 将FreeRTOSConfig.h文件中宏configSUPPORT_DYNAMIC_ALLOCATION配置为1。
- 定义函数入口参数。
- 编写任务函数。
动态任务创建函数创建的任务会立刻进入就绪态,由任务调度器调度运行。
3、动态任务创建函数内部实现简述
答:
- 申请堆栈内存&任务控制块内存。
- TCB结构体(任务控制块)成员赋值。
- 添加新任务到就绪列表中。
三、任务创建---静态方法(掌握)
1、静态任务创建函数
答:
函数参数:
函数返回值:
2、实现静态创建任务流程
答:用起来只需五步。
- 将FreeRTOSConfig.h文件中宏configSUPPORT_STATIC_ALLOCATION配置为1。
- 定义空闲任务&定时器任务的任务堆栈以及TCB。
- 实现两个接口函数(vAppLicationGetldleTaskMemory() 空闲任务接口函数和vApplicationGetTimerTaskMemory()定时器任务接口函数)。
- 定义函数入口参数。
- 编写任务函数。
静态任务创建函数创建的任务会立刻进入就绪态,由任务调度器调度运行。
3、静态任务创建函数内部实现简述
答:
- TCB结构体成员赋值。
- 添加新任务到就绪列表中。
四、任务删除
1、任务删除函数
答:
任务删除函数用于删除已经被创建的任务,被删除的任务将从就绪任务列表、阻塞任务列表、挂起任务列表和事件列表中移除。
注意:
- 当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)。
- 空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存空间,必须用户在任务被删除前提前释放,否则将会导致内存泄漏。
2、删除任务流程
答:用起来只需两步。
- 使用删除任务函数,将FreeRTOSConfig.h文件中宏INCLUDE_vTaskDelete配置为1。
- 入口参数输入需要删除的任务句柄(NULL代表删除本身)。
3、删除任务函数内部实现简述
答:
- 获取所要删除的任务控制块 --- 通过传入的任务句柄,判断所需要删除哪个任务,NULL代表删除自身。
- 将被删除任务移除所在列表 --- 将该任务所在列表中移除,包括:就绪、阻塞、挂起、事件等列表。
- 判断所需要删除的任务
- 更新下个任务的阻塞时间 --- 更新下一个任务的阻塞超时时间,以防止被删除的任务就是下一个阻塞超时的任务。
动态创建和删除
这里,开始任务创建完就立马进行任务调度,进入开始任务
若无进入临界区和退出临界区【临界区保护】
那么每创建一次任务就进入任务调度。执行start里的创建函数之后,该函数被删除。
当创建了任务1,任务1创建完进入调度
由于此处的优先级设置是start
当task1创建完之后,就立马抢占start,执行task1 函数,当task1阻塞时,释放控制权给start,start继续创建task2【task1阻塞】,task2创建完立马调度执行,当task2阻塞时。释放控制权给start,start继续创建task3【task1task2阻塞】,task3创建完里面进行调度,执行task3程序,task3阻塞后回到start,最后删除start
过程是:task1task2task3task3task2task1一直循环下去
若有进入临界区和退出临界区【临界区保护】
则创建start之后的开启任务调度将暂时失效,是先创建完start里的task1task2task3按顺序创建之后退出临界区,再开启任务调度,执行的时候顺序是task3task2task1【因为task3优先级最高】
过程是:task3task2task1task3task2task1一直循环下去
开始任务是用来创建另外3个任务的,只需要创建一次开始函数,他只需要执行一次,最后删除就可以了
--------------------------------------------------------------------
6.6静态创建任务和删除
要自己实现的2个接口函数【空闲任务内存分配、软件定时器内存分配】
在任务调度函数【vTaskStartScheduler】里的
因为configSUPPORT_STATIC_ALLOCATION=1
所以会创建空闲任务【xIdleTaskHandle = xTaskCreateStatic】位置上方【vApplicationGetIdleTaskMemory】
ctrl+f搜索上方函数的声明【tssk.h里】,复制到自己的demo文件进行定义
因为configUSE_TIMERS=1
所以会xTimerCreateTimerTask函数里
创建软件定时器任务【xTimerTaskHandle = xTaskCreateStatic】位置上方【vApplicationGetTimerTaskMemory】
ctrl+f搜索上方函数的声明【timer.h里】,复制到自己的demo文件进行定义
--------------------------------------------------------------------
04任务挂起和恢复
一、任务挂起和任务恢复介绍(熟悉)
1、任务的挂起与恢复的API函数
答:
- 挂起:挂起任务类似暂停,可恢复;删除任务,无法恢复,类似“人死两清”。
- 恢复:恢复被挂起的任务。
- “FromISR”:带有FromISR后缀是在中断函数中专用的API函数。
二、任务挂起(熟悉)
1、任务挂起函数介绍
答:
任务挂起函数用于挂起任务,使用时需要将将FreeRTOSConfig.h文件中宏INCLUDE_vTaskSuspend配置为1。
无论优先级如何,被挂起的任务都将不再被执行,直到任务被恢复。
注意:当传入的参数是NULL,则代表挂起任务自身(当前正在运行的任务)。
2、任务挂起函数内部实现
答:
- 获取所要挂起任务的控制块。(根据任务句柄获取任务控制块,如果任务句柄为NULL,表示挂起任务本身。)
- 移除所在列表。(将要挂起的任务从相应的状态列表和事件列表中移除。)
- 插入挂起任务列表。(将待挂起任务的任务状态列表项插入到挂起状态列表末尾。)
- 判断任务调度器是否运行。(判断任务调度器是否运行,在运行,更新下一次阻塞时间,防止被挂起任务为下一个阻塞超时任务。)
- 判断待挂起任务是否为当前任务。(如果挂起的是任务自身,且调度器正在运行,需要进行一次任务切换;调度器没有运行,判断挂起任务数是否等于任务总数,是:当前控制块赋值为NULL,否:寻找下一个最高优先级任务。)
三、任务恢复(熟悉)
1、任务恢复函数介绍(任务中恢复)
答:
使用该函数时需要将FreeRTOSConfig.h文件中宏INCLUDE_vTaskSuspend配置为1。
注意:任务无论被vTaskSuspend()挂起多少次,只需在任务中调用vTaskResume()恢复一次就能继续运行,且被恢复的任务会进入就绪态。
2、任务恢复函数(任务中恢复)内部实现
答:
- 恢复任务不能是正在运行任务。
- 判断任务是否子啊挂起列表中。(是:就会将该任务在挂起列表中移除,将该任务添加到就绪列表中。)
- 判断恢复任务优先级。(判断恢复的任务优先级是否大于当前正在运行的任务,是的话,执行任务切换。)
3、任务恢复函数介绍(中断中恢复)
答:
使用该函数注意要将FreeRTOSConfig.h文件中宏INCLUDE_vTaskSuspend和INCLUDE_xTaskResumeFromISR配置为1。
该函数专用于中断服务函数中,用于解挂被挂起任务。
注意:中断服务程序中要调用freeRTOS的API函数则中断优先级不能高于FreeRTOS所管理的最高优先级。
4、任务恢复函数(中断中恢复)内部实现
答:
- 关闭freertos可管理中断,防止被其他的中断打断,并返回关闭前basepri寄存器的值。
- 判断是否有挂起任务。
- 将前面保存的basepri的值,恢复回来。
- 返回xYieldRequired的值 用于决定是否需要进行任务切换。
任务挂起和回复
上述:中断的优先级要低于任务的最高优先级
中断优先级【越小越高】
任务优秀级【越大越高】
此处,我们选择中断优先级分组为4,抢占优先级拉满0~15
此时中断抢占优先级可以有0~15
但我们要给ARM内核分一点中断,RTOS任务中断给一点中断
如 0~ 4 5~15
问:为什么会有这种设置方式,他直接RTOS管理的中断为0~15不好么
答:这里的中断抢占优先级类似于分出去的感觉是吧,原本选4分组,抢占拉满0~15,但是我为了给内核分一点中断,RTOS也给一点去任务中断,得留一些中断给特定的外设使用 比如DMA啊 串口终端这些时序的东西
--------------------------------------------------------------------
RTOS的优先级
分组不是4会报以下错误
解决:
中断优先级高于RTOS的优先级会报以下错误
解决:
05中断管理
一、中断介绍(了解)
1、什么是中断
答:让CPU打断正常运行的程序,转而去处理紧急的事件(程序),就叫中断。
2、中断执行机制
答:可简单概括为三步:
- 中断请求 :外设产生中断请求(如:GPIO外部中断、定时器中断...)。
- 响应中断 :CPU停止执行当前程序,转而执行中断处理程序(ISR)。
- 退出中断 :执行完毕,返回被打断的程序处,继续往下执行。
二、中断优先级分组设置(熟悉)
1、中断优先级分组介绍
答:ARM Cortex-M 使用了8位宽的寄存器来配置中断的优先等级,这个寄存器就是中断优先级配置寄存器。但STM32只用了中断优先级配置寄存器的高4位[7:4],所以STM32提供了最大16级(0~15)的中断优先等级。
2、什么是抢占优先级,什么是子优先级
答:STM32的中断优先级可以分为抢占优先级和子优先级。
- 抢占优先级 :抢占优先级的中断可以打断正在执行但抢占优先级低的中断。
- 子优先级 :当同时发生具有相同抢占优先级的两个中断时,子优先级数小的优先执行。
注意 :中断优先级(抢占优先级和子优先级)数值越小,优先级越高。
3、中断优先级配置方式
答:一共有5种配置方式,对应着中断优先级分组的5个组。
注意:FreeRTOS中为了方便管理,采用第4号(NVIC_PriorityGroup_4)分配方式。
4、FreeRTOS中对中断优先级的管理
答:
- 低于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断才允许调用FreeRTOS的API函数。
- 建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理。
- 中断优先级数值越小越优先,任务优先级数值越大越优先。
三、中断相关寄存器(熟悉)
1、系统中断优先级配置寄存器
答:三个系统中断优先级配置寄存器,分别为 SHPR1、 SHPR2、 SHPR3 。
- SHPR1寄存器地址:0xE000ED18~0xE000ED1B
- SHPR2寄存器地址:0xE000ED1C~0xE000ED1F
- SHPR3寄存器地址:0xE000ED20~0xE000ED23
注意:FreeRTOS主要是使用SHPR3寄存器对PendSV和Systick中断优先级进行设置(设置为最低优先级)。
2、FreeRTOS如何配置PendSV和Systick中断优先级
答:
注意:在FreeRTOS系统中PendSV和SysTick设置最低优先级。
3、为什么将PendSV和SysTick设置最低优先级
答:保证系统任务切换不会阻塞系统其他中断的响应。
4、中断屏蔽寄存器
答:三个中断屏蔽寄存器,分别为PRIMASK、FAULTMASK和BASEPRI 。
FreeRTOS所使用的中断管理就是利用的BASEPRI这个寄存器。
5、BASEPRI中断屏蔽寄存器
答:BASEPRI:屏蔽优先级低于某一个阈值的中断,当设置为0时,则不关闭任何中断。
比如: BASEPRI设置为0x50,代表中断优先级在5~15内的均被屏蔽,0~4的中断优先级正常执行
6、FreeRTOS的关中断程序
答:
7、FreeRTOS的开中断程序
答:
8、中断服务函数调用FreeRTOS的API函数需注意
答:
- 中断服务函数的优先级需在FreeRTOS所管理的范围内。
- 在中断服务函数里边需调用FreeRTOS的API函数,必须使用带“FromISR”后缀的函数。
中断优先级数值越小越优先
任务不可以打断中断
中断可以打断任务
优先级的设置,低四位无效,高四位有效
关中断:
STM32——中断概览(中断优先级)_stm32中断优先级-CSDN博客
中断向量表stm32中文参考手册的中断和事件章节
其中的数字是编号,可设置代表的是NVIC可编程优先级分组中的抢占优先级和响应优先级
我们RTOS是设置优先级分组4,16个抢占优先级0~15
RTOS的中断优先级是5~15【因为PenSV编号为5】抢占设置为5为了不影响前面的中断
也就是图中的绿色部分了
注意区分RTOS的任务优先级:32个硬件任务优先级,0~31【不要在中断优先级搞混】
开中断:
RTOS的FROMISR函数是用来管理中断的
如果不在管理范围内,那么就无法关闭中断
此处为什么用delay_ns 而不是用vTaskDelay?
是因为vTaskDelay结束之前会开启中断
在这个函数里面
taskEXIT_CRITICAL();
跳转到底层 会有开启中断
ISR 中断服务函数
06临界段代码保护
一、临界段代码保护简介(熟悉)
1、什么是临界段
答:临界段代码也叫临界区,是指那些必须完整运行,不能被打断的代码片段。运行时临界段代码时需要关闭中断,当处理完临界段代码以后再打开中断。
2、适用什么场合
答:
- 外设 :需要严格按照时序初始化的外设,如IIC、SPI等。
- 系统 :系统自身需求,如任务切换过程等。
- 用户 :用户需求,如我们写的任务创建任务。
3、什么可以打断当前程序的运行
答:中断、任务调度。
二、临界段代码保护函数介绍(掌握)
1、临界段代码保护函数
答:
任务级临界区调用格式示例:
中断级临界区调用格式示例:
2、临界段代码保护函数使用特点
答:
- 成对使用。
- 支持嵌套。
- 尽量保持临界段耗时短。
进入临界区:关闭中断--》中断无法打断、任务无法切换(抢占)
挂起任务调度器:关闭任务切换(抢占),但可以中断打断
挂起任务调度器,适用于临界区位于任务与任务之间,不会造成中断的延时【临界区保护开始会关闭中断,最后会执行开中断,如果中间任务代码过多,就会导致中断延时】,可以做到临界区的安全
延时函数会调用任务调度器的挂起和恢复
任务调度器的挂起:++uxSchedulerSuspended变量
PendSV的中断是来实现我们任务的切换【在Systic滴答定时器中断里】
此处的悬起是开启的意思
如果函数的返回值不等于pdfalse 那么就开启pendsv'的中断
是pdfalse就不开启pendsv的中断。也就不会开启任务的切换了
在xtaskIncremenTick函数里
会对uxSchedulerSuspended变量进行判断
但uxSchedulerSuspended一开始就被赋予了pdfalse【0】,在开启任务调度器挂起时此变量进行++,那么在此判断里就无法执行。
那么就会进入else语句
最后返回上述变量,但这个变量在此函数内赋予的是pdfalse
退出时,这个函数的返回直接就是pdfalse了
那么就是
如果函数的返回值不等于pdfalse 那么就开启pendsv'的中断
是pdfalse就不开启pendsv的中断。也就不会开启任务的切换了
07任务调度器的挂起和恢复
一、任务调度器的挂起和恢复
1、任务调度器挂起和恢复函数
答:
使用格式示范:
2、任务调度器挂起和恢复的特点
答:
- 与临界区不一样的是,挂起任务调度器,未关闭中断。
- 它仅仅是防止任务之间的资源争夺,中断照样可以直接响应。
- 挂起任务调度器的方式,适用于临界区位于任务与任务之间;既不用去延时中断响应,又可以做到临界区的安全。
3、挂起任务调度器:vTaskSuspendAll()
答:调用一次挂起调度器,该变量uxSchedulerSuspended就加一 ,变量uxSchedulerSuspended的值,将会影响Systick触发PendSV中断,即影响任务调度。
4、恢复任务调度器:xTaskResumeAll()
答:调用一次恢复调度器,该变量uxSchedulerSuspended就减一 ,如果uxSchedulerSuspended等于0,则允许调度 。
- 当任务数量大于0时,恢复调度器才有意义,如果没有一个已创建的任务就无意义。
- 移除等待就绪列表中的列表项,恢复至就绪列表,直到xPendingReadyList列表为空。
- 如果恢复的任务优先级比当前正在执行任务优先级更高,则将xYieldPending赋值为pdTRUE,表示需要进行一次任务切换。
- 在调度器被挂起的期间内,是否有丢失未处理的滴答数。 xPendedCounts是丢失的滴答数,有则调用xTasklncrementTickf() 补齐弄失的滴答数。
- 判断是否允许任务切换。
- 返回任务是否已经切换;已经切换返回pdTRUE;反之返回pdFALSE。
08列表和列表项
一、列表和列表项的简介(熟悉)
1、什么是列表
答:列表是FreeRTOS中的一个数据结构,概念上和链表有点类似,列表被用来跟踪FreeRTOS中的任务。
2、什么列表项
答:列表项就是存放在列表中的项目。
3、列表和列表项关系
答:列表相当于链表,列表项相当于节点,FreeRTOS中的列表是一个双向环形链表。
4、列表(链表)和数组的区别
答:
- 列表的特点:列表项间的地址非连续的,是人为的连接到一起的。列表项的数目是由后期添加或删除的个数决定的,随时可以改变。
- 数组的特点:数组成员地址是连续的,数组在最初确定了成员数量后,后期将无法改变。
5、OS中为什么使用列表
答:在OS中任务的数量是不确定的,并且任务状态是会发生改变的,所以非常适用列表(链表)这种数据结构。
6、列表结构体介绍
答:有关列表的东西均在文件list.c和list.h中,以下是列表结构体:
- 在结构体中,包含两个宏(listFIRST_LIST_INTEGRITY_CHECK_VALUE 和 listSECOND_LIST_INTEGRITY_CHECK_VALUE),这两个宏是确定的已知常量,FreeRTOS通过检查这两个常量的值,来判断列表的数据在程序运行过程中,是否遭到破坏,该功能一般用于测试,默认是不开启的(我们一般不用去理会)。
- 成员uxNumberOfltems,用于记录列表中的列表项的个数(不包括xListEnd)。
- 成员pxIndex用于指向列表中的某个列表项,一般用于遍历列表中的所有列表项。
- 成员变量xListEnd是一个迷你列表项,排在最末尾。
列表结构示意图:
7、列表项结构体介绍
答:列表项是列表中用于存放数据的地方,在list.h文件中,列表项的相关结构体定义:
- 成员变量xItemValue为列表项的值,这个值多用于按升序对列表中的列表项进行排序。
- 成员变量pxNext和pxPrevious分别用于指向列表中列表项的下一个列表项和上一个列表项。
- 成员变量pxOwner用于指向包含列表项的对象(通常是任务控制块)。
- 成员变量pxContainer用于执行列表项所在列表。
列表项结构体示意图:
8、迷你列表项
答:迷你列表项也是列表项,但迷你列表项仅用于标记列表的末尾和挂载其他插入列表中的列表项。
- 成员变量xItemValue为列表项的值,这个值多用于按升序对列表中的列表项进行排序。
- 成员变量pxNext和pxPrevious分别用于指向列表中列表项的下一个列表项和上一个列表项。
- 迷你列表项只用于标记列表的末尾和挂载其他插入列表中的列表项,因此不需要成员变量pxOwner和pxContainer,以节省内存开销。
迷你列表项示意图:
9、列表和列表项关系事例
答:
列表初始状态:
列表插入两个列表项:
列表当前状态:
二、列表相关的API函数介绍(掌握)
1、列表API函数
答:
2、初始化列表函数vListInitialise()
答:
函数参数:
列表初始化后示意图:
3、初始化列表项函数vListInitialiseItem()
答:
函数参数:
列表初始化后示意图:
4、列表插入列表项函数vListInsert()
答:此函数用于将待插入列表的列表项按照列表项值升序进行排序,有序地插入到列表中 。
函数参数:
总结:函数vListInsert(),是将插入列表的列表项按照列表项值升序进行排列,有序地插入到列表中。
5、列表末尾插入列表项vListInsertEnd()
答:此函数用于将待插入列表的列表项插入到列表 pxIndex 指针指向的列表项前面,是一种无序的插入方法。
标签:优先级,函数,FreeRTOS,中断,列表,任务 From: https://blog.csdn.net/weixin_69945979/article/details/143654034