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 ,然后恢复即将切换到任务的现场。

最新文章

  1. 黄聪:C#带cookie模拟登录百度
  2. 【原】如何在jQuery中实现闭包
  3. Sharepoint学习笔记—习题系列--70-576习题解析 -(Q29-Q31)
  4. window_x64微信小程序环境搭建
  5. hdu 4267 多维树状数组
  6. Java中main方面面试题
  7. Unity5.3官方VR教程重磅登场-系列2
  8. [译]Stairway to Integration Services Level 10 - 高级事件活动
  9. A hard puzzle 1097
  10. Java笔试题目-my
  11. soj 2543 完全二叉树
  12. Java 标记接口
  13. centos7 php-apache镜像添加redis/memcache/gd/mysql_pdo/mysqli/imagick
  14. iOS 10 应用内跳转到系统设置
  15. shell脚本--数值计算
  16. 运维人员word优化
  17. Python之生成器及内置函数篇4
  18. Java对象的内存(一)
  19. sqlserver年月日转汉字大写
  20. cxgrid中,如何根据列名或字段名取得footer值

热门文章

  1. 转:为什么需要htons(), ntohl(), ntohs(),htons() 函数
  2. 转:VC中UpdateData()函数的使用
  3. 监视系统3389的VBS脚本
  4. Entity Framework with MySQL 学习笔记一(拦截)
  5. java构造方法的不同
  6. java中文件操作的工具类
  7. grouth:全栈工程师指南
  8. Android设置上下边框或者左右边框
  9. 我对Laravel ThinkPHP Yii symfony2 CI cakephp 的看法
  10. RPM包查询