【RTOS知识点】RTOS相关知识点(更新中)

  • Post author:
  • Post category:其他



一、什么是任务?


在裸机系统中,系统的主体就是 main 函数里面顺序执行的无限循环,这个无限循环里

面 CPU 按照顺序完成各种事情。在多任务系统中,我们根据功能的不同,把整个系统分割

成一个个独立的且无法返回的函数,这个函数我们称为任务。具体代码如下:
void task_entry (void *parg)
{
/* 任务主体,无限循环且不能返回 */
  for (;;)
 {
/* 任务主体代码 */
 }
}


二、操作模式以及特权级别

1、操作模式:处理者模式(handler mode,以后不再把 handler 中译——译注)和线程模式(thread mode)。引入两个模式的本意,是用于区别异常服务例程的代码——包括中断服务例程的代码,普通应用程序的代码。

2、特权级别:特权级和用户级,主要是提供一种存储器访问的保护机制,使得普通的用户程序代码不能意外地,甚至是恶意地执行涉及到要害的操作。

合法的操作流程如下图:(如果看不懂可以参考CM3权威指南)


三、Cortex-M3 的双堆栈机制

1、堆栈指针:

主堆栈指针(MSP),或写作SP_main。这是缺省的堆栈指针,它由OS内核、异常服务例程以及所有需要特权访问的应用程序代码来使用。

进程堆栈指针(PSP),或写作SP_process。用于常规的应用程序代码(不处于异常服用例程中时)。


2、当


CONTROL[1]=0


时,只使用


MSP


,此时用户程序和异常


handler


共享同一个堆栈。


3、当


CONTROL[1]=1


时,线程模式将不再使用


MSP


,而改用


PSP





handler


模式永远使用


MSP)。


进入异常时的自动压栈使用的是进程堆栈,进入异常 handler 后才自动改为 MSP,退出异常时切换回PSP,并且从进程堆栈上弹出数据。


四、异常返回

当异常服务例程执行完毕后,需要很正式地做一个“异常返回”动作序列,从而恢复先前的系 统状态,才能使被中断的程序得以继续执行。从形式上看,有3种途径可以触发异常返回序列,如 表9.2所示。而不管使用哪一种,都需要用到先前储到LR的EXC_RETURN。

在进入异常服务程序后,将自动更新LR的值为特殊的EXC_RETURN。这是一个高 28位全为1的值,只有[3:0]的值有特殊含义,如表9.3所示。当异常服务例程把这个值送往PC时,就 会启动处理器的中断返回序列。因为LR的值是由CM3自动设置的,所以只要没有特殊需求,就不要 改动它。

如果主程序在线程模式下运行,并且在使用MSP时被中断,则在服务例程中LR=0xFFFF_FFF9(主 程序被打断前的LR已被自动入栈)。 如果主程序在线程模式下运行,并且在使用PSP时被中断,则在服务例程中LR=0xFFFF_FFFD(主程序被打断前的LR已被自动入栈)。

如果主程序在Handler模式下运行,则在服务例程中LR=0xFFFF_FFF1(主程序被打断前的LR已被 自动入栈)。这时的所谓“主程序”,其实更可能是被抢占的服务例程。事实上,在嵌套时,更深 层ISR所看到的LR总是0xFFFF_FFF1,如图9.5所示。


五、什么是临界段


临界段用一句话概括就是一段在执行的时候不能被中断的代码段。

在 FreeRTOS 里面,这个临界段最常出现的就是对全局变量的操作。那么什么情况下临界段会被打断?一个是系统调度,还有一个就是外部中断。在FreeRTOS,系统调度,最终也是产生 PendSV中断,在 PendSV Handler 里面实现任务的切换,所以还是可以归结为中断。既然这样,FreeRTOS对临界段的保护最终还是回到对中断的开和关的控制。

为了快速地开关中断, Cortex-M


内核专门设置了一条


CPS


指令,有


4


种用法。
1 CPSID I ;PRIMASK=1 ;关中断
2 CPSIE I ;PRIMASK=0 ;开中断
3 CPSID F ;FAULTMASK=1 ;关异常
4 CPSIE F ;FAULTMASK=0 ;开异常

PRIMASK





FAULTMAST





Cortex-M内核 里面三个中断屏蔽寄存 器中的两个,还有一个是 BASEPRI。

在 FreeRTOS中,对中断的开和关是通过操作 BASEPRI 寄存器来实现的,即大


于等于


BASEPRI


的值的中断会被屏蔽,小于


BASEPRI


的值的中断则不会被屏蔽,不受FreeRTOS 管理。


六、空闲任务和阻塞延时

空闲任务:

空闲任务是系统在【启动调度器】的时候创建的优先级最低的任务,空闲任 务主体主要是做一些系统内存的清理工作。当任务需要延时,进入阻塞状态,那 CPU


又去干什么事情了?如果没有其它任务可以 运行,RTOS


都会为


CPU


创建一个空闲任务,这个时候


CPU


就运行空闲任务。


阻塞延时:即任务需要延时的时候,任务会放弃CPU


的使用权,


CPU


可以去干其它的事情,当任务延时时间到,重新获取CPU


使用权,任务继续运行,这样就充分地利用了


CPU


的资源。


七、任务优先级


就绪列表


pxReadyTasksLists[ configMAX_PRIORITIES ]


是一个数组,数组里面存的是就绪任务的 TCB


(准确来说是


TCB


里面的


xStateListItem


节点),数组的下标对应任务的 优先级,优先级越低对应的数组下标越小。空闲任务的优先级最低,对应的是下标为 0


的链表。任务在创建的时候,会根据任务的优先级将任务插入到就绪列表不同的位置。相同优先级的任务插入到就绪列表里面的同一条链表中,即时间片的支持。


八、延时列表





FreeRTOS


中,有一个任务延时列表(实际上有两个,为了方便讲解原理,我们假装合并为一个,其实两个的作用是一样的),当任务需要延时的时候,则先将任务挂起, 即先将任务从就绪列表删除,然后插入到任务延时列表,同时更新下一个任务的解锁时刻


变量:


xNextTaskUnblockTime 的值。


xNextTaskUnblockTime 的值等于系统时基计数器的值 xTickCount 加上任务需要延时的值 xTicksToDelay。当系统时基计数器 xTickCount 的值与 xNextTaskUnblockTime 相等时,就表示有任务延时到期了,需要将该任务就绪。


任务延时列表表维护着一条双向链表,每个节点代表了正在延时的任务,节点按照延 时时间大小做升序排列。当每次时基中断(SysTick


中断)来临时,就拿系统时基计数器的 值 xTickCount


与下一个任务的解锁时刻变量


xNextTaskUnblockTime


的值相比较,如果相 等,则表示有任务延时到期,需要将该任务就绪,否则只是单纯地更新系统时基计数器 xTickCount 的值,然后进行任务切换。


九、时间片


FreeRTOS


与隔壁的


RT-Thread





μC/OS


一样,都支持时间片的功能。所谓时间片就

是同一个优先级下可以有多个任务,每个任务轮流地享有相同的


CPU


时间,享有


CPU




时间我们叫时间片。在


RTOS


中,最小的时间单位为一个


tick


,即


SysTick


的中断周期,

RT-Thread





μC/OS


可以指定时间片的大小为多个


tick


,但是


FreeRTOS


不一样,时间片只

能是一个


tick


。与其说


FreeRTOS


支持时间片,倒不如说它的时间片就是正常的任务调度。



版权声明:本文为qq_29031103原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。