uC/OS 的任务调度解析 (转)
2024-08-22 19:17:10
|
1、任务调度器启动之后(初始化,主要是TCB的初始化),就可以创建任务,开始任务调度了,实际上第一个任务准确的说不是进行任务切换,而是进行启动当前最高优先级任务。uC/OS使用的是OSStartHighRdy
OSStartHighRdy
LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority
LDR R1, =NVIC_PENDSV_PRI
STRB R1, [R0] MOVS R0, #0 ; Set the PSP to 0 for initial context switch call
MSR PSP, R0 LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
LDR R1, =NVIC_PENDSVSET
STR R1, [R0] CPSIE I
需要解释的是,正是由于是启动第一个任务,所以当前的PSP的值为0(本因该是当前任务的堆栈指针),将该指针置零后才进行任务切换。
2、本来任务切换有两个,一个是任务级任务调度,一个是中断级任务调度,即OSCtxSw和OSIntCtxSw,任务切换就是产生中断,来进行SP的偷梁换柱,中断级任务调度时,就处在中断中,所以没有必要再次产生中断,可以直接偷梁换柱,只要稍作处理即可,但是一般的RTOS为了偷懒,OSIntCtxSw和OSCtxSw是一样的,没有做特殊处理
OSCtxSw
LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR
OSIntCtxSw
LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR
3、任务切换的代码就在Pen大SV中断函数中,一般是使用汇编实现,具体如下:
OS_CPU_PendSVHandler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer
CBZ R0, OS_CPU_PendSVHandler_nosave ; Skip register save the first time SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack
STM R0, {R4-R11} LDR R1, =OSTCBCurPtr ; OSTCBCurPtr->OSTCBStkPtr = SP;
LDR R1, [R1]
STR R0, [R1] ; R0 is SP of process being switched out ; At this point, entire context of process has been saved
OS_CPU_PendSVHandler_nosave
PUSH {R14} ; Save LR exc_return value
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
BLX R0
POP {R14} LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0] LDR R0, =OSTCBCurPtr ; OSTCBCurPtr = OSTCBHighRdyPtr;
LDR R1, =OSTCBHighRdyPtr
LDR R2, [R1]
STR R2, [R0] LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
LDM R0, {R4-R11} ; Restore r4-11 from new process stack
ADDS R0, R0, #0x20
MSR PSP, R0 ; Load PSP with new process SP
ORR LR, LR, #0x04 ; Ensure exception return uses process stack
CPSIE I
BX LR
在上面提到,一开始启动任务时,PSP的值为0,所以在此中断中进行了一次判断(Skip register save the first time),此时是不需要进行现场保护的(R4-R11),否则保护现场之后,改变当前的OSPrioCur,OSTCBCurPtr ,然后恢复即将切换到任务的现场。
最新文章
- 黄聪:C#带cookie模拟登录百度
- 【原】如何在jQuery中实现闭包
- Sharepoint学习笔记—习题系列--70-576习题解析 -(Q29-Q31)
- window_x64微信小程序环境搭建
- hdu 4267 多维树状数组
- Java中main方面面试题
- Unity5.3官方VR教程重磅登场-系列2
- [译]Stairway to Integration Services Level 10 - 高级事件活动
- A hard puzzle 1097
- Java笔试题目-my
- soj 2543 完全二叉树
- Java 标记接口
- centos7 php-apache镜像添加redis/memcache/gd/mysql_pdo/mysqli/imagick
- iOS 10 应用内跳转到系统设置
- shell脚本--数值计算
- 运维人员word优化
- Python之生成器及内置函数篇4
- Java对象的内存(一)
- sqlserver年月日转汉字大写
- cxgrid中,如何根据列名或字段名取得footer值
热门文章
- 转:为什么需要htons(), ntohl(), ntohs(),htons() 函数
- 转:VC中UpdateData()函数的使用
- 监视系统3389的VBS脚本
- Entity Framework with MySQL 学习笔记一(拦截)
- java构造方法的不同
- java中文件操作的工具类
- grouth:全栈工程师指南
- Android设置上下边框或者左右边框
- 我对Laravel ThinkPHP Yii symfony2 CI cakephp 的看法
- RPM包查询