nucleus 学习 中断
来源:互联网 发布:网络教育专科报名 编辑:程序博客网 时间:2024/05/22 04:33
- ;************************************************************************
- ;*
- ;* 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
- 。。。。。。。。。。。。。。。
- ;************************************************************************
- ;*
- ;* 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
- ;************************************************************************
- ;*
- ;* 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
- ; }
- ;}
NU对于中断上下文的保存具体操作如下:
(1)在中断发生后执行的入口函数INT_IRQ()中,将r0-r4保存至irq的栈中
(2)查找到对应的interrupt_shell(),clear中断源,更新全局的中断计数器,然后进行interrupt_contex_save
(3)首先利用r1,r2,r3保存irq模式下的sp,lr,spsr,这里sp是用来切换至系统栈后拷贝lr和spsr的,这里保存lr和spsr是目的是task被抢占后,当再次schedule时可以返回task之前的状态。
(4)切换至SVC模式,如果是非嵌套的中断则保存上下文至task stack中,将irq模式下的lr作为顶端PC的返回值入栈,将SVC模式下的r6-r14入栈,将irq模式下的sp保存至r4中入栈,最后将保存在irq_stack中的r0-r4入栈
(5)如果是嵌套中断,中断的嵌套发生在LISR中,在执行LISR时已经切换至system stack,因此嵌套中断要将中断的上下文保存至system stack中,与task stack中interrupt stack相比只是少了栈顶用来标记嵌套的标志(1 not nested)
(6)有一个分支判断,就是如果当前线程是空,即TCD_Current_Thread == NULL,表明当前是schedule中,因为初始化线程是关中断的,这样就不为schedule线程建立栈帧,因为schedule不需要保存上下文,在restore中断上下文时直接跳转至schedule。
中断上下文的恢复
全局的中断计数器INT_Count是否为0来判定当前出栈的信息,如果是嵌套则返回LISR中,否则切换至system stack执行schedule
0
上一篇:nucleus plus学习总结
下一篇:nucleus plus学习总结(后续)
相关热门文章
- SHTML是什么_SSI有什么用...
- 查看linux中某个端口(port)...
- 卡尔曼滤波的原理说明...
- shell中字符串操作
- 关于java中的“错误:找不到或...
给主人留下些什么吧!~~
评论热议
阅读全文
0 0
- nucleus 学习 中断
- Nucleus学习
- nucleus学习
- Nucleus中断处理过程!!!!
- Nucleus中断处理过程!!!!
- nucleus plus代码学习
- nucleus plus学习总结
- Nucleus
- nucleus plus(Hisr,lisr学习)
- nucleus plus学习总结(后续)
- Nucleus Task切换及中断之上下文保存
- Nucleus PLUS的启动、运行线程和中断处理
- Nucleus PLUS的启动、运行线程和中断处理
- Nucleus PLUS的启动、运行线程和中断处理
- Nucleus系统源码分析与学习
- Nucleus的中断分为管理的和非管理的中断
- 中断学习
- 中断学习
- 最常用的1000个Java类(附代码示例)
- sed编辑器基础
- nucleus plus代码学习
- nucleus学习
- nucleus plus学习总结
- nucleus 学习 中断
- 解决html表格字体
- nucleus plus学习总结(后续)
- 光衰代码整理学习
- 5-32 哥尼斯堡的“七桥问题”(并查集+度的判断)
- C# 串口总结
- STM32的结构和启动模式
- GIS二次开发牛人博客
- 电源控制和备份区域
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
凝血因子Ⅷ很高怎么办
怀孕一个月上火了怎么办
38周了还没入盆怎么办
妊娠33周血压高怎么办
孕34周突然流血怎么办
达英35漏服一天怎么办
华法林忘记2天吃怎么办
肾移植后感冒了怎么办
香水按压器坏了怎么办
香水的喷嘴坏了怎么办
抗凝血酶偏高144怎么办
抗凝血酶iii偏低怎么办
蛋白c蛋白s低怎么办
小狗吃了死老鼠怎么办
狗吃了活老鼠怎么办
两个月婴儿枕秃怎么办
观赏虾生小虾了怎么办
达比加群出血怎么办
腹透病人感冒了怎么办
瓷砖被草酸咬了怎么办
吃了毒鼠钠盐人怎么办
吃了药血压还高怎么办
吃减肥药有抗体了怎么办
孩子一咳嗽就喘怎么办
饥荒被毒蛇咬了怎么办
w10玩联盟fps低怎么办
怀孕白球比低怎么办
白球比1.5,要怎么办
未满月发烧38度怎么办
β2微球蛋白偏高怎么办
白鞋橡胶变黄怎么办
新布鞋前面挤脚怎么办
白鞋已经刷黄了怎么办
新鞋两侧挤脚怎么办
新空调有塑料味怎么办
车门胶条嘎吱响怎么办
手机用久了很卡怎么办
睫毛胶过敏肿了怎么办
肌酐尿酸都偏高怎么办
肌酐400太高该怎么办
尿素和肌酐偏高怎么办