os_cpu_a.asm
在OS_CPU_A.ASM中,定义了开、关中断的方法,在uC/OS-II系统中有三种方法可以实现中断开关,而ARM只适用于模式三,即使用一个局部变量,在中断进入之间保存CPU状态,退出时候再恢复状态。
OSStart()函数调用OSStartHighRdy()来使就绪态任务中优先级最高的任务开始运行,OSStartHighRdy()必须调用OSTaskSwHook(),调用完STaskSwHook()后,应该使OSRunning标志位为TRUE,最后再切换到最高优先级任务。此函数只是完成了高优先级任务寄存器的恢复,并没有保存当前任务的寄存器。
OSCtxSw(),任务级切换;
OSIntCtxSw(),中断级别的任务切换;
异常处理程序
********************************************************************************************************
; PUBLIC FUNCTIONS
;********************************************************************************************************
; External references
EXTERN OSRunning
EXTERN OSPrioCur
EXTERN OSPrioHighRdy
EXTERN OSTCBCur
EXTERN OSTCBHighRdy
EXTERN OSIntNesting
EXTERN OSIntExit
EXTERN OSTaskSwHook
PUBLIC OS_CPU_SR_Save
PUBLIC OS_CPU_SR_Restore
PUBLIC OSStartHighRdy
PUBLIC OSCtxSw
PUBLIC OSIntCtxSw
PUBLIC OS_CPU_ARM_ExceptResetHndlr
PUBLIC OS_CPU_ARM_ExceptUndefInstrHndlr
PUBLIC OS_CPU_ARM_ExceptSwiHndlr
PUBLIC OS_CPU_ARM_ExceptPrefetchAbortHndlr
PUBLIC OS_CPU_ARM_ExceptDataAbortHndlr
PUBLIC OS_CPU_ARM_ExceptAddrAbortHndlr
PUBLIC OS_CPU_ARM_ExceptIrqHndlr
PUBLIC OS_CPU_ARM_ExceptFiqHndlr
; EQUATES
;********************************************************************************************************
;根据CPSR的低8位设置I,F,T,及M[4:0]
OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ
OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ
OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode
OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode
OS_CPU_ARM_MODE_USR EQU 0x10 ;用户模式
OS_CPU_ARM_MODE_FIQ EQU 0x11 ;FIQ模式
OS_CPU_ARM_MODE_IRQ EQU 0x12 ;IRQ模式
OS_CPU_ARM_MODE_SVC EQU 0x13 ;管理模式
OS_CPU_ARM_MODE_ABT EQU 0x17 ;终止模式
OS_CPU_ARM_MODE_UND EQU 0x1B ;未定义模式
OS_CPU_ARM_MODE_SYS EQU 0x1F ;系统模式
OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01
OS_CPU_ARM_EXCEPT_SWI EQU 0x02
OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03
OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04
OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05
OS_CPU_ARM_EXCEPT_IRQ EQU 0x06
OS_CPU_ARM_EXCEPT_FIQ EQU 0x07
; CODE GENERATION DIRECTIVES
;********************************************************************************************************
CODE32
;*********************************************************************************************************
; CRITICAL SECTION METHOD 3 FUNCTIONS
;采用ucos所提出的模式3来禁止中断和开中断,实现硬保护
; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you
; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to
; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr'
; into the CPU's status register.
;
;也就是说cpu_sr是一个局部变量,在进入中断之前使用它来保存状态,退出时再恢复
;
; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void);
; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr);
;
;
; Note(s) : (1) These functions are used in general like this:
;
; void Task (void *p_arg)
; {
; /* Allocate storage for CPU status register. */
; #if (OS_CRITICAL_METHOD == 3)
; OS_CPU_SR os_cpu_sr;
; #endif
;
; :
; :
; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */
; :
; :
; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */
; :
; :
; }
;
; (2) OS_CPU_SR_Restore() is implemented as recommended by Atmel's application note:
;
; "Disabling Interrupts at Processor Level"
;*********************************************************************************************************
MRS R0, CPSR ;复制CPSR到R0
; Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1, R0, #OS_CPU_ARM_CONTROL_INT_DIS
;RO中存放了CPSR,把#OS_CPU_ARM_CONTROL_INT_DIS和R0进行逻辑或运算,结果存放到R1中
MSR CPSR_c, R1
;传送R1的内容到CPSR,但是只修改CPSR中的控制位域[7:0]
MRS R1, CPSR ; Confirm that CPSR contains the proper interrupt disable flags
AND R1, R1, #OS_CPU_ARM_CONTROL_INT_DIS
CMP R1, #OS_CPU_ARM_CONTROL_INT_DIS
BNE OS_CPU_SR_Save_Loop ; Not properly disabled (try again)
BX LR ; Disabled, return the original CPSR contents in R0
MSR CPSR_c, R0
BX LR
; START MULTITASKING
; void OSStartHighRdy(void)
;
; Note(s) : 1) OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;;*********************************************************************************************************
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
MOV R1, #1
STRB R1, [R0]
MOV LR, PC
BX R0
LDR R0, ?OS_TCBHighRdy ; Get highest priority task TCB address
LDR R0, [R0] ; get stack pointer
LDR SP, [R0] ; switch to the new stack
;有些代码在这里写成 LDMFD SP!,{R0}
MSR CPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC} ; pop new task's context
; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
; 任务级切换
; Note(s) : 1) OSCtxSw() is called in SYS mode with BOTH FIQ and IRQ interrupts DISABLED
;
; 2) The pseudo-code for OSCtxSw() is:
; a) Save the current task's context onto the current task's stack
; b) OSTCBCur->OSTCBStkPtr = SP;
; c) OSTaskSwHook();
; d) OSPrioCur = OSPrioHighRdy;
; e) OSTCBCur = OSTCBHighRdy;
; f) SP = OSTCBHighRdy->OSTCBStkPtr;
; g) Restore the new task's context from the new task's stack
; h) Return to new task's code
;
; 3) Upon entry:
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBCur指向即将挂起的任务,而OSTCBHighRdy指向即将恢复的任务
; OSTCBHighRdy points to the OS_TCB of the task to resume
;*********************************************************************************************************
; SAVE CURRENT TASK'S CONTEXT
STMFD SP!, {LR} ; Push return address
;LR中其实是任务切换时对应的PC值
STMFD SP!, {LR}
STMFD SP!, {R0-R12} ; Push registers
MRS R0, CPSR ; Push current CPSR
TST LR, #1 ; See if called from Thumb mode
ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, Set the T-bit
STMFD SP!, {R0}
;至此,在堆栈中保存环境的任务已经完成
LDR R0, ?OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R1, [R0]
STR SP, [R1]
MOV LR, PC
BX R0
LDR R1, ?OS_PrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R1, ?OS_TCBHighRdy
LDR R2, [R1]
STR R2, [R0]
LDMFD SP!, {R0} ; Pop new task's CPSR
MSR CPSR_cxsf, R0
; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
; 中断级的任务切换
; Note(s) : 1) OSIntCtxSw() is called in SYS mode with BOTH FIQ and IRQ interrupts DISABLED
;
; 2) The pseudo-code for OSIntCtxSw() is:
; a) OSTaskSwHook();
; b) OSPrioCur = OSPrioHighRdy;
; c) OSTCBCur = OSTCBHighRdy;
; d) SP = OSTCBHighRdy->OSTCBStkPtr;
; e) Restore the new task's context from the new task's stack
; f) Return to new task's code
;
; 3) Upon entry:
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; OSIntCtxSw()和OSCtxSw()相似,区别是OSIntCtxSw()是在ISR中被调用的,ISR已经保存了CPU的寄存器,
; 所以不需要再此保存寄存器的值
;*********************************************************************************************************
LDR R0, ?OS_TaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
LDR R1, ?OS_PrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R1, ?OS_TCBHighRdy
LDR R2, [R1]
STR R2, [R0]
LDMFD SP!, {R0} ; Pop new task's CPSR
MSR CPSR_cxsf, R0
; RESET EXCEPTION HANDLER
; 进入异常后,LR会指向下一条指令的地址,所以在压栈的时候,需要减去相应的值。
; 对于reset,svc,swi减去0,对于预取终止,irq,fiq减去4,对于数据中止和地址中止减去8
;********************************************************************************************************
; LR offset to return from this exception: 0
; (there is no way to return from a RESET exception)
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_RESET ; Set exception ID to OS_CPU_ARM_EXCEPT_RESET
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
; UNDEFINED INSTRUCTION EXCEPTION HANDLER
;********************************************************************************************************
; LR offset to return from this exception: 0
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
; SOFTWARE INTERRUPT EXCEPTION HANDLER
;********************************************************************************************************
; LR offset to return from this exception: 0
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
; PREFETCH ABORT EXCEPTION HANDLER
;********************************************************************************************************
SUB LR, LR, #4 ; LR offset to return from this exception: -4
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
; DATA ABORT EXCEPTION HANDLER
;********************************************************************************************************
SUB LR, LR, #8 ; LR offset to return from this exception: -8
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
; ADDRESS ABORT EXCEPTION HANDLER
;********************************************************************************************************
SUB LR, LR, #8 ; LR offset to return from this exception: -8
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
; INTERRUPT REQUEST EXCEPTION HANDLER
;********************************************************************************************************
SUB LR, LR, #4 ; LR offset to return from this exception: -4
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
; FAST INTERRUPT REQUEST EXCEPTION HANDLER
;********************************************************************************************************
SUB LR, LR, #4 ; LR offset to return from this exception: -4
STMFD SP!, {R0-R12, LR} ; Push working registers
MOV R3, LR ; Save link register
MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ
B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler
; GLOBAL EXCEPTION HANDLER
;********************************************************************************************************
MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR)
; SPSR.Mode = FIQ, IRQ, SVC, ABT, UND : Other exception
; SPSR.Mode = SYS : Task
; SPSR.Mode = USR : *unsupported state*
AND R2, R1, #OS_CPU_ARM_MODE_MASK ; 保留R1的低8位控制位
CMP R2, #OS_CPU_ARM_MODE_SYS
BNE OS_CPU_ARM_ExceptHndlr_BreakExcept
; EXCEPTION HANDLER: TASK INTERRUPTED
;********************************************************************************************************
MRS R2, CPSR ; Save exception's CPSR
MOV R4, SP ; Save exception's stack pointer
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
STMFD SP!, {R3} ; Push task's PC
STMFD SP!, {LR} ; Push task's LR
STMFD SP!, {R5-R12} ; Push task's R12-R5
LDMFD R4!, {R5-R9} ; Move task's R4-R0 from exception stack to task's stack
STMFD SP!, {R5-R9}
ORRNE R1, R1, #OS_CPU_ARM_CONTROL_THUMB ; If yes, Set the T-bit
STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR)
LDR R1, ?OS_Running
LDRB R1, [R1]
CMP R1, #1
BNE OS_CPU_ARM_ExceptHndlr_BreakTask_1
LDR R3, ?OS_IntNesting ; OSIntNesting++;
LDRB R4, [R3]
ADD R4, R4, #1
STRB R4, [R3]
LDR R4, [R3]
STR SP, [R4]
MSR CPSR_cxsf, R2 ; RESTORE INTERRUPTED MODE
MOV LR, PC
BX R1
; exception stack is not used when restoring task context.
ADD SP, SP, #(14*4)
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
; if a ready task with higher priority than
; the interrupted one is found.
LDR R0, ?OS_IntExit
MOV LR, PC
BX R0
LDMFD SP!, {R0} ; Pop new task's CPSR
MSR CPSR_cxsf, R0
; EXCEPTION HANDLER: EXCEPTION INTERRUPTED
;********************************************************************************************************
MRS R2, CPSR ; Save exception's CPSR
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
LDR R3, ?OS_IntNesting ; OSIntNesting++;
LDRB R4, [R3]
ADD R4, R4, #1
STRB R4, [R3]
MOV LR, PC
BX R3
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
LDR R3, ?OS_IntNesting ; OSIntNesting--;
LDRB R4, [R3]
SUB R4, R4, #1
STRB R4, [R3]
; POINTERS TO VARIABLES
;*********************************************************************************************************
DC32 OSRunning
DC32 OSPrioCur
DC32 OSPrioHighRdy
DC32 OSTCBCur
DC32 OSTCBHighRdy
DC32 OSIntNesting
DC32 OSTaskSwHook
DC32 OSIntExit
DC32 OS_CPU_ExceptHndlr
os_cpu_a.asm的更多相关文章
- ucos实时操作系统学习笔记——操作系统在STM32的移植
使用ucos实时操作系统是在上学的时候,导师科研项目中.那时候就是网上找到操作系统移植教程以及应用教程依葫芦画瓢,功能实现也就罢了,没有很深入的去研究过这个东西.后来工作了,闲来无聊就研究了一下这个只 ...
- UCOSII内核代码分析
1 UCOSII定义的关键数据结构 OS_EXT INT8U OSIntNesting; OSIntNesting用于判断当前系统是否正处于中断处理例程中. OS_EXT ...
- μC/OS-Ⅲ系统的任务切换和任务调度
一.任务切换 在操作系统中当任务需要从一个任务切换到另外一个任务时,要将当前任务的现场保存到当前任务的堆栈中(当前任务现场主要指CPU相关寄存器),然后回复新任务的现场并执行新任务.这个叫做上下文切换 ...
- STM32固件库3.5+uCOS2.86移植(转自暴走的工程师)
考了很多移植的资料和代码,终于移植好了...应该是完美移植吧~~哈哈哈~~ 编译环境是IAR 工程适用于STM32F10X大容量产品,如果不是,请自行修改启动文件和工程配置 编译器优化等级最高...这 ...
- uC/OS-II实现TEST.MAK块
################################################################################ ...
- uC/OS-II汇编代码
;*************************************************************************************************** ...
- 简单RTOS学习(一) uc/os-II 工程模板建立
随着工业需求以及单片机性能越来越高,单个芯片能够且需要处理的任务也越来越多,使用传统前后台任务模式已经很难满足设计的需求,嵌入式实时操作系统正是在这种背景下发展起来,目前流行的有rt-thread,f ...
- UCOS2_STM32F1移植详细过程(四)
Ⅰ.概述 上一篇文章是讲述uC/OS-II Ports下面os_cpu_a.asm.os_cpu_c.c和os_cpu.h文件底层端口代码的移植(修改)和说明,接着上一篇文章来讲述关于UCOS移植应用 ...
- UCOS2_STM32F1移植详细过程(三)
Ⅰ.概述 上一篇文章是讲述ST芯片相关的配置和OS裁剪相关的配置,接着上一篇文章来讲述关于UCOS的移植,该文主要针对uC/OS-II Ports下面os_cpu_a.asm.os_cpu_c.c和o ...
随机推荐
- Linux内核分析——第一章 Linux内核简介
第一章 Linux内核简介 一.Unix的历史 1.Unix系统成为一个强大.健壮和稳定的操作系统的根本原因: (1)简洁 (2)在Unix中,很多东西都被当做文件对待.这种抽象使对数据和对设备的 ...
- mosquitto集群配置
--------------------------------------------------------前言------------------------------------------ ...
- SSM 关于service和dao的封装
近期由于客户需求,所以我们整个小组开始开发java项目. 虽然很久以前也是系统学习过.不过干了这么多年 .net ,有关java的早就扔了. 好了,废话不多说.我们看看SSM 关于service和d ...
- Number Clicker CodeForces - 995E(双向bfs)
双向bfs 注意数很大 用map来存 然后各种难受....
- Day24-Ajax操作、图片验证码、KindEditor使用-转
参考源:http://blog.csdn.net/fgf00/article/details/54917439 三.Ajax操作 ajax操作基于浏览器的xmlHttpRequest对象,IE低版本是 ...
- Django_在单独文件中加载Django环境临时调试
创建Django环境后,每次在打印调试都需要基于项目有些麻烦. 如何在项目外的文件中加载项目环境进行便携的调试? 创建一个新的 orm.py import os if __name__ == '__m ...
- Python之Numpy数组拼接,组合,连接
转自:https://www.douban.com/note/518335786/?type=like ============改变数组的维度==================已知reshape函数 ...
- MT【95】由参数前系数凑配系数题2
提示:都是看$a,b$前的系数做的$a=4/3,b=2/3;a+b=\le2$,一样的可以求得$a+b$的最小值-1,当$b=\frac{1}{3},a=\frac{-4}{3}$时取到等号.此题是清 ...
- 自学huawei之路-6005-8AP设备启动界面
返回自学Huawei之路 自学huawei之路-AC6005-8AP设备启动界面 [YK-MES-MASTER] Please check whether system data has been c ...
- 51nod 1450 闯关游戏
首先肯定要先把所有的关卡打通后去找两星几率最大的关卡刷星(论打游戏经验的重要性). 所以从两星几率小的关打起,记录当前拿到x个星星的几率和当前走过的期望步数,如果发现剩下的关必须全两星,就直接计算答案 ...