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内核分析第三次实验
http://blog.sina.com.cn/s/blog_78e559950102wo67.html
- 《Linux内核分析》第四周:扒开系统调用的三层皮
杨舒雯 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 " 一. 用户 ...
- 冲刺Two之站立会议3
今天继续昨天的工作,对主界面进行设计优化,并成功将各个按钮和对应的功能模块连接了起来.并对服务器部分进行了部分改进,包括登录界面的美观性和服务器数据库部分的处理.
- C#ToString() 格式化数值
格式字符串采用以下形式:Axx,其中 A 为格式说明符,指定格式化类型,xx 为精度说明符,控制格式化输出的有效位数或小数位数. 格式说明符 说明 示例 输出 C 货币 2.5.ToString(&q ...
- Docker(六)-Dcoker仓库
仓库 一个容易混淆的概念是注册服务器(Registry). 实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像.从这方面来说, 仓库可以被认为是一个具体的项目 ...
- CF 1070J Streets and Avenues in Berhattan
DP的数组f其实开得不够大,应该开200000,但是它在cf上就是过了... 题意是把一堆字母分别分配到行和列. 分析一下,答案实际上只和n行中和m列中每种字母分配的个数有关.而且答案只和" ...
- Minimum Sum LCM UVA - 10791(分解质因子)
对于一个数n 设它有两个不是互质的因子a和b 即lcm(a,b) = n 且gcd为a和b的最大公约数 则n = a/gcd * b: 因为a/gcd 与 b 的最大公约数也是n 且 a/gcd ...
- Swap HDU - 2819 (有关矩阵的二分匹配)
题意见大佬:https://www.cnblogs.com/gj-Acit/archive/2013/08/17/3265502.html 题目大意很明确,交换图的某些行或者是某些列(可以都换),使得 ...
- 【BZOJ1093】[ZJOI2007]最大半联通子图(Tarjan,动态规划)
[BZOJ1093][ZJOI2007]最大半联通子图(Tarjan,动态规划) 题面 BZOJ 洛谷 洛谷的讨论里面有一个好看得多的题面 题解 显然强连通分量对于题目是没有任何影响的,直接缩点就好了 ...
- C++时间标准库时间time
转自:http://www.cnblogs.com/yukaizhao/archive/2011/04/29/cpp_time_system_time.html (玉开) C++标准库中的时间需要引用 ...