【LiteOS】小白进阶之常用 LiteOS 任务接口与基础原理详解(一)
LiteOS 的任务是调度执行的最小单元,主要按照优先级抢占,辅以时间片轮转的方式进行调度。
任务的操作和维护保护创建、删除、调用、挂起、恢复、切换、sleep 等。
任务间的交互可以通过消息或事件进行,同时支持使用互斥锁 MUX 或信号量 semphore来 进行活动的互斥同步。
任务可以分为不同的优先级,优先级用 0-31 表示,其中 0 为最高优先级。
1、系统的启动
从 vendor.s 文件 __vector_table 开始运行,首先初始化 MSP 的地址,然后调用 Reset_Handler 函数,在 reset 函数中跳转 __iar_program_start,然后进入 main 函数,在 main 函数中进行了内存、任务等初始化,随后启动系统任务开始调度。
vendor.s 只是系统刚启动时运行,而对于中断向量函数表,在初始化时配置 OS_NVIC_VTOR 寄存器进行重新定位。
2、关于中断
在 CortexM4 上存在256中断号,支持多个优先级配置,16-255为可配置的IRQ,0-15依次分别为栈顶位置(MSP)、复位、NMI(不可屏蔽中断)、硬件错误、memory管理错误、总线错误、使用错误(指令或处理器状态转换)、7-10保留、SVC、调用监控(用于软件调试)、13保留、PendSV(用于任务上下文切换)、sysTick(系统时间片调度)。
为了某些特殊情况下禁止中断的响应,M4有三个特殊的寄存器PRIMASK\FAULTMASK\BASEPRI,能够在特权模式下访问;
PRIMASK可用来禁止除了NMI和HardFault以外中断;
FAULTMASK用来屏蔽除了NMI以外的中断;
BASEPRI用于禁止一些优先级比较低的中断。
3、任务优先级实现
#define LOS_PRIORITY_QUEUE_PRIORITYNUM 32
LITE_OS_SEC_BSS LOS_DL_LIST
*g_pstLosPriorityQueueList;//g_pstLosPriorityQueueList通过malloc对应LOS_PRIORITY_QUEUE_PRIORITYNUM大小的存储块。
LiteOS实现中对每一个优先级的任务使用了一个链表,当任务需要切换时,则从g_pstLosPriorityQueueList高优先级任务队列开始查找需要执行的任务。
4、时间片轮转
关于时间片:基于Tick来处理,Tick时钟在Cortex M4环境中通过SysTick Control的相关寄存器来配置。
SysTick是基于clk来计数,所以配置SysTick时根据系统的主频以及自定义的Tick时长来计算。
在正确配置SysTick寄存器的基础上,每个Tick会产生一个中断,中断号为15。
在Tick的中断服务程序中,进行时间片的计算,软件定时器的处理等,所以软件定时器的精度和Tick的精度有一定依赖性。
在任务运行达到系统设定的时间片Tick数目时,可进行显示的放权,进而调用其他任务,已达到时间片轮转的目的。
5、互斥锁与信号量
liteOS中都采用PV操作,即PV操作(pend post)。主要差别在于信号量允许多个任务重入,在创建信号量时,可以设置最大重入次数。
6、任务上下文的切换
所谓任务的上下文切换,理解上是在任务切换时,对任务当前环境变量进行保存,以便于任务切换回来时恢复现有状态。
任务的上下文切换,在中断 PendSV 的服务程序中实现,理解上好处:在中断处理避免了在线程中处理时,中断打断上下文切换的需要处理情况。
ICSR(Interrupt Control and State Register)使得用户在需要进行上下文切换时可以配置相应寄存器,以达到触发 PendSV 中断的目的。
7、任务堆栈的实现
在 cortexM4 系统中存在两种堆栈:MSP、PSP,亦即主堆栈指针及进程堆栈指针,在进入中断处理服务程序时用MSP,而在用户线程运行时需要使用PSP。
在cortexM4中可以通过配置CONTROL寄存器的方式来选择MSP或PSP。
CONTROL寄存器的定义:
CONTROL[0]:0-特权级线程,1-用户级线程,在中断处理服务程序中用于为特权级线程;CONTROL[1]:0-选择主堆栈指针MSP,1-选择进程堆栈指针PSP。
对于特殊寄存器的控制需要使用特殊的MSR/MRS指令进行操作,所以一般相关代码需要汇编实现,在liteOS中最底层任务相关汇编函数放在dispatch.s中。
8、消息队列与事件
消息队列顾名思义就是先进先出FIFO,LiteOS中消息队列可以用来在不同任务之间进行数据的交互。而事件event用来各个任务的同步,相对每个任务只能读取一个消息队列的限制,事件没有这样的要求,但同时事件不提供任务间的数据传输功能。理解上事件更像与多个任务的独立的存在,而消息队列却具有一定的相关性。在LiteOS中消息队列和事件都支持超时机制,当然超时可以设置成两种极限情形:立即响应和用于等待。
9、任务调度详解
系统有两个任务调度函数:
-
VOID osSchedule(VOID)
-
VOID LOS_Schedule(VOID)
这两个函数最终会调用到汇编编写的 osTaskSchedule() 函数,在移植的时候要根据不同的内核来修改,在 COTEX-M3 函数内核中用的是 pendsv 中断来切换任务。
-
osTaskSchedule
-
LDR R0, =OS_NVIC_INT_CTRL
-
LDR R1, =OS_NVIC_PENDSVSET
-
STR R1, [R0]
-
BX LR
该函数就是直接操作寄存器触发 pendsv 异常:
-
PendSV_Handler
-
MRS R12, PRIMASK
-
CPSID I
-
-
LDR R2, =g_pfnTskSwitchHook
-
LDR R2, [R2]
-
CBZ R2, TaskSwitch
-
PUSH {R12, LR}
-
BLX R2
-
POP {R12, LR}
异常直接调用 TaskSwitch 函数:
-
TaskSwitch
-
MRS R0, PSP
-
-
STMFD R0!, {R4-R12}
-
VSTMDB R0!, {D8-D15}
-
-
LDR R5, =g_stLosTask
-
LDR R6, [R5]
-
STR R0, [R6]
-
-
LDRH R7, [R6 , #4]
-
MOV R8,#OS_TASK_STATUS_RUNNING
-
BIC R7, R7, R8
-
STRH R7, [R6 , #4]
-
-
LDR R0, =g_stLosTask
-
LDR R0, [R0, #4]
-
STR R0, [R5]
-
-
LDRH R7, [R0 , #4]
-
MOV R8, #OS_TASK_STATUS_RUNNING
-
ORR R7, R7, R8
-
STRH R7, [R0 , #4]
-
-
LDR R1, [R0]
-
VLDMIA R1!, {D8-D15}
-
LDMFD R1!, {R4-R12}
-
MSR PSP, R1
-
-
MSR PRIMASK, R12
-
BX LR
任务调度函数就是通过操作全局变量 g_stLosTask,把当前任务的寄存器入栈,其实就是存在任务控制块中 pStackPointer 指向的内存里面,然后把最新的就绪任务弹出来,就实现了任务切换。
-
typedef struct tagTaskCB
-
{
-
VOID *pStackPointer; /**< Task stack pointer */
-
UINT16 usTaskStatus;
-
UINT16 usPriority;
-
UINT32 uwStackSize; /**< Task stack size */
-
UINT32 uwTopOfStack; /**< Task stack top */
-
UINT32 uwTaskID; /**< Task ID */
-
TSK_ENTRY_FUNC pfnTaskEntry; /**< Task entrance function */
-
VOID *pTaskSem; /**< Task-held semaphore */
-
VOID *pThreadJoin; /**< pthread adaption */
-
VOID *pThreadJoinRetval; /**< pthread adaption */
-
VOID *pTaskMux; /**< Task-held mutex */
-
UINT32 auwArgs[4]; /**< Parameter, of which the maximum number is 4 */
-
CHAR *pcTaskName; /**< Task name */
-
LOS_DL_LIST stPendList;
-
LOS_DL_LIST stTimerList;
-
UINT32 uwIdxRollNum;
-
EVENT_CB_S uwEvent;
-
UINT32 uwEventMask; /**< Event mask */
-
UINT32 uwEventMode; /**< Event mode */
-
VOID *puwMsg; /**< Memory allocated to queues */
-
} LOS_TASK_CB;
文章来源: blog.csdn.net,作者:简一商业,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/liwei16611/article/details/86581096
- 点赞
- 收藏
- 关注作者
评论(0)