FreeRTOS基本介绍、列表、移植、值得注意的点

1、FreeRTOS:

(1)调度策略使用了抢占式调度和时间片调度的结合,不同级别间的任务抢占式调度,同级别任务采用时间片调度。采用了动态内存申请。

(2)任务优先级:数字越高,任务优先级越高。STM32中最大为32-1

(3)时间片的长度,依据滴答定时器的设定。滴答定时器为最高优先级

(4)任务切换:高优先级会延时释放CPU控制权

电机控制任务balance:100Hz频率运行,优先级为4(vTaskDelayUntil()函数)

OLED显示任务show: 1Hz频率运行,优先级为3(vTaskDelayUntil()函数)

消息帧任务modbus:优先级为0,没有更高优先级任务抢占时会一直运行

 (但这样相当于一直占用空闲CPU的资源,设置为更高优先级可能会更好)

vTaskDelayUntil()函数:FreeRTOS中任务延时函数之一,让任务按照指定周期性方式运行。会使任务挂起,直至指定时间到达为止。时间为:上次此任务运行的时间+周期频率。

(5)任务堆栈:任务切换时,存储任务数据的内存区域。设置为了512

(6)滴答定时器

时间节拍频率设置为1000,周期1ms

初始化于delay_init(u8 SYSCLK)函数,SYSCLK=168

reload是滴答定时器的计数值。

reload = SYSCLK*100000/configTICK_RATE_HZ = 168*1000000/1000 = 168*1000

所以单次时间:reload/168M = 1ms

(7)开始任务start_task:用于创建其他任务

(8)临界区:相当于关中断,关闭所有优先级的中断

创建完start_task任务后退出临界区

(9)任务调度器的挂起:未关闭中断,只是停止任务的切换,不会被其他任务打断

仅仅防止了任务间的资源争夺

vTaskSuspend()、vTaskResume()挂起单个任务

(10)FreeRTOS的中断管理:

通常只能管理5~15优先级的,通过portDISABLE_INTERRUPTS(),优先级分组默认为4,

设置FreeRTOS可管理的最高优先级,优先级高于5的都无法管理

(11)中断优先级分组

STM32用了中断优先级配置寄存器的高4位[7:4]来配置,最大16级优先级,5种分配方式

FreeRTOS中默认是用优先级分组4,不使用子优先级,方便抢占优先级判断。

2、FreeRTOS列表:双向环形链表

(1)列表

就绪列表:每个优先级都有一个列表,有标志位,当该优先级列表中有任务时置1,共32个

阻塞列表:因等待事件而被阻塞的任务

(2)列表结构体

uxNumberOfItems:列表中的列表项数量

*pxIndex:用于遍历列表项的指针

xListEnd:列表末尾项,就是一个列表项,方便对列表操作

(3)列表项结构体

xItemValue:列表项的值,用于确定插入列表时的位置

*pxNext:下一个列表项

*pxPrevious:上一个列表项

*pvOwner:列表项的拥有者,即任务

*pxContainer:列表项所在列表

(4)列表和列表项的初始化

最开始只需要给定一个该结构体类型的指针即可,函数中自动完成创建

(5)列表项的插入:两种方式

              vListInsert( ):根据列表项值插入

              vListInsertEnd( ):插入到pxIndex所指向列表项的前面

指定要插入的列表和列表项

3、FreeRTOS移植

移植步骤:

(1)添加FreeRTOS源码

include:FreeRTOS头文件,FreeRTOS.h、task.h、timers.h等

portable:FreeRTOS的移植文件。只保留Keil、RVDS、MemMang这三个。

              Keil:指向RVDS文件夹

              RVDS:不同内核芯片的移植文件

              MemMang:内存管理文件

croutine.c:协程相关文件

event_groups.c:时间相关文件

list.c:列表相关文件

queue.c:队列相关文件

stream_buffer.c:流式缓冲区相关文件

tasks.c:任务相关文件

timers.c:软件定时器相关文件

(2)添加FreeRTOSConfig.h:

FreeRTOS操作系统的配置文件。FreeRTOS操作系统是可裁剪的,可以根据需求裁剪掉不需要用到的FreeRTOS功能,以此来节约MCU中内存资源。

三种获取途径:1、自行编写,根据需求裁剪 2、官方提供的演示工程 3、正点原子工程

(3)修改SYSTEM文件:

sys.h:定义系统文件夹是否支持FreeRTOS,宏SYSTEM_SUPPORT_OS改为1

usart.c:添加FreeRTOS头文件,删掉原先UCOS部分的代码(正点写的)

delay.c:对滴答定时器SysTick设定

1、SysTick_Handler():中断服务函数中添加xPortSysTickHandler();

2、delay_init():初始化SysTick重装载值等,设定FreeRTOS心跳节拍

7、FreeRTOS消息队列

(1)消息队列

是任务到任务、任务到中断、中断到任务数据交流的一种机制(消息传递)

(2)队列的读写

对队列读写时都会进入临界区(关中断)防止多任务冲突。

(任务切换依靠PendSV,是最低优先级,可以停止任务切换)

写队列xQueueSend(),读队列xQueueReceive()。函数中包含了临界区的使用。

(3)队列数据传输方式

可以传递数据和指针(大数据时)

(4)阻塞时间设置

0:直接返回不等待

0~port_MAX_DELAY:若在阻塞时间内无法入队,超时后直接返回不再等待

Port_MAX_DELAY:死等,直到可以入队为止。出队阻塞与入队阻塞类似。

(5)队列操作基本过程:
a、创建队列

b、往队列写入消息

c、从队列读取消息。若无数据,则阻塞

(6)队列结构体

存储区域起始地址pcHead:首个队列项

下一个写入位置pcWriteTo:下个队列项位置

等待发送列表xTasksWaitingToSend、等待接收列表xTasksWaitingToReceive

非空闲队列项目数量uxMessagesWaiting

队列长度uxLength

队列项目大小:单个队列项大小uxItemSize

上锁计数器cRxLock:cRxLock上锁的时候,是无法操作等待发送列表xTaskWaitingToSend和等待接收列表的xTaskWaitingToReceive,

(7)创建过程

a、定义队列句柄,创建队列

        

        

        

         第一个参数为队列中包含的最大项目数,第二个参数为每个项目所需的字节数。

b、不同按键值,入不同队

        

        

c、读取小数据队列

        

        

d、读取大数据队列

        

        

FreeRTOS值得注意的点

1、中断可以打断任意任务(不管优先级有多高)

2、任务可以同等优先级(软件上数量没有限制,使用时间片调度(应该要先设置为时间片调度)策略分配时间片)

3、如果高优先级任务一直在运行会怎么样?会一直运行,使得低优先级任务无法运行。(除非高优先级任务进入阻塞状态,释放CPU控制权)

4、优先级软件上没有限制,STM32硬件上限制为0~31;

5、优先级的高低与中断相反,数字越大,优先级越高。

6、FreeRTOS中,时间片调度时,每次每个任务只能使用一个时间片,若要增加运行时间,只能是设置SysTick中断周期(一个时间片就等于SysTick(滴答定时器)中断周期)。但ucos中可以设置每次运行2个、3个时间片。。。

7、

优先级策略调度与FreeRTOS中的调度器所使用的调度算法(例如时间片轮转、抢占式调度算法)之间有密切的关系,因为优先级策略决定了任务在调度器中执行的顺序和方式。

8、FreeRTOS为了方便管理,采用组4中断优先级分组,就不必区分子优先级,只用管抢占优先级。

9、中断服务函数若要调用FreeRTOS的API函数,中断服务函数的优先级需要在FreeRTOS的管理范围内,如5~15;他同时若在中断服务中调用,必须带有“FromISR”后缀的函数

10、FreeRTOS中断管理由BASEPRI寄存器实现:BASEPRI:屏蔽优先级低于某一个阈值的中断,设置为0时,则不关闭任何中断。(FreeRTOS可管理的最大优先级(中断的))

11、通过portDISABLE_INTERRUPTS()可以关闭比BASEPRI设置的优先级高的中断(禁止所有中断),比如: BASEPRI设置为0x50,代表中断优先级在5~15内的均被屏蔽,0~4的中断优先级正常执行。portENABLE_INTERRUPTS()打开中断。

12、SVC中断只会在启动第一次任务时,调用一次,以后都不调用,后面的任务切换都是在PenSV中断实现的

13、任务切换的过程在PendSV中断服务函数内完成

14、往任务堆栈内写入的位置,其实就是一块块内存,不是寄存器,出栈的时候就出栈到对应的寄存器里面

15、任务堆栈是由高地址向下,向低地址生长的

16、系统延时函数vTaskDelay(10)会释放当前任务的CPU的使用权给其他任务,引起任务调度,把当前运行的任务挂载到阻塞列表。

用自己写的延时函数delay_ms(10)会死等,不会引发任务调度

17、堆栈大小的设置:用于存放任务切换时,需要保存的资源。

18、在调度任务中,不同优先级任务,按优先级别高低顺序来执行,即抢占式任务调度策略,高优先级需要通过延时函数vTaskDelay(10);释放自身CPU使用权,低优先级任务才能运行,同时同一优先级任务按时间片调度策略运行,每个任务只运行很短的时间1ms,最后若是两个任务相同,相当于同时完成。

19、扫描检测按键时,需要保持按下状态才能被检测到,vTaskDelay(10)时,由于时间短,按下几乎都能成功检测。但当vTaskDelay(1000),几乎需要长按1s以上才能保证每次都被检测到

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值