nucleus 学习 中断
- ;************************************************************************
- ;*
- ;* FUNCTION
- ;*
- ;* INT_IRQ
- ;*
- ;* DESCRIPTION
- ;*
- ;* This routine is the board-specific section for
- ;* level 1 interrupt handling
- ;*
- ;* CALLED BY
- ;*
- ;* None
- ;*
- ;* CALLS
- ;*
- ;* TMT_Timer_Interrupt
- ;*
- ;* INPUTS
- ;*
- ;* None
- ;*
- ;*
- ;* OUTPUTS
- ;*
- ;* None
- ;*
- ;* HISTORY
- ;*
- ;* NAME DATE REMARKS
- ;*
- ;* B. Ronquillo 05-10-00 Created initial version 1.0
- ;*
- ;************************************************************************
- .def _INT_IRQ
- _INT_IRQ
- ; ARM Core Check //确认CPSR,这里应该是确认是否在IRQ模式下
- STMDB {r1}
- MRS r1, SPSR
- TST r1, #IRQ_BIT
- LDMIA {r1}
- SUBNES pc,lr,#4
- STMDB sp!,{r0-r4} ; Save r0-r4 on temporary IRQ stack //sp=sp-4 保存R0~R4到栈
- SUB lr,lr,#4 ; Adjust IRQ return address //lr=lr-4就是把lr下移了一格
- ;********************************
- ;* Begin Hardware Specific Code * //开始硬件特性代码?
- ;********************************
- LDR r3, INT_CNTRL_BASE_1 ; load Interrupt Control Base //装载中断控制器基地址
- LDR r4, [r3,#INT_CNTRL_MIR] ; Get enable register value //获取enable register的值,INT_CNTRL_MIR的值
- ;******************************
- ;* End Hardware Specific Code *
- ;******************************
- STMDB sp!,{r4} ; Put the enable register value on the IRQ stack //把r4压入栈,r4是enable register的值
- MVN r4,#0 ; Start with 0xFFFFFFFF to allow nesting of interrupts //全部置1
- ;********************************
- ;* Begin Hardware Specific Code *
- ;********************************
- LDR r2, [r3,#INT_CNTRL_ITR] ; Read Pending reg //这次读取了INT_CNTRL_ITR的值
- ;******************************
- ;* End Hardware Specific Code *
- ;******************************
- LDR r3, IRQ_Priority ; Get the Priority table address //获取IRQ优先级表的地址
- IRQ_VECTOR_LOOP
- LDR r0, [r3,#0] ; Load first vector to be checked from priority table
- MOV r1, #1 ; Build mask
- MOV r1, r1, LSL r0 ; Use vector number to set mask to correct bit position //逻辑左移优先级个数,不会溢出吗
- TST r1, r2 ; Test if pending bit is set //判断
- BNE IRQ_VECTOR_FOUND ; If bit is set, branch to found section... //找到IRQ_VECTOR
- BIC r4,r4,r1 ; Clear mask bit to keep higher priority ints active //如果没找到查下一个向量表?
- ADD r3, r3, #4 ; Move to next word in the priority table
- ADR r0, Priority_End ; Load the end address for the priority table
- CMP r0, r3 ; Make sure not at the end of the table (shouldn't happen!)
- BNE IRQ_VECTOR_LOOP ; Continue to loop if not at the end of the table
; No bits in pending register set, restore registers and exit interrupt servicing //恢复上下文
ADD sp,sp,#4 ; Adjust sp above IRQ enable value
LDMIA sp!,{r0-r4} ; Restore r0-r4
STMDB sp!,{lr} ; Put return address for IRQ on stack
LDMIA sp!,{pc}^ ; return to the point of the exception and restore SPSR
IRQ_VECTOR_FOUND
;********************************
;* Begin Hardware Specific Code *
;********************************
LDR r3, INT_CNTRL_BASE_1 ; load Interrupt Control Base //获取INT_CNTRL_BASE
MVN r2, r1 ; Get the inverse of the interrupt vector //之前r1和r2应该是一样的,取了反
STR r2, [r3,#INT_CNTRL_ITR] ; Write a zero to the interrupt being handled //写一个0到中断处理中
LDR r2, [r3,#INT_CNTRL_MIR] ; Read the Mask reg
ORR r4, r2, r4 ; Turn off lower priority pending bits and currently masked bits
STR r4, [r3,#INT_CNTRL_MIR] ; Disable(Mask) all lower priority interrupts and currently masked interrupts
MOV r1, #1 ; Clear the pending interrupt //清除pending中断位
STR r1, [r3,#INT_CNTRL_CONTROL_REG] ; by writing a 1 to the Control Reg //写入1清除
;******************************
;* End Hardware Specific Code *
;******************************
LDR r3, IRQ_Vectors ; Get IRQ vector table address
MOV r2, r0, LSL #2 ; Multiply vector by 4 to get offset into table
ADD r3, r3, r2 ; Adjust vector table address to correct offset
LDR r2, [r3,#0] ; Load branch address from vector table
MOV PC, r2 ; Jump to correct branch location based on vector table //跳转到中断向量表,这个跳转应该是找到对应的处理程序?
; END: INT_IRQ
中断向量表:
- ; Define vector table used by INT_IRQ to branch to necessary ISR
- INT_IRQ_Vectors:
- .word _INT_IRQ_2 ; Vector 0
- .word INT_Interrupt_Shell ; Vector 1
- .word INT_Interrupt_Shell ; Vector 2
- .word INT_Interrupt_Shell ; Vector 3
- .word INT_Interrupt_Shell ; Vector 4
- .word INT_Interrupt_Shell ; Vector 5
- .word INT_Interrupt_Shell ; Vector 6
- .word INT_Interrupt_Shell ; Vector 7
- .word INT_Interrupt_Shell ; Vector 8
- .word INT_Interrupt_Shell ; Vector 9
- .word INT_Interrupt_Shell ; Vector 10
- .word INT_Interrupt_Shell ; Vector 11
- .word INT_Interrupt_Shell ; Vector 12
- .word INT_Interrupt_Shell ; Vector 13
- .word INT_Interrupt_Shell ; Vector 14
- .word INT_Interrupt_Shell ; Vector 15
- .word INT_Interrupt_Shell ; Vector 16
- .word INT_Interrupt_Shell ; Vector 17
- .word INT_Interrupt_Shell ; Vector 18
- .word INT_Interrupt_Shell ; Vector 19
- .word INT_Interrupt_Shell ; Vector 20
- .word INT_Interrupt_Shell ; Vector 21
- .word INT_Interrupt_Shell ; Vector 22
- .word INT_Interrupt_Shell ; Vector 23
- .word INT_Interrupt_Shell ; Vector 24
- .word INT_Interrupt_Shell ; Vector 25
- .word INT_Interrupt_Shell ; Vector 26
- .word INT_Interrupt_Shell ; Vector 27
- .word INT_Interrupt_Shell ; Vector 28
- .word INT_Interrupt_Shell ; Vector 29
- .word INT_Timer_Interrupt ; Vector 30
- .word INT_Interrupt_Shell ; Vector 31
- 。。。。。。。。。。。。。。。
INT_Interruopt_Shell(感觉只是跳转到_TCT_Interrupt_Context_Save):
- ;************************************************************************
- ;*
- ;* FUNCTION
- ;*
- ;* INT_Interrupt_Shell
- ;*
- ;* DESCRIPTION
- ;*
- ;* Handles all interrupts which use NU_Register_LISR.
- ;*
- ;*
- ;* CALLED BY
- ;*
- ;* INT_IRQ
- ;*
- ;* CALLS
- ;*
- ;* TCT_Dispatch_LISR
- ;* TCT_Interrupt_Context_Restore
- ;*
- ;* INPUTS
- ;*
- ;* vector (register r0)
- ;*
- ;* OUTPUTS
- ;*
- ;* None
- ;************************************************************************
- .def INT_Interrupt_Shell
- INT_Interrupt_Shell
- MOV r4,lr ; Put IRQ return address into r4 //这里r4是PC的值
- BL _TCT_Interrupt_Context_Save //什么直接跳转了?
- BL _TCC_Dispatch_LISR //怎么两个跳转?LISR?
- MRS r1,CPSR ; Pickup current CPSR //清除了中断,关了位
- BIC r1,r1,#MODE_MASK ; Clear the mode bits
- ORR r1,r1,#(IRQ_MODE_OR_LOCKOUT) ; Set the IRQ mode bits and Lockout interrupts
- MSR CPSR,r1 ; Lockout interrupts/change to IRQ mode
- ;********************************
- ;* Begin Hardware Specific Code *
- ;********************************
- LDMIA sp!,{r1} ; Get IRQ enable value off IRQ stack //提取栈中的值到sp
- LDR r2, INT_CNTRL_BASE_1 ; Get IRQ0 base register address //获取IRQ0基地址
- STR r1,[r2,#INT_CNTRL_MIR] ; Re-enable all lower priority interrupts //重新开启低优先级中断
- ;******************************
- ;* End Hardware Specific Code *
- ;******************************
- MRS r1,CPSR ; Pickup current CPSR
- BIC r1,r1,#MODE_MASK ; Clear the mode bits
- ORR r1,r1,#SUP_MODE ; Set the SVC mode bits
- MSR CPSR,r1 ; Change to SVC mode //切换成svc模式
- B _TCT_Interrupt_Context_Restore
既然跳转到_TCT_Interrupt_Context_Save那就继续学习吧:
- ;************************************************************************
- ;*
- ;* FUNCTION
- ;*
- ;* TCT_Interrupt_Context_Save
- ;*
- ;* DESCRIPTION
- ;*
- ;* This function saves the interrupted thread's context. Nested
- ;* interrupts are also supported. If a task or HISR thread was
- ;* interrupted, the stack pointer is switched to the system stack
- ;* after the context is saved.
- ;*
- ;* CALLED BY
- ;*
- ;* Application ISRs Assembly language ISRs
- ;* INT_Interrupt_Shell Interrupt handler shell
- ;*
- ;* CALLS
- ;*
- ;* None
- ;*
- ;* INPUTS
- ;*
- ;* vector Interrupt's vector number
- ;*
- ;* OUTPUTS
- ;*
- ;* None
- ;*
- ;* HISTORY
- ;*
- ;* NAME DATE REMARKS
- ;*
- ;* W. Lamie 02-15-1994 Created initial version 1.0
- ;* D. Lamie 02-15-1994 Verified version 1.0
- ;* D. Driscoll 01-04-2002 Released version 1.13.3.
- ;* Updated to handle nested /
- ;* prioritized IRQs
- ;************************************************************************
- ;VOID TCT_Interrupt_Context_Save(INT vector)
- ;{
- .def $TCT_Interrupt_Context_Save
- $TCT_Interrupt_Context_Save ; Dual-state interworking veneer
- .state16
- BX r15
- NOP
- .state32
- B _TCT_Interrupt_Context_Save
- .def _TCT_Interrupt_Context_Save
- _TCT_Interrupt_Context_Save
- ; Determine if this is a nested interrupt. //确定是不是嵌套中断
- LDR r1,Int_Count ; Pickup address of interrupt count //Int_Count是中断计数
- LDR r2,[r1, #0] ; Pickup interrupt counter
- ADD r2,r2,#1 ; Add 1 to interrupt counter
- STR r2,[r1, #0] ; Store new interrupt counter value //更新中断计数
- CMP r2,#1 ; Is it nested?
- BEQ TCT_Not_Nested_Save ; No //如果不是嵌套就跳转
- ; Nested interrupt. Save complete context on the current stack.
- TCT_Nested_Save
- ; 1. Save another register on the exception stack so we have enough to work with //保存另一个寄存器(r5)到异常栈,腾出空间来。r13是sp指针
- STMDB r13!,{r5}
- ; 2. Save the necessary exception registers into r1-r3 //保存必要的异常寄存器到r1-r3
- MOV r1,r13 ; Put the exception r13 into r1
- MOV r2,r14 ; Move the return address for the caller
- ; of this function into r2
- MRS r3,spsr ; Put the exception spsr into r3
- ; 3. Adjust the exception stack pointer for future exceptions //调整异常栈指针为之后的异常
- ADD r13,r13,#24 ; r13 will point to enable reg value when done
- ; 4. Switch CPU modes to save context on system stack //转换CPU模式到system stack(之前初始化过的)
- MRS r5,CPSR ; Pickup the current CPSR
- BIC r5,r5,#MODE_MASK ; Clear the mode bits
- ORR r5,r5,#SUP_MODE ; Change to supervisor mode (SVD)
- MSR CPSR,r5 ; Switch modes (IRQ->SVC)
- ; 5. Store the SVC r13 into r5 so the r13 can be saved as is. //这里明明是把r5放进r13(sp)
- MOV r5,r13
- ; 6. Save the exception return address on the stack (r15). //保存r4进栈
- STMDB r5!,{r4}
- ; 7. Save r6-r14 on stack //保存r6-r14进栈
- STMDB r5!,{r6-r14}
- ; 8. Switch back to using r13 now that the original r13 has been saved. //又把r13换回来了,回到sp回到原来的位置了
- MOV r13,r5
- ; 9. Get r5 and exception enable registers off of exception stack and //
- ; save r5 (stored in r4) back to the system stack. //保存r5(存在r4中)到system stack中,好吧之前的mov都理解错了,mov 目的,源
- LDMIA r1!,{r4-r5}
- STMDB r13!,{r4}
- MOV r4,r5 ; Put exception enable value into r4
- ; 10. Get the rest of the registers off the exception stack and //获取剩下的exception stack到system stack中
- ; save them onto the system stack.
- LDMIA r1!,{r5-r8,r11} ; Get r0-r4 off exception stack
- STMDB r13!,{r5-r8,r11} ; Put r0-r4 on system stack
- ; 11. Store the exception enable value back on the exception stack.
- STMDB r1,{r4}
- ; 12. Save the SPSR on the system stack (CPSR)
- STMDB r13!,{r3}
- ; 13. Re-enable interrupts //重新开启中断
- MRS r1,CPSR
- BIC r1,r1,#(IRQ_BIT_OR_FIQ_BIT)
- MSR CPSR,r1
- BX r2 ; Return to calling ISR
- ; }
- ; else
- ; {
- TCT_Not_Nested_Save
- ; Determine if a thread was interrupted. //判断是否进程产生了中断
- ; if (TCD_Current_Thread) //如果TCD_Current_Thread是空,则在schedule中因为初始化线程是关中断的
- ; {
- LDR r1,Current_Thread ; Pickup current thread ptr address
- LDR r1,[r1, #0] ; Pickup the current thread pointer
- CMP r1,#0 ; Is it NU_NULL?
- BEQ TCT_Idle_Context_Save ; If no, no real save is necessary
- ; Yes, a thread was interrupted. Save complete context on the
- ; thread's stack.
- ; 1. Save another register on the exception stack so we have enough to work with
- STMDB r13!,{r5}
- ; 2. Save the necessary exception registers into r1-r3
- MOV r1,r13 ; Put the exception r13 into r1
- MOV r2,r14 ; Move the return address for the caller
- ; of this function into r2
- MRS r3,spsr ; Put the exception spsr into r3
- ; 3. Adjust the exception stack pointer for future exceptions
- ADD r13,r13,#24 ; r13 will point to enable reg value when done
- ; 4. Switch CPU modes to save context on system stack
- MRS r5,CPSR ; Pickup the current CPSR
- BIC r5,r5,#MODE_MASK ; Clear the mode bits
- ORR r5,r5,#SUP_MODE ; Change to supervisor mode (SVD)
- MSR CPSR,r5 ; Switch modes (IRQ->SVC)
- ; 5. Store the SVC r13 into r5 so the r13 can be saved as is.
- MOV r5,r13
- ; 6. Save the exception return address on the stack (r15).
- STMDB r5!,{r4}
- ; 7. Save r6-r14 on stack
- STMDB r5!,{r6-r14}
- ; 8. Switch back to using r13 now that the original r13 has been saved.
- MOV r13,r5
- ; 9. Get r5 and exception enable registers off of exception stack and
- ; save r5 (stored in r4) back to the system stack.
- LDMIA r1!,{r4-r5}
- STMDB r13!,{r4}
- MOV r4,r5 ; Put exception enable value into r4
- ; 10. Get the rest of the registers off the exception stack and
- ; save them onto the system stack.
- LDMIA r1!,{r5-r8,r11} ; Get r0-r4 off exception stack
- STMDB r13!,{r5-r8,r11} ; Put r0-r4 on system stack
- ; 11. Store the exception enable value back on the exception stack.
- STMDB r1,{r4}
- ; 12. Save the SPSR on the system stack (CPSR)
- STMDB r13!,{r3}
- ; 13. Save stack type to the task stack (1=interrupt stack)
- MOV r1,#1 ; Interrupt stack type
- STMDB r13!,{r1}
- ; Save the thread's stack pointer in the control block.
- ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread
- ; REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr
- LDR r1,Current_Thread ; Pickup current thread ptr address
- LDR r3,[r1, #0] ; Pickup current thread pointer
- STR r13,[r3, #TC_STACK_POINTER] ; Save stack pointer
- ; Switch to the system stack.
- ; REG_Stack_Ptr = TCD_System_Stack
- LDR r1,System_Stack ; Pickup address of stack pointer
- LDR r3,System_Limit ; Pickup address of stack limit ptr
- LDR r13,[r1, #0] ; Switch to system stack
- LDR r10,[r3, #0] ; Setup system stack limit
- ; Re-enable interrupts
- MRS r1,CPSR
- BIC r1,r1,#(IRQ_BIT_OR_FIQ_BIT)
- MSR CPSR,r1
- ; Return to caller ISR.
- BX r2 ; Return to caller ISR
- ; }
- TCT_Idle_Context_Save
- MOV r2,r14 ; Save r14 in r2
- LDR r3,[r13] ; Get exception enable value from stack
- ADD r13,r13,#20 ; Adjust exception r13 for future interrupts
- STR r3,[r13] ; Put exception enable value back on stack
- MRS r1,CPSR ; Pickup current CPSR
- BIC r1,r1,#MODE_MASK ; Clear the current mode
- BIC r1,r1,#(IRQ_BIT_OR_FIQ_BIT) ; Re-enable interrupts
- ORR r1,r1,#SUP_MODE ; Prepare to switch to supervisor
- ; mode (SVC)
- MSR CPSR,r1 ; Switch to supervisor mode (SVC)
- BX r2 ; Return to caller ISR
- ; }
- ;}
nucleus 学习 中断的更多相关文章
- nucleus学习
task的TCB结构: typedef struct TC_TCB_STRUCT { /* Standard thread information first. This information is ...
- 【转载-Andrew_qian】stm32中断学习
[转载]stm32中断学习 中断对于开发嵌入式系统来讲的地位绝对是毋庸置疑的,在C51单片机时代,一共只有5个中断,其中2个外部中断,2个定时/计数器中断和一个串口中断,但是在STM32中,中断数量大 ...
- Linux快速学习系列
这篇文章会随着学习的进行,不断的更新!!! 总结 操作系统引入的抽象概念 进程(process) 地址空间(address space) 虚拟内存(virtual memory) 操作系统引入的cah ...
- Nucleus 实时操作系统中断(下)
Nucleus 实时操作系统中断(下) Nucleus RTOS兼容性 由于中断在Nucleus SE中的实现方式与Nucleus rto截然不同,因此不应期望有特定的兼容性.Nucleus RTOS ...
- JUC源码学习笔记3——AQS等待队列和CyclicBarrier,BlockingQueue
一丶Condition 1.概述 任何一个java对象都拥有一组定义在Object中的监视器方法--wait(),wait(long timeout),notify(),和notifyAll()方法, ...
- 20169212《Linux内核原理与分析》第六周作业
视频学习 一.用户态.内核态和中断 内核态:处于高的执行级别下,代码可以执行特权指令,访问任意的物理地址,这时的CPU就对应内核态 用户态:处于低的执行级别下,代码只能在级别允许的特定范围内活动.在日 ...
- system v和posix的共享内存对比 & 共享内存位置
参考 http://www.startos.com/linux/tips/2011012822078.html 1)Linux和所有的UNIX操作系统都允许通过共享内存在应用程序之间共享存储空间. 2 ...
- Protection 5 ---- Priviliege Level Checking 2
CPU不仅仅在程序访问数据段和堆栈段的时候进行权限级别检查,当程序控制权转换的时候也会进行权限级别检查.程序控制权转换的情况很多,各种情况下检查的方式以及涉及到的检查项都是不同的.这篇文章主要描述了各 ...
- MVC5系列——布局视图
MVC5系列——布局视图 目录 系列文章 概述 布局视图 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5系列——添加 ...
随机推荐
- 各大漏洞平台及SRC的区别和如何批量刷漏洞
批量刷漏洞: 01刷指纹->02刷原始漏洞->03刷CMS->04刷指定政府.教育->05刷众测平台->06刷SRC->07刷国内外.活动 搜索引擎: 百度.goo ...
- php sqrt()函数 语法
php sqrt()函数 语法 作用:sqrt()函数的作用是对参数进行求平方根 语法:sqrt(X) 参数: 参数 描述 X 进行求平方根的数字 说明:返回将参数X进行开平方后的结果江苏大理石平台 ...
- Android中实现Activity的启动拦截之----实现360卫士的安装应用界面
第一.摘要 今天不是周末,但是我已经放假了,所以就开始我们的技术探索之旅,今天我们来讲一下Android中最期待的技术,就是拦截Activity的启动,其实我在去年的时候,就像实现这个技术了,但是因为 ...
- php基于SQLite实现的分页功能示例
php基于SQLite实现的分页功能. 这里操作数据库文件使用的是前面文章<PHP基于PDO实现的SQLite操作类>中的SQLite数据库操作类. 代码: <?php class ...
- loadrunner(预测系统行为和性能的负载测试工具)
LoadRunner,是一种预测系统行为和性能的负载测试工具.通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够对整个企业架构进行测试.企业使用LoadRu ...
- vue项目打包之后原本好的样式变得不好了的原因分析
这个主要是打包的过程将所有的css文件进行归类压缩,导致原先其他文件里的样式对当前的产生了影响,应该有同样的类名了.怎么改?要么改类名,要么用scope,scss的写法.
- 原生 js 实现 vue 的某些功能
1.数据双向绑定:https://www.cnblogs.com/yuqing-o605/p/6790709.html?utm_source=itdadao&utm_medium=referr ...
- vue数据渲染、条件判断及列表循环
1.数据渲染 {{msg}} <template> <div id="app"> {{msg}} </div> </template&g ...
- MongoDB(7):集群部署实践,包含复制集,分片
注: 刚开始学习MongoDB,写的有点麻烦了,网上教程都是很少的代码就完成了集群的部署, 纯属个人实践,错误之处望指正!有好的建议和资料请联系我QQ:1176479642 集群架构: 2mongos ...
- Linux 下 VIM 的操作
其实VI 和vim本质上没有多大区别,,但是VIM 可以高亮关键字,使得更受青睐 vim里面有3种模式:命令模式,编辑模式,末行模式 1. vim--->:set number VIM 打开文档 ...