FreeRTOS一些知识笔记【1】

【FreeRTOS列表和列表项】
列表项有两种,全功能版的列表项xLIST_ITEM和迷你版的列表项xMINI_LIST_ITEM
全功能版的列表项有  检查完整性,列表项值,pnext,pprevious,TCB,pcontainer
迷你版的列表项有    检查完整性,列表项值,pnext,pprevious
一个List中,ListEnd就是一个mini列表项
List排序通过ListItemValue来排序的




【任务创建详解】
1.创建任务堆栈和任务TCB,实际是申请任务堆栈和TCB堆栈
2.初始化任务TCB必要的字段
3.初始化任务堆栈
4.进入临界区
5.当前任务数量增加1
6.更新任务就绪列表pxReadyTasksLists[priority],priority就是新建任务的
  优先级,保证同一个优先级的任务可以放在同一个列表下,且可以快速找到
7.更新当前正在运行的任务 TCB 指针 pxCurrentTCB(主要看优先级)
8.退出临界区
9.执行上下文切换




【任务调度器】
任务启动和任务切换主要使用
SVC      系统服务函数,用于任务启动
PendSV   可挂起系统调用,用于完成任务切换
SysTick  产生系统时钟节拍,提供时间片


任务调度器
1.创建空闲任务
2.是否使能软件定时器
3.关中断
4.初始化滴答定时器,FPU,PendSV
5.获取MSP初始值
6.使能中断
7.使用汇编指令svc 0触发SVC中断引起SVC中断
8.开启第一个任务
9.以后的任务切换用PendSV中断服务函数


【任务切换】
FreeRTOS有两种方法触发任务切换:
1.执行系统调用,比如普通任务可以使用taskYIELD()强制任务切换,中断服务程序
中使用portYIELD_FROM_ISR()强制任务切换;
2.系统节拍时钟中断


对于Cortex-M3平台,这两种方法的实质是一样的,都会使能一个PendSV中断,在
PendSV中断服务程序中,找到最高优先级的就绪任务,然后让这个任务获得CPU运
行权,从而完成任务切换。


在PendSV中
1.使用PSP进程堆栈指针,将PC,LR,R12,R3~R0压栈
2.开始使用MSP主堆栈指针
3.将R11~R4压栈
4.进入临界区
5.切换上下文,找到下一个要执行的任务,pxCurrentTCB指向下一个任务TCB
6.退出临界区
7.获取下一个任务TCB的堆栈地址,将R11~R4出栈
8.跟新PSP进程堆栈指针,使之指向任务堆栈
9.退出中断,将PC,LR,R12,R3~R0出栈




【FreeRTOS队列分析】
二进制信号量、计数信号量、互斥量和递归互斥量都是使用队列来实现的


二进制信号量其实是一个队列项为1,大小为0的队列,其本质是调用
uxMessageWaiting 来实现的。
获取二进制:对于二进制信号量和计数信号量,可以简化为三种情况:
第一,如果队列不为空,队列结构体成员 uxMessageWaiting 减1,判断
是否有因入队而阻塞的任务,有的话解除阻塞,然后返回成功信息(pdPASS);
第二,如果队列为空并且阻塞时间为0,则直接返回错误码(errQUEUE_EMPTY),
表示队列为空;
第三,如果队列为空并且阻塞时间不为0,则任务会因为等待信
号量而进入阻塞状态,任务会被挂接到延时列表中。


【FreeRTOS任务通知分析】
volatile uint32_t ulNotifiedValue;  
/*任务通知值*/    
volatile uint8_t ucNotifyState; 
/*任务通知状态,标识任务是否在等待通知等*/  
任务通知的局限性:只能有一个任务接收通知事件


【FreeRTOS系统延时分析】
相对延时函数其实是相对于调用vTaskDelay()开始计时的
绝对延时函数其实是保证任务按一定频率周期性的阻塞和执行


如果要想正真精确周期性执行某个任务,可以使用系统节拍钩子函数
vApplicationTickHook(),它在系统节拍中断服务函数中被调用,因
此这个函数中的代码必须简洁。


【FreeRTOS系统时钟节拍分析】
系统节拍中断服务程序会调用函数xTaskIncrementTick()来完成主要
工作,如果该函数返回值为真(不等于pdFALSE),说明处于就绪态任
务的优先级比当前运行的任务优先级高。这会触发一次PendSV中断,
进行上下文切换。


xTickCount+xTicksToDelay会被记录到任务TCB中,随着任务一起挂接
到延时列表。如果内核判断出xTickCount+ xTicksToDelay溢出
(大于32位可以表示的最大值),就将当前任务挂接到列表指针
pxOverflowDelayedTaskList指向的列表中,否则就挂接到列表
指针pxDelayedTaskList指向的列表中。任务按照延时时间,顺序
的插入到延时列表中。
所以当系统节拍中断次数计数器xTickCount溢出时,必须将延时
列表指针pxDelayedTaskList和溢出延时列表指针pxOverflowDelayedTaskList
交换以便正确处理延时的任务。


【FreeRTOS空闲任务分析】
1.vTaskDelete(NULL),有任务删除了自己,他的TCB和堆栈就交给空闲任务来释放
2.钩子函数


流程:
1.释放自己删自己的那个任务的内存
2.是否使用抢占式内核,没用的话就强行发起一次任务切换,保证最高优先级任务能得到响应
3.使用抢占式内核的话,就执行同优先级的其他任务,不需要用户自己强制任务切换了
4.使能钩子函数的话,就调用钩子函数
5.是否使能Tickless低功耗模式,使能的话就进入低功耗


【FreeRTOS临界段】
由于在临界段中要关中断和开中断,所以实际操作的是BASEPRI寄存器,
向寄存器BASEPRI写入MAX,那么优先级低于MAX的中断就会被屏蔽。


FreeRTOS有四个临界段代码保护函数,两个任务级,两个中断级
在临界段代码保护中,优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY(优先级数一样)
的中断将得不到响应,所以,在中断级临界段段中,那个中断函数的优先级一定要低于
configMAX_SYSCALL_INTERRUPT_PRIORITY。


在F103的FreeRTOS例程中
#define configMAX_SYSCALL_INTERRUPT_PRIORITY
( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
configPRIO_BITS=4,configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY =5,
这样一来,configMAX_SYSCALL_INTERRUPT_PRIORITY =80,那不是所有中断都可以调用临界段
了。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值