UCOS-II中OS_CPU_IRQ_ISR移植過程分析
16-19、接下來的操作本應(yīng)該是完成將SP的值保存到任務(wù)堆棧空間的,但是在UC/OS-II中存在一個全局變量OSIntNesting,它表明了中斷嵌套的次數(shù),因此需要對這個值進(jìn)行一次加1操作。
21、接下來的操作就是判斷是否在中斷嵌套中,也就是對全局變量進(jìn)行比較操作,如果這個值是1,則認(rèn)為只有一個中斷產(chǎn)生,如果不等于1,則認(rèn)為實在中斷嵌套中。本文引用地址:http://2s4d.com/article/201612/324516.htm
CMP R1,#1 ;if(OSIntNesting==1){
22、BNE %F1;如果是在中斷嵌套中,則直接跳轉(zhuǎn)到下面的中斷處理函數(shù)中
23-25、
LDR R4,=OSTCBCur ;OSTCBHighRdy->OSTCBStkPtr=SP;
LDR R5,[R4]
STR SP,[R5]
說明是從任務(wù)到中斷的過程,也就是只有一個中斷產(chǎn)生,不是在中斷嵌套中,這時就需要將SP的值保存到任務(wù)控制塊中。 以上的操作也就完成了任務(wù)情景的保存操作,接下來的操作就應(yīng)該是真正的中斷處理函數(shù)啦。
27、1 MSR CPSR_c,#IRQMODE|NOINT;實質(zhì)上是完成CPU模式的切換操作,進(jìn)入到IRQ模式下。
接下來的實際處理過程就如前面兩篇文章中討論的中斷處理過程。
29-30、
LDR R0, =INTOFFSET
LDR R0, [R0]
得到INTOFFSET的值,實際上就是得到偏移量,實質(zhì)上就是中斷號產(chǎn)生中斷,通過這個寄存器可以快速的確定在二級向量表中該中斷的向量位置,該向量表中就保存了對應(yīng)中斷處理函數(shù)的函數(shù)地址。
32、LDR R1, IRQIsrVect
43、IRQIsrVect DCD HandleEINT0
這兩句說明了我前面的分析,IRQIsrVect實際上就是一個標(biāo)號,其中存儲了HandleEINT0,HandleEINT0又是我們IRQ中斷向量的入口地址(前一篇文章已經(jīng)說明),也就是說HandleEINT0是二級向量表的開始地址。因此此時R1中實際上就保存了HandleEINT0。
33、MOV LR, PC;就是完成簡單的保存過程,這個過程實質(zhì)上就是保存了函數(shù)調(diào)用的返回地址。
34、LDR PC, [R1, R0, LSL #2];這句代碼的意義是將地址R1+R0*4處的內(nèi)容加載到PC中,也就是實現(xiàn)函數(shù)的跳轉(zhuǎn),即函數(shù)的調(diào)用過程。其中R1=HandleEINT0,而R0恰好又是一個偏移量,每一個指針的空間是4個字節(jié),那么R1+R0*4地址處剛好就是對應(yīng)中斷號的向量。其中就保存了對應(yīng)中斷函數(shù)的地址。因此PC就保存了這個調(diào)用函數(shù)的入口地址。也就是實現(xiàn)了處理函數(shù)調(diào)用過程。
35、 MSR CPSR_c,#SVCMODE|NOINT; 執(zhí)行這句代碼的前提就是被調(diào)用的函數(shù)執(zhí)行完畢了,相關(guān)的入棧出棧操作也已經(jīng)完成,恢復(fù)到了調(diào)用前的狀態(tài)。此時需要將CPU的模式切換到SVC模式下。
36、BL OSIntExit ;這個操作完成了中斷的切換,如果不是在中斷嵌套中,那么最高優(yōu)先級的任務(wù)就會被執(zhí)行,進(jìn)入最高優(yōu)先的任務(wù)之后就不會再返回了,這是UC/OS-II中任務(wù)的特點,之后的代碼也就不會執(zhí)行了。這是特別需要注意的。但是如果任務(wù)處在中斷嵌套中,那么OSIntExit只是減少中斷嵌套的次數(shù),并不完成其他的操作。那么這時候就需要恢復(fù)之前被中斷的任務(wù)了,也就是需要完成任務(wù)堆棧的彈出操作。
39-41、
LDMFD SP!,{R4} ;POP the tasks CPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R0-R12,LR,PC}^
這幾句代碼的實現(xiàn)實質(zhì)上是完成了在中斷嵌套中時的任務(wù)切換操作。
討論:
不知道我理解的對不對,我認(rèn)為這段代碼存在一定的問題,具體的問題如下,因為在中斷嵌套中,CPU執(zhí)行的肯定就是中斷服務(wù)函數(shù),此時的任務(wù)處于低優(yōu)先級的,并不需要我們保存任務(wù)的信息。為什么這段代碼能夠運行的原因我認(rèn)為主要是因為這種處理的方式是不可能導(dǎo)致中斷嵌套問題產(chǎn)生的。因為我們在進(jìn)入中斷以后關(guān)閉了中斷使能位,不會產(chǎn)生中斷嵌套也就看不出問題所在。我認(rèn)為如果在支持中斷嵌套的CPU中,應(yīng)該首先檢測是否在中期嵌套中,如果在中斷嵌套中,則不需要任務(wù)寄存器的保存,如果不在,則需要保存。
關(guān)閉中斷的方式避免了中斷嵌套產(chǎn)生的可能,這也說明一直需要保存任務(wù)的情景,使得這段代碼是有效的。
總結(jié):
在討論ARM的移植過程中,我覺得首先應(yīng)該搞清楚每一種情況下CPU的工作模式,同時搞清楚寄存器的特殊性,同時搞清楚中斷處理的一般過程。
評論