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 ...
随机推荐
- Notes of Daily Scrum Meeting(12.19)
今天工作进展的速度别昨天稍有提高,希望大家再接再厉!加油! 团队任务总结如下: 团队成员 今日团队工作 陈少杰 重新尝试使用get等方法进行网络连接的调试 王迪 调试搜索功能中测出的问题 金鑫 测试已 ...
- Linux内核分析(第二周)
操作系统是如何工作的? 一.总结:三大法宝 1.存储程序计算机 + 函数调用堆栈 + 中断机制 2.堆栈:C语言程序运行时候必须的一个记录调用路径和参数的空间(函数调用框架/提供局部变量/传递参数/保 ...
- 第二个Spring冲刺周期团队进展报告
第一天:找识别不了的原因 第二天:继续找识别不了的原因 第三天:找文字库,找到tessdata语言包,放到手机SD卡根目录 第四天:了解OCR引擎 第五天:将导入tess-two导入到项目中,并进行测 ...
- c++ 读写功能
课程作业三 git链接: Operations 感想 这次代码修改的地方主要有,加入了文件读写.读出功能,以及分离函数写到了头文件里. 但是也有很多不足的地方,首先本来想要 ...
- 课程回顾5in1
提出过的问题 问题1:敏捷开发在现阶段急于使用或试行,会不会得到相反的结果? 整个开发流程在施行了一整个学期,有积极的影响,也有消极的影响.例如通过这个流程的实施,规划短期的项目进度,使得成员能逐步了 ...
- Linux命令(二十三) 磁盘管理命令(一) df,du,tune2fs
一. 查看磁盘占用空间情况 df df 命令用于查看硬盘空间的使用情况,还可以查看硬盘分区的类型或 inode 节点的使用情况等. df 命令常用参数如下: -a 显示所有文件系统的磁盘使用情况,包括 ...
- php 的优缺点
1.优点:开源 免费性 快捷性 [程序开发快,运行快,技术本身学习快] 插件丰富,网上的解决方案有很多,而且还有庞大的开源社区可以提供帮助. 跨平台性强 效率高 图像处理 面向对象 [在php4 ...
- linux 文件夹操作
一.操作命令 1.创建文件夹 : mkdir 2.创建文件 : touch.vi 3.删除文件/文件夹:rm 删除文件夹的时候使用 -r可以循环删除子目录 4.移动文件/文件夹:mv 移动文件夹,使用 ...
- 3.23日PSP
工作 类型 日期 开始时间 结束时间 中断时间 净时间 搭hadoop环境(已终止) 技能 3.23 00:00 00:50 0min 50min 看构建之法 学习 3.23 9:30 10:00 3 ...
- 08.基于IDEA+Spring+Maven搭建测试项目--Maven的配置文件settings.xml
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://mav ...