正文
3.中斷Interrupts
中斷提供了應(yīng)用程序與現(xiàn)實世界中發(fā)生的事情之間的接口。例如,你可以使用中斷來捕捉被按下的按鈕,來標記時間的流逝或捕捉一些其他事件。
當中斷發(fā)生時,處理器通常會查看內(nèi)存中一個稱為向量(Vector)的預定義位置。一個向量通常包含相關(guān)的中斷處理程序的地址。包含應(yīng)用程序中所有向量的內(nèi)存塊稱為中斷向量表。
3.1單級和多級平臺 Single-Level and Multi-Level Platforms
目標處理器根據(jù)所支持的中斷優(yōu)先級的數(shù)量進行分類。我們應(yīng)該理解目標硬件上的中斷機制。
有兩種不同類型的目標平臺:
單級平臺Single-level:在單級平臺上,有一個單一的中斷優(yōu)先級。如果正在處理中斷,所有其他掛起的中斷必須等待當前處理完成。
多級平臺Multi-level:在多級平臺上,有多個中斷級別。如果正在處理一個中斷,那么它可以被任何具有更高優(yōu)先級的中斷所搶占。也被稱為嵌套的中斷模型。
3.2 中斷服務(wù)例程Interrupt Service Routines
AUTOSAR操作系統(tǒng)使用中斷服務(wù)路程(ISRs)捕獲中斷。ISR與任務(wù)相似;然而,ISRs的不同之處在于:
?ISR不能被RTA-OS API調(diào)用激活。
?ISR不能調(diào)用TerminateTask()和ChainTask() API。
?ISR從相關(guān)中斷優(yōu)先級的入口點開始執(zhí)行。
?只能在ISR中使用部分RTA-OS API。
3.3 一類和二類中斷Category 1 and Category 2 Interrupts
AUTOSAR操作系統(tǒng)將中斷分為兩類,稱為1類和2類中斷。類別指示操作系統(tǒng)是否參與處理中斷。
3.3.1一類中斷Category 1 Interrupts
第一類中斷不與RTA-OS交互。它們應(yīng)該始終是應(yīng)用程序中優(yōu)先級最高的中斷。正確配置硬件、編寫中斷處理程序并從中斷中返回取決于用戶。
處理程序在RTA-OS的優(yōu)先級級別或更高級別執(zhí)行。但是,我們可以調(diào)用RTA-OS API來啟用/禁用中斷和恢復/掛起中斷。
3.3.2二類中斷Category 2 Interrupts
對于第2類中斷,中斷向量指向內(nèi)部RTA-OS代碼。當中斷被觸發(fā)時,RTA-OS執(zhí)行內(nèi)部代碼,然后調(diào)用用戶提供的處理程序。
這個處理程序是作為一個綁定到中斷的ISR提供的(可以認為這是一個非常高優(yōu)先級的任務(wù))。從ISR的指定入口點開始執(zhí)行,一直持續(xù)到入口函數(shù)返回。當入口函數(shù)返回時,RTA-OS執(zhí)行另一小段內(nèi)部代碼,然后從中斷返回。
圖3.1 二類中斷處理狀態(tài)圖
圖3.2 可視化RTA-OS第2類包裝器(Wrappers)
3.4 中斷優(yōu)先級Interrupt Priorities
中斷在中斷優(yōu)先級級別(IPL)上執(zhí)行。RTA-OS對所有目標微控制器的IPL進行標準化,IPL 0表示用戶級別,所有任務(wù)執(zhí)行,1或以上的IPL表示中斷級別。重要的是,不要混淆IPL與任務(wù)優(yōu)先級。如果IPL為1,則會高于應(yīng)用程序中使用的最高任務(wù)優(yōu)先級。
IPL是對目標硬件上的中斷優(yōu)先級的與處理器無關(guān)的描述。
在一個單級平臺上,有兩個ipl,0和1。IPL 0表示目標沒有中斷,任務(wù)按優(yōu)先級順序運行。IPL 1表示目標正在為中斷提供服務(wù)。由于只有一個非零的IPL,所有的中斷,包括第1類和第2類,都以相同的優(yōu)先級運行。這意味著所有的中斷都是序列化的。
在多級平臺上,較高優(yōu)先級的中斷可以優(yōu)先于較低優(yōu)先級的中斷,因此,可以嵌套ISR處理程序。因此,例如,較高優(yōu)先級ISR可以中斷低優(yōu)先級ISR的執(zhí)行。但是,ISR永遠不能被任務(wù)搶占。
第一類ISR不能被第二類ISR中斷。這是因為2類ISR有可能激活一個任務(wù),因此操作系統(tǒng)需要在離開ISR時檢查上下文切換——這就是操作系統(tǒng)在圖3.2所示的“包裝器Wrappers”函數(shù)的第二部分所做的事情。由于ISR可以在多級平臺上嵌套,因此必須在每個中斷退出時進行此檢查。現(xiàn)在,如果第1類ISR可以被第2類ISR搶占,那么在退出第1類ISR時,不會檢查上下文切換,并且最初被搶占的任務(wù)將恢復,而不是激活的高優(yōu)先級任務(wù)。這是優(yōu)先級反轉(zhuǎn),可能在系統(tǒng)中導致未知的副作用。
此問題意味著所有第2類ISR必須具有不高于最低優(yōu)先級的第1類ISR的IPL。RTA-OS在生成時自動檢查它,如果是這種情況,將會產(chǎn)生一個錯誤。
單級平臺和多級平臺的中斷優(yōu)先級層次結(jié)構(gòu)如圖3.3所示。
圖3.3 中斷優(yōu)先級層次結(jié)構(gòu)
3.4.1 用戶級User Level
用戶級別是允許處理所有中斷的最低中斷優(yōu)先級級別。所有任務(wù)都從其入口點開始在用戶級別上執(zhí)行。
一個任務(wù)有時需要在用戶級別以上運行,例如,它可能需要訪問與ISR共享的數(shù)據(jù)。在訪問數(shù)據(jù)時,它必須防止中斷被提供服務(wù)。最簡單的方法是讓該任務(wù)在訪問數(shù)據(jù)時禁用中斷。一種機制是使用AUTOSAR操作系統(tǒng)的資源機制。
即使任務(wù)的優(yōu)先級高于用戶級別的中斷,ISR也可以優(yōu)先執(zhí)行任務(wù)。但是,只有ISR的中斷優(yōu)先級高于當前的優(yōu)先級,它才能做到這一點。
圖3.4 配置中斷
3.4.2 操作系統(tǒng)級別OS Level
最高優(yōu)先級類別2 ISR的優(yōu)先級定義了操作系統(tǒng)級別。如果執(zhí)行發(fā)生在操作系統(tǒng)級別或更高級別,則不會發(fā)生其他第2類中斷。
RTA-OS使用OS級別來防止對內(nèi)部OS數(shù)據(jù)結(jié)構(gòu)的并發(fā)訪問。任何操縱操作系統(tǒng)內(nèi)部狀態(tài)的RTA-OS API都將在操作系統(tǒng)級別執(zhí)行部分(如果不是全部)執(zhí)行時間。操作系統(tǒng)鉤子(例如Error鉤子,PreTask和PostTaskHook)和操作系統(tǒng)回調(diào)也在操作系統(tǒng)級別運行。如果任務(wù)在操作系統(tǒng)級別執(zhí)行,則不會發(fā)生RTA-OS操作(除了任務(wù)進行的調(diào)用)。
3.5 中斷配置Interrupt Configuration
在RTA-OS中,中斷使用rtaoscfg進行靜態(tài)配置。圖3.4顯示了一個中斷是如何被構(gòu)造出來的。
在最簡單的級別上,一個中斷具有以下屬性:
中斷名字:該名稱用于引用實現(xiàn)中斷處理程序功能的C代碼。
中斷類別:如果處理程序不需要執(zhí)行RTA-OS API調(diào)用,則這是第1類,否則是第2類。
中斷優(yōu)先級:調(diào)度程序使用優(yōu)先級來確定中斷何時運行(類似于任務(wù)使用的任務(wù)優(yōu)先級)。優(yōu)先級是微控制器特定的參數(shù),因此在設(shè)置優(yōu)先級之前必須選擇RTA-OS目標。請注意,有些目標只支持單個中斷優(yōu)先級。
中斷向量:RTA-OS使用指定的向量為中斷生成向量表條目(也就是中斷在MCU中的地址)。與中斷優(yōu)先級一樣,中斷向量配置是微控制器特有的,因此在配置中斷向量之前必須選擇一個目標。
注意: 在IPL是用戶可編程的微控制器上,集成者應(yīng)該確保內(nèi)部中斷設(shè)備的編程優(yōu)先級與RTA-OS配置的級別相匹配。由于此配置必須在操作系統(tǒng)啟動之前進行,因此RTA-OS無法完成此操作,因為可能需要執(zhí)行1類ISR。RTA-OS可能能夠生成適當?shù)呐渲脭?shù)據(jù)供使用。集成者需要查閱目標/編譯器端口指南以獲得具體說明。
集成指導:RTA-OS GUI允許選擇不同的目標(例如,允許快速遷移一個操作系統(tǒng)配置到一個新的微控制器)。當更改目標時,將刪除所有特定于目標的配置,包括中斷優(yōu)先級和中斷向量設(shè)置。因此,需要酌情提供新的目標設(shè)置。
3.5.1 中斷向量表產(chǎn)生Vector Table Generation
在大多數(shù)情況下,RTA-OS可以自動生成向量表。rtaosgen將創(chuàng)建一個向量表,其中正確的向量指向內(nèi)部包裝器(Wrappers)代碼,并將其放在生成的庫中。
如果您想編寫自己的向量表,那么您必須確保RTA-OS不會生成向量表。您可以通過禁用向量表生成(Target ? Disable Vector Table Generation)來防止生成向量表,如圖3.5所示。
當自定義的編寫向量表時,需要確保所有與第2類ISRs分支相關(guān)聯(lián)的中斷向量到RTA-OS中斷包裝器,該包裝器設(shè)置ISR執(zhí)行的上下文。
注意:不能直接編寫中斷處理程序。這樣做將繞過RTA-OS,并且您試圖在處理程序的上下文中與內(nèi)核進行的任何交互都很可能導致內(nèi)核狀態(tài)的不可恢復的損壞。
通常,自己編寫的向量表需要滿足如下形式的標簽:Os_Wrapper_VECTOR,其中vector是向量的十六進制地址。然而,確切的細節(jié)是具體硬件平臺特定的。應(yīng)該查閱目標/編譯器端口指南,以獲得如何提供自己的向量表的具體細節(jié)。
圖3.5 防止RTA-OS自動生成向量表
3.6 實現(xiàn)中斷處理程序Implementing Interrupt Handlers
3.6.1 1類中斷處理程序Category 1 Interrupt Handlers
編寫第1類ISR的格式是不可移植的。微控制器的編譯器通常定義一個特定于ANSI C的編譯器擴展,允許將函數(shù)標記為中斷。然而,有些編譯器不能做到這一點。當這種情況發(fā)生時,需要編寫一個匯編語言處理程序。
確保第1類ISR入口函數(shù)的名稱與您在配置過程中為該ISR指定的名稱相同。
對于第1類ISR,通常必須使用一個特定于編譯器的關(guān)鍵字(有時稱為實用碼函數(shù)或指令)。RTA-OS提供了一個名為CAT1_ISR的宏,它可以擴展為編譯器工具鏈的正確指令,使用它來將函數(shù)標記為第1類ISR。
CAT1_ISR(Interrupt1) { /* Handler body. */ /* Return from interrupt. */ }
Example 3.1: Entry Function for a Category 1 ISR
3.6.2 第2類中斷處理程序Category 2 Interrupt Handlers
2類中斷是在RTA-OS的控制下處理的。一個2類ISR類似于一個任務(wù)。它有一個入口函數(shù),當中斷處理程序需要運行時,由RTA-OS調(diào)用。2類中斷處理程序是使用示例3.2中的C語法編寫的。
#includeISR(isr_identifier){ /* Handler body. */ }
Example 3.2: Entry Function for a Category 2 ISR
不需要為第2類ISR入口函數(shù)提供任何C函數(shù)原型。這些在rtaosgen生成的Os.h頭文件中提供。
注意:不能在類別2 ISR中放置“從中斷返回”命令。從中斷返回-由RTA-OS處理。
3.6.3 清除中斷Dismissing Interrupts
當硬件檢測到一個中斷時,它通常會設(shè)置一個掛起位,告訴中斷控制器已經(jīng)發(fā)生了一個中斷。然后,中斷控制器將通過中斷向量表切換到處理程序。
掛起位的處理取決于目標硬件,但有兩個基本模型:
1.掛起位在中斷處理后自動清除(即當中斷處理程序開始執(zhí)行時)。當處理程序退出時,如果當前中斷正在處理時,中斷已成為掛起,則該處理程序?qū)⒆詣又匦掠|發(fā)。
2.掛起的位必須由中斷處理程序中的用戶代碼手動清除。中斷處理程序的主體,無論是第1類還是第2類,都需要包括清除掛起位的代碼,并向硬件發(fā)出信號,然后中斷已被處理。
如果需要清除掛起位,最好在進入處理程序時立即執(zhí)行此操作,因為這樣可以最大限度地減少中斷發(fā)生的第二個實例設(shè)置掛起位與隨后清除掛起位之間的時間。這有助于防止中斷多次掛起但硬件無法識別的問題。代碼示例3.3展示了二類ISR處理程序的推薦結(jié)構(gòu)。
#includeISR(Interrupt1) { /* Dismiss the interrupt where required */ /* Rest of the handler */ }
Example 3.3: Dismissing the interrupt
#includeISR(InefficientHandler) { /* Long handler code. */ }
Example 3.4: Inefficient interrupt handler
#includeISR(EfficientHandler) { ActivateTask(Task1); } TASK(Task1) { /* Long handler code. */ TerminateTask(); }
Example 3.5: More efficient interrupt handler
需要查閱硬件參考手冊,以了解需要在目標硬件上執(zhí)行的操作。
3.6.4 編寫高效的中斷處理程序 Writing Effificient Interrupt Handlers
編寫的每個中斷處理程序?qū)⒃诖a執(zhí)行所需的時間內(nèi)阻塞所有同等或更低優(yōu)先級的中斷。在編寫中斷處理程序時,使處理程序盡可能短是一種良好的做法。長時間運行的處理程序?qū)榈蛢?yōu)先級中斷的服務(wù)增加額外的延遲。
通過最小化中斷處理程序的執(zhí)行時間,可以最大化整個系統(tǒng)的響應(yīng)性。
如果需要執(zhí)行一段長時間運行的代碼來響應(yīng)中斷發(fā)生,那么可以將該代碼放入任務(wù)中,然后從Category 2 ISR激活該任務(wù)。例3.4和例3.5展示了這些技術(shù)的不同之處。
使用第2類處理程序,可以將所需的功能移動到任務(wù)中,只需使用中斷處理程序來激活任務(wù),然后終止。
3.7 啟用和禁用中斷Enabling and Disabling Interrupts
中斷只有在啟用時才會發(fā)生。默認情況下,RTA-OS確保在StartOS()返回時啟用所有內(nèi)部中斷。
集成指導:AUTOSAR操作系統(tǒng)使用術(shù)語“禁用”表示屏蔽中斷,“啟用”表示取消屏蔽中斷。因此,啟用和禁用API調(diào)用不會啟用或禁用中斷源;它們只是阻止處理器識別中斷(通常通過修改處理器的中斷掩碼)。
需要在短時間內(nèi)禁用中斷,以防止在任務(wù)或ISR中的關(guān)鍵代碼部分發(fā)生中斷。臨界區(qū)可以是訪問共享數(shù)據(jù)的代碼區(qū)。
可以使用許多不同的API調(diào)用來啟用和禁用中斷:
? DisableAllInterrupts() and EnableAllInterrupts()
禁用和啟用硬件上可以禁用的所有中斷(通常是所有可以屏蔽的中斷)。這些調(diào)用不能嵌套。在DisableAllInterrupts()之后,不允許調(diào)用除EnableAllInterrupts()之外的操作系統(tǒng)API。
? SuspendAllInterrupts() and ResumeAllInterrupts()
掛起并恢復所有可以在硬件上禁用的中斷(通常是所有可以屏蔽的中斷)。這些調(diào)用可以嵌套。在SuspendAllInterrupts()之后,不允許在SuspendAllInterrupts()/ResumeAllInterrupts()對和SuspendOSInterrupts()/ResumeOSInterrupts()對之外調(diào)用API。
? SuspendOSInterrupts() and ResumeOSInterrupts()
掛起和恢復硬件上的所有第2類中斷。這些調(diào)用可以嵌套。除了SuspendAllInterrupts()/ResumeAllInterrupts()對和SuspendOSInterrupts()/ResumeOSInterrupts()對之外,不允許在SuspendOSInterrupts()之后調(diào)用API。
注意:必須確?!癛esume”調(diào)用不會比“Suspend”調(diào)用多。如果存在,則可能導致嚴重錯誤,并且行為未定義。隨后的' Suspend '調(diào)用可能無法工作。這將導致無保護的臨界區(qū)。
示例3.6顯示了是如何正確地使用中斷控制API調(diào)用和嵌套的。
在第1類ISR的情況下,必須確保在禁用中斷的整個時間內(nèi)沒有進行RTA-OS API調(diào)用(其他掛起/恢復調(diào)用除外)。
如果2類ISR通過調(diào)用DisableAllInterrupts()將中斷級別提高到OS級別以上,那么它可能不會進行任何其他RTA-OS API調(diào)用,除了調(diào)用EnableAllInterrupts()來恢復中斷優(yōu)先級。當執(zhí)行ISR時,不允許將中斷優(yōu)先級降低到初始級別以下。
#includeTASK(Task1) { DisableAllInterrupts(); /* First critical section */ /* Nesting not allowed */ EnableAllInterrupts(); SuspendOSInterrupts(); /* Second critical section */ /* Nesting allowed. */ SuspendAllInterrupts(); /* Third critical section */ /* Nested inside second */ ResumeAllInterrupts(); ResumeOSInterrupts(); TerminateTask(); }
Example 3.6: Nesting Interrupt Control API Calls
3.8 保存寄存器集Saving Register Sets
RTA-OS提供了一種跨上下文切換保存寄存器集的機制,rtaosgen可以優(yōu)化提高運行時性能所需的保存量。
2類ISR也可以使用相同的機制,只需選擇哪些ISR使用圖3.6所示的配置寄存器集。
圖3.6:在類別2 ISR中的寄存器集
3.9 默認中斷The Default Interrupt
如果使用RTA-OS來生成一個向量表,那么可能需要用一個默認的中斷來填充未使用的向量位置。
圖3.7顯示了如何定義默認中斷的。
圖3.7:在向量表中放置一個默認中斷
注意:不要從默認中斷進行任何RTA-OS API調(diào)用,并且不能從處理程序返回。
默認中斷就像第1類中斷一樣實現(xiàn),因此必須用CAT1_ISR宏標記為中斷。默認中斷處理程序中的最后一條語句應(yīng)該是一個無限循環(huán)。示例3.7顯示了如何做到這一點。
CAT1_ISR(DefaultInterruptHandler) { /* invoke target-specific code to lock interrupts */ asm(’di’); /* or whatever on your platform */ for (;;) { /* Loop forever */ } /* Do NOT return from default handler. */ }
Example 3.7: The Default Interrupt Handler
3.10 小結(jié)
?RTA-OS支持1類中斷和2類中斷。
?1類ISR是繞過RTA-OS的正常嵌入式系統(tǒng)中斷。因此,它們不能與操作系統(tǒng)交互,并且被禁止進行(大多數(shù))RTA-OS API調(diào)用。它們應(yīng)該使用CAT1_ISR宏進行標記。
?第二類ISR是操作系統(tǒng)管理的中斷,運行在RTA操作系統(tǒng)提供的包裝器(Wrappers)中。這些中斷可以調(diào)用RTA-OS API。它們必須使用ISR宏進行標記。
?所有中斷運行在中斷優(yōu)先級(IPL),它總是嚴格高于最高任務(wù)優(yōu)先級。
?IPL標準化了所有硬件設(shè)備的中斷優(yōu)先級模型-更高的IPL意味著更高的優(yōu)先級。
?RTA-OS可以生成一個中斷向量表,或者你可以選擇自己編寫。當生中斷向量表時,RTA-OS可以用用戶配置的默認中斷插入未使用的位置。
審核編輯:劉清
-
微控制器
+關(guān)注
關(guān)注
48文章
7565瀏覽量
151593 -
處理器
+關(guān)注
關(guān)注
68文章
19334瀏覽量
230186 -
AUTOSAR
+關(guān)注
關(guān)注
10文章
362瀏覽量
21622 -
ISR
+關(guān)注
關(guān)注
0文章
38瀏覽量
14446
原文標題:符合AUTOSAR標準的RTA-OS --Interrupts詳解
文章出處:【微信號:汽車電子嵌入式,微信公眾號:汽車電子嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論