中斷處理程式的設計
在嵌入式系統的設計中,與外設互動,基本是兩種模式:輪詢和中斷。考慮到CPU與外設之間的速度差,如果涉及到與外設通訊,一般採用中斷的方式:只有當外設完成了資料傳送或者接收,才中斷CPU,獲得處理,這樣可以保證CPU的處理效率最高。
與資料收發相關的中斷,中斷處理程式與外部程式(作業系統和應用程式)之間的資料交換方式的設計是中斷處理程式設計的一個關鍵部分,直接影響系統的工作效率,甚至是一些偶發性故障的原因。
資料交換的主要考慮的因素有:資料完整性(保證資料不丟失)、交換的效率(儘量減少CPU的參與)、執行效率(中斷處理程式的執行應儘量保證時間短)、異常資料丟棄的效率(儘可能在離入口近的位置丟棄異常資料)。其中資料完整性經常會被忽視,中斷處理程式的不恰當導致的資料丟失經常會與通訊干擾導致的資料丟失相混淆,從而掩蓋了真正的問題。
本文主要探討中斷處理程式與外部程式之間的資料互動的方式及其優缺點。
FIFO結構快取
這是一種最簡單直觀的資料互動方式,採用迴圈Buffer作為快取,主要用於資料接收。其結構如下:
迴圈Buffer有一個起始位置Start和一個結束位置End,當指標移動到End以後,自動回到Start位置。關於迴圈Buffer的具體實現,網上有很多詳細資料,此處就不贅述。
應用到中斷的接收處理中,中斷處理程式作為該FIFO的資料生產者,操作寫指標WritePointer,將接收到的資料寫入該快取;外部程式作為該FIFO的資料消費者,操作讀指標ReadPointer,將資料從快取中讀出,進行處理。外部程式必須保證讀指標不超越寫指標,以防止讀出不正確的資料。簡單的處理虛擬碼如下:
Interrupt Handler:
{
...
FifoBuffer[WritePointer] = DataRegister;
WriterPointer++;
if(WriterPointer > End) WriterPointer = Start;
...
}
Application:
{
...
AppBuffer[bufPointer] = FifoBuffer[ReadPointer];
bufPointer++;
ReadPointer++;
if(ReadPointer > End) ReadPointer = Start;
Lock_CPU();
if(ReadPointer == WritePointer) {
unLock_CPU();
Stop;
}
unLock_CPU();
...
}
在採用該方法時,實際上隱含著一個假設:寫指標永遠不會追上讀指標,也就是不會發生迴圈Buffer溢位的情況。為了滿足這個要求,一方面外部程式必須保證讀處理應該以合適的頻度得到執行;另外,在設計時,迴圈Buffer保證有足夠的長度。
從上面的實現可以看出,中斷處理程式只負責將接收到的資料放入FIFO中,處理簡單,佔用時間少;但外部程式必須頻繁地檢查FIFO以確保新收到的資料得到及時處理;資料包的識別、資料的檢查和拷貝也都需要外部程式負責,處理負擔較重。同時為了保證資料不丟失,就必須滿足上述隱含條件。
訊息傳遞
在嵌入式系統中,不同任務之間,經常採用一種訊息機制來進行資料傳輸。所有的嵌入式作業系統,都提供了相應的機制,如RTX的MailBox。基本的思路就是將需要傳送的資料放入公共的記憶體中(在嵌入式系統中,實際上就是全域性變數),然後通過郵箱將指標傳遞給接收方。
在中斷處理程式和外部程式之間,也可以採用這種機制傳遞接收到的資料。為了提高傳遞的效率,一般需要中斷處理程式識別出一個完整的資料包,以一次傳遞一個數據包的形式進行。簡單的處理虛擬碼如下所示:
Interrupt Handler:
{
...
msgSendBuffer = Get_Message_Buffer();
CopyDataToBuffer(InternalBuffer, msgSendBuffer);
Send_MailBox(DestinationMailBox, msgSendBuffer);
...
}
Application:
{
...
Receive_MailBox(WaitMailBox, msgRcvBuffer);
...
}
採用這種方式,可以簡化外部處理程式的實現,以一種統一的處理訊息的方式來實現對來自中斷和其他任務的資料。對接收到的資料的處理,中斷處理程式側需要識別出一個完整的資料包,並將它拷貝到訊息快取中,對資料包合法性的檢查可以由中斷執行,也可以由外部程式執行。因此,中斷處理程式的任務較多,而外部Task則相對簡單。
在這種方式中,同樣有一個隱含的條件:必須保證訊息快取肯定能申請到,否則將導致整個資料包的丟失。另外,如果訊息快取與外部任務用的快取採用同一套機制的話,外部任務的快取申請可能延遲中斷的快取申請,影響中斷處理的效率。為了解決這個問題,常常為中斷與外部傳輸準備專用的快取。
快取區交換
在中斷處理程式中的資料拷貝是一件比較耗時的工作,往往會阻塞其他中斷處理程式和應用程式,嚴重時導致異常發生。因此在中斷處理中避免拷貝,是提高效率的捷徑。如果能夠同時與DMA等的使用相結合,能夠顯著解放CPU的負擔,提高整個系統的執行效率。
快取區交換是對訊息傳遞的一種改進,中斷處理程式與外部應用程式之間還是採用訊息傳遞的機制,但在中斷處理程式中不再需要申請快取,而是直接使用外部應用程式預先申請好的快取;而預先申請快取,在中斷需要使用快取時保證已經準備好則是外部應用程式的責任。
基本處理流程如下所示:
該方法如果與DMA結合使用,接收資料的動作將由硬體自動完成,大大減少對CPU的中斷次數,可以大大提供處理效率。