資料介紹
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移植笔记12次下载
- UCOSIII学习笔记(二)任务管理、Hook函数、中断4次下载
- 亲测有效的UCOSIII嵌入STM32F103C8T6实验,介绍常见移植问题,付实测代码!!!25次下载
- STM32f4—ucosiii移植代码工程21次下载
- uCOSIII系统移植(二)构建多任务1次下载
- Oracle数据库-plsql-基础、函数讲解12次下载
- Oracle中常用的函数与表达式讲解2次下载
- EE-128:C++中的DSP:从C++调用汇编类成员函数2次下载
- 如何使用DSP汇编语言实现高精度的三角函数7次下载
- UCOS移植过程全讲解教程免费下载21次下载
- 单片机C函数中的嵌入汇编之形参传递详细资料说明1次下载
- CC1101与MSP430接口库移植到STM32的详细资料说明19次下载
- ucosIII移植教程94次下载
- UCOS扩展例程-UCOSIII空闲任务钩子函数的使用31次下载
- UCOS扩展例程-UCOSIII移植23次下载
- 详解RTOS中的Hook函数421次阅读
- 关联接口函数与libmodbus移植1273次阅读
- RTOS中钩子函数的用途及用法807次阅读
- 手把手带你移植HAL库函数3458次阅读
- C语言中的动态内存管理讲解649次阅读
- 高速接口MIPI DPHY配置task函数1276次阅读
- 如何在MPLAB XC16编译器内建函数2141次阅读
- 如何写要被C调用的汇编函数1669次阅读
- RTL建模中的函数和任务讨论1482次阅读
- HOOK函数概述、用途和用法14967次阅读
- 如何在c51程序中调用汇编函数4549次阅读
- 如何把APP中固定函数移植到bootloade2007次阅读
- 详细讲解RT-Thread I2C设备驱动框架及相关函数21276次阅读
- C语言与汇编语言相互结合的嵌套汇编语言3775次阅读
- 接口与类的关系_接口函数和调用函数有什么区别9864次阅读
下載排行
本周
- 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次下載 | 免費
評論