野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 49451|回复: 156

[ucos] UCOSIII移植中的汇编接口函数讲解:OS_CPU_PendSVHandler加OS_CPU_PendSVHandler

  [复制链接]
发表于 2016-10-8 14:22:08 | 显示全部楼层 |阅读模式
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) 使能中断,任务开始运行.
;********************************************************************************************************


  1. ;********************************************************************************************************
  2. ;                                         开始多任务
  3. ;                                      void OSStartHighRdy(void)
  4. ;
  5. ; 注意 :    1) 这个函数触发了一个PendSV异常,导致第一个任务开始运行.
  6. ;
  7. ;           2) OSStartHighRdy() 必须:
  8. ;              a) 设置PendSV的优先级为最低;
  9. ;              b) 初始化进程堆栈指针PSP等于0, 表明这是第一次上下文切换;
  10. ;              c) 设置主堆栈指针等于OS_CPU_ExceptStkBase
  11. ;              d) 触发PendSV异常;
  12. ;              e) 使能中断,任务开始运行.
  13. ;********************************************************************************************************

  14. OSStartHighRdy
  15.     ; 设置PendSV中断优先级
  16.                 LDR     R0, =NVIC_SYSPRI14                                 
  17.     LDR     R1, =NVIC_PENDSV_PRI
  18.     STRB    R1, [R0]                   ;*R0=R1(低字节),因为表达优先级只需要8bit

  19.     ; 初始化PSP=0
  20.                 MOVS    R0, #0                     ; 把0加载到R0                                             
  21.     MSR     PSP, R0                    ; 把R0的值加载到特殊寄存器PSP

  22.     ; 初始化MSP地址
  23.                 LDR     R0, =OS_CPU_ExceptStkBase  ; 把OS_CPU_ExceptStkBase这个指针变量的地址加载到R0                          
  24.     LDR     R1, [R0]                   ; *R0 = R1,实际上就是把OS_CPU_ExceptStkBase的值加载到R1
  25.     MSR     MSP, R1                    ; 把R1的值加载到MSP,此时MSP=OS_CPU_ExceptStkBase
  26.    
  27.     ; 触发PendSV异常 (进入上下文切换)
  28.     LDR     R0, =NVIC_INT_CTRL                                 
  29.     LDR     R1, =NVIC_PENDSVSET
  30.     STR     R1, [R0]                   ; *R0 = R1      
  31.    
  32.     ; 打开中断
  33.                 CPSIE   I                                                   

  34. ; 正常情况下,永远不会运行到这,因为这是一个死循环
  35. OSStartHang
  36.     B       OSStartHang
复制代码


1:PendSV 异常服务函数 void OS_CPU_PendSVHandler(void)

  1. OS_CPU_PendSVHandler
  2.     CPSID   I                                                          ; 关中断,执行上下文切换的时候不能被中断,属于临界段
  3.     MRS     R0, PSP                                                ; 加载PSP(即R13)的值到R0
  4.     CBZ     R0, OS_CPU_PendSVHandler_nosave     ; R0的值为0则跳转到OS_CPU_PendSVHandler_nosave; CBZ:比较,如果结果为0就跳转
  5.                                                                            ; 第一次进行上下文切换的时候PSP等于0,所以要进行跳转
  6.                                                                                                                                                                                                                                                                
  7.     SUBS    R0, R0, #0x20                                     ; 压栈之前先调整堆栈指针,要压栈的寄存器R4-R11有8个,所以偏移为8*0x04=0x20
  8.     STM     R0, {R4-R11}                                       ; 手动将R4-R11压栈

  9.     ; 实现 OSTCBCurPtr->OSTCBStkPtr = SP;
  10.     LDR     R1, =OSTCBCurPtr                              ; R1=&OSTCBCurPtr,这个时候R1里面存的是OSTCBCurPtr这个指针变量的地址               
  11.     LDR     R1, [R1]                                             ; R1=*R1=OSTCBCurPtr,这个时候,R1等于OSTCBCurPtr这个指针变量
  12.     STR     R0, [R1]                                             ; *R1=R0,这个时候OSTCBCurPtr指向的TCB的第一个成员(即OSTCBCurPtr->OSTCBStkPtr)等于R0
  13.                                                                         ; R0又是一开始进行压栈的PSP,所以OSTCBCurPtr->OSTCBStkPtr = SP
  14.                                                                         ; 程序运行到这个点上,进入上下文切换的过程已经保存好了
  15. OS_CPU_PendSVHandler_nosave
  16.     PUSH    {R14}                                               ; 保存 LR exc_return 的值
  17.     LDR     R0, =OSTaskSwHook                         ; 调用OSTaskSwHook()
  18.     BLX     R0
  19.     POP     {R14}

  20.     ; 实现 OSPrioCur = OSPrioHighRdy;
  21.     LDR     R0, =OSPrioCur                                ; R0=&OSPrioCur                                
  22.     LDR     R1, =OSPrioHighRdy                         ; R1=&OSPrioHighRdy
  23.     LDRB    R2, [R1]                                         ; R2=*R1(低字节),因为优先级是8bit的,所以是低字节
  24.     STRB    R2, [R0]                                          ; R0=*R2(低字节),因为优先级是8bit的,所以是低字节

  25.     ; 实现 OSTCBCurPtr = OSTCBHighRdyPtr;
  26.                 LDR     R0, =OSTCBCurPtr                ; R0=&OSTCBCurPtr                                 
  27.     LDR     R1, =OSTCBHighRdyPtr                     ; R1=&OSTCBHighRdyPtr
  28.     LDR     R2, [R1]                                           ; R2=*R1
  29.     STR     R2, [R0]                                           ; R0=*R2

  30.     LDR     R0, [R2]                                          ; R0等于新的进程的SP; SP = OSTCBHighRdyPtr->StkPtr
  31.                                                                       ; R2=OSTCBHighRdyPtr,则[R2]=*R2=OSTCBHighRdyPtr=StkPtr,因为TCB的第一个成员就是StkPtr
  32.     LDM     R0, {R4-R11}                                  ; 从新的堆栈中弹出R4-R11
  33.     ADDS    R0, R0, #0x20                                ; 重新调整堆栈指针,R4-R11为8个寄存器,每个寄存器为四个字节,8*4=32=0X20
  34.     MSR     PSP, R0                                          ; 更新PSP的值
  35.     ORR     LR, LR, #0x04                                ; 判断LR寄存器的位4是否为1,确保异常返回用用的是PSP
  36.     CPSIE   I                                                    ; 打开中断,上下文切换结束
  37.     BX      LR                                                   ; 异常返回

  38.     END                                                          ; 汇编程序结束
复制代码








回复

使用道具 举报

 楼主| 发表于 2016-10-8 14:23:00 | 显示全部楼层
; 只有在特权级下,才可以访问下面三个寄存器
; 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,      ;开异常
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-10-8 14:24:33 | 显示全部楼层
MOVS:把一个立即数存储到寄存器中
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-10-8 14:25:30 | 显示全部楼层
LDR作为伪指令
LDR:加载一个立即数或者一个地址值到一个寄存器

举例:
LDR Rd, = label
如果label是立即数,那Rd等于立即数
如果label是一个标识符,比如指针,那存到Rd的就是label这个标识符的地址
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-10-8 14:26:32 | 显示全部楼层
LDR作为ARM指令
1.png
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-9-2 14:25:14 | 显示全部楼层
MRS 与 MSR 的用法记忆
这两个ARM指令都是用来数据传输的,传输的方向都是从右往左,R 对应普通的寄存器,S对应特殊寄存器

MRS    【R】普通的寄存器    【S】特殊寄存器           ; 方向为从右到左
MSR    【S】特殊寄存器       【R】普通的寄存器        ; 方向为从右到左
回复 支持 反对

使用道具 举报

发表于 2016-10-8 15:30:33 | 显示全部楼层
学习了,感谢
回复 支持 反对

使用道具 举报

发表于 2016-10-8 16:13:34 | 显示全部楼层
暂时还学不到,先收藏。
回复 支持 反对

使用道具 举报

发表于 2016-10-9 08:30:16 | 显示全部楼层
学习学习下
回复 支持 反对

使用道具 举报

发表于 2016-10-9 16:15:41 | 显示全部楼层
来支持一下
回复 支持 反对

使用道具 举报

发表于 2016-10-9 20:05:39 | 显示全部楼层
关注下,最近学习 UCOS3
回复 支持 反对

使用道具 举报

发表于 2016-10-11 12:39:07 | 显示全部楼层
每日来火逼论坛,水一炮
回复 支持 反对

使用道具 举报

发表于 2016-10-12 09:20:54 | 显示全部楼层
仔细学习一下
回复 支持 反对

使用道具 举报

发表于 2016-10-19 23:29:20 | 显示全部楼层
先mar下.。。。。。。
回复

使用道具 举报

发表于 2016-10-20 09:40:26 | 显示全部楼层
这个必须要看看
回复 支持 反对

使用道具 举报

发表于 2016-10-26 06:10:31 | 显示全部楼层
好高端,希望学习一下。
回复 支持 反对

使用道具 举报

发表于 2016-10-27 22:35:10 | 显示全部楼层
学习,学习,学习
回复 支持 反对

使用道具 举报

发表于 2016-10-29 19:26:10 | 显示全部楼层
最近正在学这个
回复 支持 反对

使用道具 举报

发表于 2016-11-6 23:00:15 | 显示全部楼层
学习啦!!谢谢!!
回复 支持 反对

使用道具 举报

发表于 2016-11-6 23:31:46 | 显示全部楼层
最近一直在学习UCOSIII,入门系统必备
回复 支持 反对

使用道具 举报

发表于 2016-11-7 13:22:18 | 显示全部楼层
good 很好的学习文章
回复 支持 反对

使用道具 举报

发表于 2016-11-13 22:02:40 | 显示全部楼层
项目需要,所以现在要移植ucos
回复 支持 反对

使用道具 举报

发表于 2016-11-14 08:46:49 | 显示全部楼层
求学,想看全部内容好好学习学习

回复 支持 反对

使用道具 举报

发表于 2016-11-15 21:20:16 | 显示全部楼层
求解决移植时程序卡在OS_CPU_PendSV_Handler  PROC
                EXPORT  OS_CPU_PendSV_Handler             [WEAK]
                B       .
回复 支持 2 反对 0

使用道具 举报

发表于 2016-11-17 12:28:31 | 显示全部楼层
学习了,感谢
回复 支持 反对

使用道具 举报

发表于 2016-11-17 17:08:03 | 显示全部楼层
火哥的程序是很值得学习的,我都是学着火哥的程序成长的
回复 支持 反对

使用道具 举报

发表于 2016-11-17 22:09:31 | 显示全部楼层
固件库,xiexie
回复 支持 反对

使用道具 举报

发表于 2016-11-20 23:18:12 | 显示全部楼层
学学................谢谢啦
回复 支持 反对

使用道具 举报

发表于 2016-11-21 07:11:45 | 显示全部楼层
UCOSIII移植中的汇编接口函数讲解:OS_CPU_PendSVHandler加OS_CPU_PendSVHandler
回复 支持 反对

使用道具 举报

发表于 2016-11-22 16:48:31 | 显示全部楼层
看一哈子咯              
回复 支持 反对

使用道具 举报

发表于 2017-1-13 08:01:19 | 显示全部楼层
来学习了!!!
回复

使用道具 举报

发表于 2017-2-4 22:08:35 | 显示全部楼层
UCOSIII移植中的汇编接口函数讲解:OS_CPU_PendSVHandler加OS_CPU_PendSVHandler
回复 支持 反对

使用道具 举报

发表于 2017-2-14 09:14:13 | 显示全部楼层
正好学uC/OS,看看
回复 支持 反对

使用道具 举报

发表于 2017-2-14 16:35:04 | 显示全部楼层
           
回复 支持 反对

使用道具 举报

发表于 2017-2-16 13:41:20 | 显示全部楼层
                                                      
回复 支持 反对

使用道具 举报

发表于 2017-2-18 15:05:06 | 显示全部楼层
谢谢                                       
回复 支持 反对

使用道具 举报

发表于 2017-2-25 10:49:42 | 显示全部楼层
感谢分享干货,不过回帖才可看太麻烦了....
回复 支持 反对

使用道具 举报

发表于 2017-2-27 19:58:26 | 显示全部楼层
void OSStartHighRdy
回复 支持 反对

使用道具 举报

发表于 2017-3-3 11:21:09 | 显示全部楼层
学习了,mark
回复 支持 反对

使用道具 举报

发表于 2017-3-13 17:07:41 | 显示全部楼层
学习一下
回复

使用道具 举报

发表于 2017-3-22 23:32:01 | 显示全部楼层
MARKMARKMARKMARKMARKMARKMARK
回复 支持 反对

使用道具 举报

发表于 2017-4-25 10:09:50 | 显示全部楼层
学习一下,我这里到进入死循环了
回复 支持 反对

使用道具 举报

发表于 2017-4-28 13:53:39 | 显示全部楼层
支持火哥!!!!!!!!!!!!!
回复

使用道具 举报

发表于 2017-5-1 10:01:49 | 显示全部楼层
回复

使用道具 举报

发表于 2017-5-8 20:42:25 | 显示全部楼层
感谢分享!
回复

使用道具 举报

发表于 2017-5-8 21:15:54 | 显示全部楼层
学习。。                              
回复 支持 反对

使用道具 举报

发表于 2017-5-17 23:44:33 | 显示全部楼层
谢谢分享                                         
回复 支持 反对

使用道具 举报

发表于 2017-6-13 13:53:11 | 显示全部楼层
666666666666666666666666666
回复 支持 反对

使用道具 举报

发表于 2017-6-15 09:12:47 | 显示全部楼层
6666666666666
回复 支持 反对

使用道具 举报

发表于 2017-6-20 08:50:58 | 显示全部楼层
来看看,学习下!
回复 支持 反对

使用道具 举报

发表于 2017-7-8 21:30:45 | 显示全部楼层
学习一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-21 22:42 , Processed in 0.089446 second(s), 33 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表