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