ARM Cortex-M3中断跳转过程
在學習CM3的時候,仔細學習了CM3的中斷跳轉過程,發現嵌入式的MCU在這一塊基本上是一樣的,當然不同架構的MCU也有自己的特性。
我來介紹下CM3的中斷跳轉過程,首先假設中斷發生,CM3內核開始響應中斷,由于不同廠家的CM3可能略有區別,但CM3的內核肯定是一樣的,所以我們在這個前提下開始討論,暫時把中斷屏蔽位,標志位之類的東西放在一邊。
現在介紹中斷響應的過程:
1、壓棧。從這一點來講幾乎所有的處理器都是一樣的,用壓棧保護現場。壓入哪些寄存器呢,又是怎樣一個順序?如果就大多數的C語音編程來講,這個不是很關心的內容。但是CM3的壓棧寄存器特點,讓我們來見識下ARM設計的特點。其壓棧順序如下圖所示,請注意壓棧的地址順序和時間順序不是相同的。
| 地址(SP) | 寄存器 | 被保護順序(時間順序) |
| N-0 | 之前已壓棧內容 | ? |
| N-4 | xPSR | 2 |
| N-8 | PC | 1 |
| N-12 | LR | 8 |
| N-16 | R12 | 7 |
| N-20 | R3 | 6 |
| N-24 | R2 | 5 |
| N-28 | R1 | 4 |
| N-32 | R0 | 3 |
這一點就我們普通coding來講,是非常奇特的,堆棧的空間順利和進棧時間沒有必然聯系,跟我們“后進先出”的觀點有很大出入,那么顯然這里的“堆棧”,并不是我們傳統意義的上的堆棧,具體怎樣實現ARM沒有詳述,只是說他們可以做到這點。
我們可以看到PC,xPSR,R0,R1,R2,R3是率先入棧的(時間上),這樣做的目的,是為了編譯器優先使用入棧了的寄存器來保存中間結果(如果程序過大也可能要用到R4-R11,此時編譯器負責生成代碼來push它們)。這也是要求ISR盡量短小的原因,用更少的寄存器,以加快響應。
2、查找中斷向量表。其實這一步跟第一步是并行的,只是為了分別介紹我,列了序號。ARM是有D-Code(數據總線)和I-Code(指令總線),兩條總線。可以看到PC是第一個壓棧的,此時數據總線正忙于壓棧操作,與此同時指令總線就可以查找中斷向量表,查詢中斷服務程序的入口地址。在CM3中中斷向量表位于地址從0x00000000開始的一段存儲空間,每個表項占一個字(4byte)。這是中斷向量表沒有重定位的情況,當然中斷向量表也可以重定位,即存儲在其他地方。這個需要設置相應的寄存器,我個人認為還是讓其固定在這個默認的位置比較好,以免出現以外情況。在看中斷向量表的時候我遇到了一個很有意思的問題:
中斷服務函數的入口地址為0x67C(圖1所示),但是中斷向量表中存儲的地址確是0x67D(圖2所示),竟然加了1。
?? ?這讓我糾結了很久,后來一位整ARM7的大牛解答了我的問題。ARM的PC最低位是0的時候ARM會進入ARM模式,但是最低位是1的時候會進入thumb模式。而我們的CM只支持thumb模式,所以PC最低位必須為1。而且thumb指令集是16位的,所以0x67D就是指向0x67C所存儲的指令,但是減一就不行了,就變成了指令空間內上一個地址存儲的指令。
?????????把CM3中斷跳轉過程寫出來跟大家分享,若有不妥之處,望大家斧正。
圖1 方框內為所對應中斷服務函數入口地
圖2 方框內為中斷向量表中中斷服務函數入口地址
***************************************************************************
記得在DSP TMS32F2812中,中斷向量的初始化是由一段地址拷貝代碼完成的,在STM32(Cortex-M3)中沒有顯示的代碼拷貝,只有啟動代碼進行了向量的初始化,一直以為是編譯器在程序影像中自己完成了相關向量的拷貝,即,拷貝到固定的NVIC區,事實上并不是這樣,cortex-m3并沒有一塊專門用于存放NVIC向量表的地方,這張表實際是存放在代碼(程序映像)的開始,下面引用cortex-M3權威指南進行解釋:
??? 當發生了異常并且要響應它時,CM3需要定位其服務例程的入口地址。這些入口地址存儲在所謂的“(異常)向量表”中。缺省情況下,CM3認為該表位于零地址處,且各向量占用4字節。因此每個表項占用4字節,如表7.6所示。
??因為地址0處應該存儲引導代碼,所以它通常映射到Flash或者是ROM器件,并且它們的值不得在運行時改變。然而,為了支持動態重分發中斷,CM3允許向量表重定位——從其它地址處開始定位各異常向量。這些地址對應的區域可以是代碼區,但更多是在RAM區。在RAM區就可以修改向量的入口地址了。為了實現這個功能,NVIC中有一個寄存器,稱為“向量表偏移量寄存器”(在地址0xE000_ED08處),通過修改它的值就能重定位向量表。但必須注意的是:向量表的起始地址是有要求的:必須先求出系統中共有多少個向量,再把這個數字向上“圓整”到2的整次冪,而起始地址必須對齊到后者的邊界上。例如,如果一共有32個中斷,則共有32+16(系統異常)=48個向量,向上圓整到2的整次冪后值為64,因此向量表重定位的地址必須能被64*4=256整除,從而合法的起始地址可以是:0x0, 0x100, 0x200等。向量表偏移量寄存器的定義如表7.7所示。
如果需要動態地更改向量表,則對于任何器件來說,向量表的起始處都必須包含以下向量:
? 主堆棧指針(MSP)的初始值
? 復位向量
? NMI
? 硬fault服務例程
后兩者也是必需的,因為有可能在引導過程中發生這兩種異常。
可以在SRAM中開出一塊空間用于存儲向量表。在引導期間先填寫好各向量,然后在引導完成后,就可以啟用內存中的新向量表,從而實現向量可動態調整的能力。
總結
以上是生活随笔為你收集整理的ARM Cortex-M3中断跳转过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软中断与硬中断
- 下一篇: Cortex_m3的启动过程