dsPIC33C系列的中斷向量表(IVT)位于程序存儲(chǔ)器中,起始單元地址是0x000004h(0x000000~0x000002是復(fù)位入口地址)。IVT包含6個(gè)不可屏蔽陷阱向量和最多246個(gè)中斷源。一般來(lái)說(shuō),每個(gè)中斷源都有自己的中斷向量。每個(gè)中斷向量都包含一個(gè)24位寬的地址。每個(gè)中斷向量單元中編程的值是其相關(guān)的中斷服務(wù)程序(ISR)的起始地址。如下圖所示。
6個(gè)不可屏蔽中斷向量表,它們的CPU優(yōu)先級(jí)不可設(shè)置,優(yōu)先級(jí)分別為9-15。
中斷向量根據(jù)其自然優(yōu)先級(jí)區(qū)分優(yōu)先順序(在沒(méi)有分配優(yōu)先級(jí)的情況下,優(yōu)先級(jí)0-7可設(shè)置),自然優(yōu)先級(jí)與中斷向量在向量表中的位置有關(guān)。一般來(lái)說(shuō),較低地址的中斷向量具有較高的自然優(yōu)先級(jí)。例如在下列向量表中,與向量編號(hào)為8(外部中斷0)相關(guān)的中斷比其他向量地址的中斷具有更高的自然優(yōu)先級(jí)。
中斷向量表的重映射
dsPIC33C共有256個(gè)中斷源,每一個(gè)中斷源對(duì)應(yīng)一個(gè)中斷向量地址,且每個(gè)中斷向量地址是固定不能改變的。通常,我們?cè)贐ootLoader中不使用中斷,只在應(yīng)用程序中使用中斷功能。當(dāng)禁用CodeGuard時(shí),大多數(shù)dsPIC33器件只有一個(gè)IVT表。對(duì)于具有單個(gè)IVT表的MCU ,需要在中斷向量表中設(shè)置跳轉(zhuǎn)偏移量(也就是重映射,在應(yīng)用程序空間中復(fù)制IVT表),讓中斷產(chǎn)生后能跳轉(zhuǎn)到應(yīng)用程序中。
在用戶應(yīng)用程序空間中的固定地址處創(chuàng)建預(yù)定義的應(yīng)用程序中斷重映射表。該表中的每個(gè)條目都包含一個(gè)GOTO指令,該指令跳至該中斷的實(shí)際應(yīng)用程序中斷服務(wù)程序(ISR)。發(fā)生中斷時(shí),這些中斷將自動(dòng)跳到中斷處理函數(shù)。
下面是中斷的流程以及它在應(yīng)用程序中斷服務(wù)程序中的結(jié)束方式
(1)發(fā)生UART1中斷;
(2)PC指針跳轉(zhuǎn)到硬件中斷向量表中指定的地址(此處地址假設(shè)為0x4000),這是應(yīng)用程序中斷重映射表中的固定位置;
(3)應(yīng)用程序中斷重映射有一個(gè)指向?qū)嶋H應(yīng)用程序中斷服務(wù)程序函數(shù)的GOTO指令。
上述中斷跳轉(zhuǎn)的方法有一定缺點(diǎn),就程序存儲(chǔ)空間而言,其成本可能更高。每個(gè)中斷在dsPIC33器件上需要2條指令(6個(gè)字節(jié),GOTO占兩個(gè)指令)。在dsPIC33C器件上有256個(gè)中斷。如果每個(gè)中斷都需要跳轉(zhuǎn),則可能需要超過(guò)1KB的內(nèi)存。此外,大多數(shù)應(yīng)用程序代碼僅使用幾個(gè)中斷源,在這種情況下,應(yīng)用程序中斷重映射表中未使用的中斷入口只是浪費(fèi)空間。
一種“壓縮”或“減小”此表大小的方法是確定將在此設(shè)計(jì)產(chǎn)品系列中使用或可能使用哪些中斷。然后僅在“應(yīng)用程序中斷重映射表”中創(chuàng)建入口,并將這些入口放置在“應(yīng)用程序中斷重映射表”的開(kāi)頭開(kāi)始的連續(xù)位置。有了此應(yīng)用程序可以支持的中斷“列表”,Bootloader就可以獲取該列表,并針對(duì)識(shí)別出的中斷,使用簡(jiǎn)化的應(yīng)用程序中斷重映射表中相應(yīng)入口的地址在IVT中編程其中斷。此外,對(duì)于未使用的中斷,我們可以在應(yīng)用程序空間中創(chuàng)建一個(gè)“默認(rèn)中斷服務(wù)程序”,并在應(yīng)用程序中斷重映射表中創(chuàng)建一個(gè)入口,同時(shí)為默認(rèn)值創(chuàng)建一個(gè)ISR。這將通過(guò)默認(rèn)的中斷服務(wù)程序?qū)⑺衅渌袛嗵D(zhuǎn)到應(yīng)用程序。這樣,如果應(yīng)用程序稍后決定需要一個(gè)以前不需要的新中斷,則它仍然可以通過(guò)重新映射的默認(rèn)處理程序訪問(wèn)該中斷。
選擇哪些中斷跳轉(zhuǎn)到它們自己的ISR,哪些跳轉(zhuǎn)到默認(rèn)ISR可能是一項(xiàng)困難的任務(wù),因?yàn)锽ootloader可能不知道哪些中斷正在使用或可以使用。此外,由于產(chǎn)品的生命周期以年為單位,產(chǎn)品功能可能會(huì)隨著時(shí)間而改變。 因此,如果閃存空間不是主要考慮因素,那么即使應(yīng)用程序的外設(shè)具有獨(dú)立ISR的可能性很小,Bootloaer區(qū)也應(yīng)將其跳轉(zhuǎn)給獨(dú)立的ISR,只有當(dāng)外設(shè)在項(xiàng)目開(kāi)發(fā)中完全確定不會(huì)使用,或者不需要使用中斷,或者可以使用默認(rèn)的ISR中斷時(shí),才將外設(shè)跳轉(zhuǎn)到默認(rèn)的ISR。
使用上述方法,最終中斷跳轉(zhuǎn)方案如下所示。 在此示例中,應(yīng)用程序僅需要兩個(gè)專用的ISR(例如UART1和SPI1)。 因此,這兩個(gè)外設(shè)中的每一個(gè)在應(yīng)用程序中斷重映射表中都有一個(gè)專用入口,而應(yīng)用程序中斷重映射表中的其他入口都采用默認(rèn)中斷ISR。 所有可以共享一個(gè)公共ISR的“未使用的”或外設(shè),其IVT入口都指向應(yīng)用程序中斷重新映射表中的這個(gè)入口,這也是重新映射表中的第一個(gè)地址。 通過(guò)使用默認(rèn)的中斷入口,可以大大減小應(yīng)用程序中斷重映射表的大小。
在上面的示例中,應(yīng)用程序未使用外設(shè)A,B和C,但是將它們的中斷轉(zhuǎn)發(fā)給應(yīng)用程序默認(rèn)處理程序,以防萬(wàn)一以后需要它們時(shí)使用。
在boot區(qū)需要中斷的情況下,IVT不必將該中斷跳轉(zhuǎn)至應(yīng)用程序(注意:在具有備用中斷表的設(shè)備-AIVT上,這不是必需的)。 在這種情況下,Bootloader將使用來(lái)自IVT的中斷。 在下面的示例中,比如Bootloader需要在中斷模式下使用UART2。 在這種情況下,IVT不會(huì)將中斷轉(zhuǎn)發(fā)給應(yīng)用程序,而是決定將中斷保留在Bootloader。