资料介绍
1:开始多任务函数 void OSStartHighRdy(void)
在OSInit()初始化完毕之后,会调用OSStart(),在OS开始函数里面会调用void OSStartHighRdy(void)函数,这是一个纯汇编编写的函数,在os_cpu_a.s这个汇编文件里面实现,具体的如下,我已经给每一句代码都添加了注释。
; 开始多任务
; void OSStartHighRdy(void)
;
; 注意 : 1) 这个函数触发了一个PendSV异常,导致第一个任务开始运行。
;
; 2) OSStartHighRdy() 必须:
; a) 设置PendSV的优先级为最低;
; b) 初始化进程堆栈指针PSP等于0, 表明这是第一次上下文切换;
; c) 设置主堆栈指针等于OS_CPU_ExceptStkBase
; d) 触发PendSV异常;
; e) 使能中断,任务开始运行。
;********************************************************************************************************
; 开始多任务
; void OSStartHighRdy(void)
;
; 注意 : 1) 这个函数触发了一个PendSV异常,导致第一个任务开始运行。
;
; 2) OSStartHighRdy() 必须:
; a) 设置PendSV的优先级为最低;
; b) 初始化进程堆栈指针PSP等于0, 表明这是第一次上下文切换;
; c) 设置主堆栈指针等于OS_CPU_ExceptStkBase
; d) 触发PendSV异常;
; e) 使能中断,任务开始运行。
;********************************************************************************************************
OSStartHighRdy
; 设置PendSV中断优先级
LDR R0, =NVIC_SYSPRI14
LDR R1, =NVIC_PENDSV_PRI
STRB R1, [R0] ;*R0=R1(低字节),因为表达优先级只需要8bit
; 初始化PSP=0
MOVS R0, #0 ; 把0加载到R0
MSR PSP, R0 ; 把R0的值加载到特殊寄存器PSP
; 初始化MSP地址
LDR R0, =OS_CPU_ExceptStkBase ; 把OS_CPU_ExceptStkBase这个指针变量的地址加载到R0
LDR R1, [R0] ; *R0 = R1,实际上就是把OS_CPU_ExceptStkBase的值加载到R1
MSR MSP, R1 ; 把R1的值加载到MSP,此时MSP=OS_CPU_ExceptStkBase
; 触发PendSV异常 (进入上下文切换)
LDR R0, =NVIC_INT_CTRL
LDR R1, =NVIC_PENDSVSET
STR R1, [R0] ; *R0 = R1
; 打开中断
CPSIE I
; 正常情况下,永远不会运行到这,因为这是一个死循环
OSStartHang
B OSStartHang
1:PendSV 异常服务函数 void OS_CPU_PendSVHandler(void)
OS_CPU_PendSVHandler
CPSID I ; 关中断,执行上下文切换的时候不能被中断,属于临界段
MRS R0, PSP ; 加载PSP(即R13)的值到R0
CBZ R0, OS_CPU_PendSVHandler_nosave ; R0的值为0则跳转到OS_CPU_PendSVHandler_nosave; CBZ:比较,如果结果为0就跳转
; 第一次进行上下文切换的时候PSP等于0,所以要进行跳转
SUBS R0, R0, #0x20 ; 压栈之前先调整堆栈指针,要压栈的寄存器R4-R11有8个,所以偏移为8*0x04=0x20
STM R0, {R4-R11} ; 手动将R4-R11压栈
; 实现 OSTCBCurPtr->OSTCBStkPtr = SP;
LDR R1, =OSTCBCurPtr ; R1=&OSTCBCurPtr,这个时候R1里面存的是OSTCBCurPtr这个指针变量的地址
LDR R1, [R1] ; R1=*R1=OSTCBCurPtr,这个时候,R1等于OSTCBCurPtr这个指针变量
STR R0, [R1] ; *R1=R0,这个时候OSTCBCurPtr指向的TCB的第一个成员(即OSTCBCurPtr->OSTCBStkPtr)等于R0
; R0又是一开始进行压栈的PSP,所以OSTCBCurPtr->OSTCBStkPtr = SP
; 程序运行到这个点上,进入上下文切换的过程已经保存好了
OS_CPU_PendSVHandler_nosave
PUSH {R14} ; 保存 LR exc_return 的值
LDR R0, =OSTaskSwHook ; 调用OSTaskSwHook()
BLX R0
POP {R14}
; 实现 OSPrioCur = OSPrioHighRdy;
LDR R0, =OSPrioCur ; R0=&OSPrioCur
LDR R1, =OSPrioHighRdy ; R1=&OSPrioHighRdy
LDRB R2, [R1] ; R2=*R1(低字节),因为优先级是8bit的,所以是低字节
STRB R2, [R0] ; R0=*R2(低字节),因为优先级是8bit的,所以是低字节
; 实现 OSTCBCurPtr = OSTCBHighRdyPtr;
LDR R0, =OSTCBCurPtr ; R0=&OSTCBCurPtr
LDR R1, =OSTCBHighRdyPtr ; R1=&OSTCBHighRdyPtr
LDR R2, [R1] ; R2=*R1
STR R2, [R0] ; R0=*R2
LDR R0, [R2] ; R0等于新的进程的SP; SP = OSTCBHighRdyPtr->StkPtr
; R2=OSTCBHighRdyPtr,则[R2]=*R2=OSTCBHighRdyPtr=StkPtr,因为TCB的第一个成员就是StkPtr
LDM R0, {R4-R11} ; 从新的堆栈中弹出R4-R11
ADDS R0, R0, #0x20 ; 重新调整堆栈指针,R4-R11为8个寄存器,每个寄存器为四个字节,8*4=32=0X20
MSR PSP, R0 ; 更新PSP的值
ORR LR, LR, #0x04 ; 判断LR寄存器的位4是否为1,确保异常返回用用的是PSP
CPSIE I ; 打开中断,上下文切换结束
BX LR ; 异常返回
END ; 汇编程序结束
; 只有在特权级下,才可以访问下面三个寄存器
; PRIMASK :这是个只有单一比特的寄存器。 在它被置 1 后,就关掉所有可屏蔽的异常,只剩下 NMI 和硬 fault 可以响应。它的缺省值是 0,表示没有关中断。
; FAULTMASK:这是个只有 1 个位的寄存器。当它置 1 时,只有 NMI 才能响应,所有其它的异常,甚至是硬 fault,也通通闭嘴。它的缺省值也是 0,表示没有关异常。
; BASEPRI :这个寄存器最多有 9 位( 由表达优先级的位数决定)。它定义了被屏蔽优先级的阈值。当它被设成某个值后,所有优先级号大于等于此值的中断都被关(优先级号
; 越大,优先级越低)。但若被设成 0,则不关闭任何中断, 0 也是缺省值。
;
; 为了快速的开关中断,CM3专门设置了一条CPS指令,有4种用法
; CPSID I //PRIMASK = 1, ;关中断
; CPSIE I //PRIMASK = 0, ;开中断
; CPSID F //FAULTMASK = 1, ;关异常
; CPSIE F //FAULTMASK = 0, ;开异常
在OSInit()初始化完毕之后,会调用OSStart(),在OS开始函数里面会调用void OSStartHighRdy(void)函数,这是一个纯汇编编写的函数,在os_cpu_a.s这个汇编文件里面实现,具体的如下,我已经给每一句代码都添加了注释。
; 开始多任务
; void OSStartHighRdy(void)
;
; 注意 : 1) 这个函数触发了一个PendSV异常,导致第一个任务开始运行。
;
; 2) OSStartHighRdy() 必须:
; a) 设置PendSV的优先级为最低;
; b) 初始化进程堆栈指针PSP等于0, 表明这是第一次上下文切换;
; c) 设置主堆栈指针等于OS_CPU_ExceptStkBase
; d) 触发PendSV异常;
; e) 使能中断,任务开始运行。
;********************************************************************************************************
; 开始多任务
; void OSStartHighRdy(void)
;
; 注意 : 1) 这个函数触发了一个PendSV异常,导致第一个任务开始运行。
;
; 2) OSStartHighRdy() 必须:
; a) 设置PendSV的优先级为最低;
; b) 初始化进程堆栈指针PSP等于0, 表明这是第一次上下文切换;
; c) 设置主堆栈指针等于OS_CPU_ExceptStkBase
; d) 触发PendSV异常;
; e) 使能中断,任务开始运行。
;********************************************************************************************************
OSStartHighRdy
; 设置PendSV中断优先级
LDR R0, =NVIC_SYSPRI14
LDR R1, =NVIC_PENDSV_PRI
STRB R1, [R0] ;*R0=R1(低字节),因为表达优先级只需要8bit
; 初始化PSP=0
MOVS R0, #0 ; 把0加载到R0
MSR PSP, R0 ; 把R0的值加载到特殊寄存器PSP
; 初始化MSP地址
LDR R0, =OS_CPU_ExceptStkBase ; 把OS_CPU_ExceptStkBase这个指针变量的地址加载到R0
LDR R1, [R0] ; *R0 = R1,实际上就是把OS_CPU_ExceptStkBase的值加载到R1
MSR MSP, R1 ; 把R1的值加载到MSP,此时MSP=OS_CPU_ExceptStkBase
; 触发PendSV异常 (进入上下文切换)
LDR R0, =NVIC_INT_CTRL
LDR R1, =NVIC_PENDSVSET
STR R1, [R0] ; *R0 = R1
; 打开中断
CPSIE I
; 正常情况下,永远不会运行到这,因为这是一个死循环
OSStartHang
B OSStartHang
1:PendSV 异常服务函数 void OS_CPU_PendSVHandler(void)
OS_CPU_PendSVHandler
CPSID I ; 关中断,执行上下文切换的时候不能被中断,属于临界段
MRS R0, PSP ; 加载PSP(即R13)的值到R0
CBZ R0, OS_CPU_PendSVHandler_nosave ; R0的值为0则跳转到OS_CPU_PendSVHandler_nosave; CBZ:比较,如果结果为0就跳转
; 第一次进行上下文切换的时候PSP等于0,所以要进行跳转
SUBS R0, R0, #0x20 ; 压栈之前先调整堆栈指针,要压栈的寄存器R4-R11有8个,所以偏移为8*0x04=0x20
STM R0, {R4-R11} ; 手动将R4-R11压栈
; 实现 OSTCBCurPtr->OSTCBStkPtr = SP;
LDR R1, =OSTCBCurPtr ; R1=&OSTCBCurPtr,这个时候R1里面存的是OSTCBCurPtr这个指针变量的地址
LDR R1, [R1] ; R1=*R1=OSTCBCurPtr,这个时候,R1等于OSTCBCurPtr这个指针变量
STR R0, [R1] ; *R1=R0,这个时候OSTCBCurPtr指向的TCB的第一个成员(即OSTCBCurPtr->OSTCBStkPtr)等于R0
; R0又是一开始进行压栈的PSP,所以OSTCBCurPtr->OSTCBStkPtr = SP
; 程序运行到这个点上,进入上下文切换的过程已经保存好了
OS_CPU_PendSVHandler_nosave
PUSH {R14} ; 保存 LR exc_return 的值
LDR R0, =OSTaskSwHook ; 调用OSTaskSwHook()
BLX R0
POP {R14}
; 实现 OSPrioCur = OSPrioHighRdy;
LDR R0, =OSPrioCur ; R0=&OSPrioCur
LDR R1, =OSPrioHighRdy ; R1=&OSPrioHighRdy
LDRB R2, [R1] ; R2=*R1(低字节),因为优先级是8bit的,所以是低字节
STRB R2, [R0] ; R0=*R2(低字节),因为优先级是8bit的,所以是低字节
; 实现 OSTCBCurPtr = OSTCBHighRdyPtr;
LDR R0, =OSTCBCurPtr ; R0=&OSTCBCurPtr
LDR R1, =OSTCBHighRdyPtr ; R1=&OSTCBHighRdyPtr
LDR R2, [R1] ; R2=*R1
STR R2, [R0] ; R0=*R2
LDR R0, [R2] ; R0等于新的进程的SP; SP = OSTCBHighRdyPtr->StkPtr
; R2=OSTCBHighRdyPtr,则[R2]=*R2=OSTCBHighRdyPtr=StkPtr,因为TCB的第一个成员就是StkPtr
LDM R0, {R4-R11} ; 从新的堆栈中弹出R4-R11
ADDS R0, R0, #0x20 ; 重新调整堆栈指针,R4-R11为8个寄存器,每个寄存器为四个字节,8*4=32=0X20
MSR PSP, R0 ; 更新PSP的值
ORR LR, LR, #0x04 ; 判断LR寄存器的位4是否为1,确保异常返回用用的是PSP
CPSIE I ; 打开中断,上下文切换结束
BX LR ; 异常返回
END ; 汇编程序结束
; 只有在特权级下,才可以访问下面三个寄存器
; PRIMASK :这是个只有单一比特的寄存器。 在它被置 1 后,就关掉所有可屏蔽的异常,只剩下 NMI 和硬 fault 可以响应。它的缺省值是 0,表示没有关中断。
; FAULTMASK:这是个只有 1 个位的寄存器。当它置 1 时,只有 NMI 才能响应,所有其它的异常,甚至是硬 fault,也通通闭嘴。它的缺省值也是 0,表示没有关异常。
; BASEPRI :这个寄存器最多有 9 位( 由表达优先级的位数决定)。它定义了被屏蔽优先级的阈值。当它被设成某个值后,所有优先级号大于等于此值的中断都被关(优先级号
; 越大,优先级越低)。但若被设成 0,则不关闭任何中断, 0 也是缺省值。
;
; 为了快速的开关中断,CM3专门设置了一条CPS指令,有4种用法
; CPSID I //PRIMASK = 1, ;关中断
; CPSIE I //PRIMASK = 0, ;开中断
; CPSID F //FAULTMASK = 1, ;关异常
; CPSIE F //FAULTMASK = 0, ;开异常
下载该资料的人也在下载
下载该资料的人还在阅读
更多 >
- STM32F0系列ucosIII移植笔记
- UCOSIII学习笔记(二)任务管理、Hook函数、中断
- 亲测有效的UCOSIII嵌入STM32F103C8T6实验,介绍常见移植问题,付实测代码!!!
- STM32f4—ucosiii移植代码工程 21次下载
- uCOSIII系统移植(二)构建多任务
- Oracle数据库-plsql-基础、函数讲解
- Oracle中常用的函数与表达式讲解
- EE-128:C++中的DSP:从C++调用汇编类成员函数
- 如何使用DSP汇编语言实现高精度的三角函数 7次下载
- UCOS移植过程全讲解教程免费下载 21次下载
- 单片机C函数中的嵌入汇编之形参传递详细资料说明
- CC1101与MSP430接口库移植到STM32的详细资料说明 17次下载
- ucosIII移植教程 94次下载
- UCOS扩展例程-UCOSIII空闲任务钩子函数的使用 30次下载
- UCOS扩展例程-UCOSIII移植 23次下载
- 手把手带你移植HAL库函数 1102次阅读
- C语言中的动态内存管理讲解 301次阅读
- 高速接口MIPI DPHY配置task函数 835次阅读
- 鸿蒙富设备移植指南:编译框架适配 1307次阅读
- 如何在MPLAB XC16编译器内建函数 1379次阅读
- 如何写要被C调用的汇编函数 1116次阅读
- RTL建模中的函数和任务讨论 948次阅读
- STM32F103使用(3.5)库函数新建工程 3323次阅读
- HOOK函数概述、用途和用法 1.3w次阅读
- pic单片机的各种汇编语言指令解析 2271次阅读
- 如何在c51程序中调用汇编函数 4107次阅读
- 如何把APP中固定函数移植到bootloade 1720次阅读
- 详细讲解RT-Thread I2C设备驱动框架及相关函数 2w次阅读
- C语言与汇编语言相互结合的嵌套汇编语言 3420次阅读
- 接口与类的关系_接口函数和调用函数有什么区别 9547次阅读
下载排行
本周
- 1电子电路原理第七版PDF电子教材免费下载
- 0.00 MB | 1497次下载 | 免费
- 2TC358743XBG评估板参考手册
- 1.36 MB | 330次下载 | 免费
- 3单片机典型实例介绍
- 18.19 MB | 99次下载 | 1 积分
- 4S7-200PLC编程实例详细资料
- 1.17 MB | 28次下载 | 1 积分
- 5笔记本电脑主板的元件识别和讲解说明
- 4.28 MB | 18次下载 | 4 积分
- 6开关电源原理及各功能电路详解
- 0.38 MB | 14次下载 | 免费
- 79天练会电子电路识图
- 5.91 MB | 6次下载 | 免费
- 8100W短波放大电路图
- 0.05 MB | 4次下载 | 3 积分
本月
- 1OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234313次下载 | 免费
- 2PADS 9.0 2009最新版 -下载
- 0.00 MB | 66304次下载 | 免费
- 3protel99下载protel99软件下载(中文版)
- 0.00 MB | 51209次下载 | 免费
- 4LabView 8.0 专业版下载 (3CD完整版)
- 0.00 MB | 51043次下载 | 免费
- 5555集成电路应用800例(新编版)
- 0.00 MB | 33564次下载 | 免费
- 6接口电路图大全
- 未知 | 30321次下载 | 免费
- 7Multisim 10下载Multisim 10 中文版
- 0.00 MB | 28588次下载 | 免费
- 8开关电源设计实例指南
- 未知 | 21540次下载 | 免费
总榜
- 1matlab软件下载入口
- 未知 | 935054次下载 | 免费
- 2protel99se软件下载(可英文版转中文版)
- 78.1 MB | 537794次下载 | 免费
- 3MATLAB 7.1 下载 (含软件介绍)
- 未知 | 420026次下载 | 免费
- 4OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234313次下载 | 免费
- 5Altium DXP2002下载入口
- 未知 | 233046次下载 | 免费
- 6电路仿真软件multisim 10.0免费下载
- 340992 | 191183次下载 | 免费
- 7十天学会AVR单片机与C语言视频教程 下载
- 158M | 183278次下载 | 免费
- 8proe5.0野火版下载(中文版免费下载)
- 未知 | 138039次下载 | 免费
评论
查看更多