在驅動程序內部,我有一個功能可以將數據從內部結構複製到應用程序的結構中。
此過程可以被微控制器中斷觸發器中斷嗎?
uint16_t getRawData(結構數據* Data_external)
{
如果(Data_external == NULL)
{
返回ERR_PARA;
}
其他
{
* Data_external =數據_內部;//複製過程。可以打擾一下嗎?
}
返回ERR_NONE;
}
在驅動程序內部,我有一個功能可以將數據從內部結構複製到應用程序的結構中。
此過程可以被微控制器中斷觸發器中斷嗎?
uint16_t getRawData(結構數據* Data_external)
{
如果(Data_external == NULL)
{
返回ERR_PARA;
}
其他
{
* Data_external =數據_內部;//複製過程。可以打擾一下嗎?
}
返回ERR_NONE;
}
是的。MCU中的幾乎所有內容都可以被中斷請求中斷。中斷處理程序完成後,先前的代碼將繼續執行,因此通常不會出現問題。
在特殊情況下,中斷處理程序可以被更高優先級的中斷(嵌套中斷)自己中斷。
如果一定不能中斷一系列指令,那麼您需要實施一個關鍵部分(基本上全局禁用中斷,執行此操作,然後再次啟用)。
請記住,根據目標CPU的體系結構,單行C可以編譯為許多彙編指令。如果 i
例如是 uint32_t
,則AVR上的簡單 i ++
會編譯為多條指令。
任何不是 atomic的操作都會受到中斷的干擾。這種編程通常與大多數其他編程有很大不同,並且可能使那些尚未研究處理器設計或計算機體系結構的人感到困惑。
您可能會想:“這將永遠不會發生,這段代碼需要花費多長時間複製,中斷發生的可能性有多大?”但是對於大多數生產嵌入式應用程序來說,這是會發生的,因為該產品已啟用多年且沒有更新。
像這樣的結構副本的另一個問題是,當它們確實發生時,它們極難調試,因為它們僅在中斷恰好在正確的時間(可能只有一個週期)發生時才發生。
中斷的全部要點是它們可以(並且確實)一直發生,並且設計為對發生時正在運行的任何代碼產生零影響。保存所有寄存器,並且根據CPU體系結構,可以交換一個完全不同的寄存器集,由中斷處理,然後恢復原始寄存器,並使代碼繼續正常運行。
當中斷服務例程本身嘗試訪問正在運行的中斷代碼正在訪問的內存時,可能會出現問題。 當時間緊迫的I / O進程中斷時,甚至可能發生更細微的錯誤。這些問題在較舊的,更簡單的,不太安全的體系結構中很常見,在“用戶”和“主管/內核”模式代碼之間可能幾乎沒有分隔。
這類問題可能很難識別,而且通常很難重現,但是一旦識別出來,使用防禦性編程,互斥量/信號量或僅通過禁用代碼關鍵部分中的中斷來解決這些問題通常就非常簡單。
已經廣泛研究了一般問題類別,如果尚未嘗試和測試多種解決方案,現代多核CPU甚至多任務操作系統將無法實現。
我將繼續前進,並假設您出於非常充分的理由問這個問題。
* Data_external =數據內部;
可以拆分(除非存在一些不太可能在此處發揮作用的極端情況)。
我不知道您的CPU,但我還沒有看到一個CPU在道德上不能做到:
cli();/ *屏蔽所有中斷* /
* Data_external =數據_內部;
sti();/ *恢復中斷掩碼* /
現在不能在任何單核CPU上拆分它,因為在中斷關閉時沒有任何東西可以中斷。這是否一個好主意,取決於很多我根本沒有資格評估的事情。
如果您是多核的(我最後記得市場上有多核嵌入式CPU),請不要這樣做。這是毫無價值的。您將需要開發適當的鎖定。
您提供的代碼確實可以被打斷。但是,在開始到處製作關鍵部分之前,應檢查以下幾件事:
您說此功能位於“驅動程序內部”。調用此函數時是否已禁用中斷?還是在阻止其他中斷觸發的中斷處理程序中調用它?如果是,則實際上無法中斷該操作。
是否曾經在中斷處理程序中訪問過 Data_internal
?如果沒有,即使中斷操作也不會造成傷害。
[沒有足夠的評論意見]
具有這種結構副本的另一個gotchya是它是淺副本。您可能需要深拷貝。
根據機器體系結構,淺表副本可能(但不可能)是原子副本。幾乎可以肯定,在任何體系結構上,深拷貝都不是原子的。
適合嵌入式系統使用的質量實現將記錄如何足夠詳細地執行 volatile
限定的各種類型的讀取或寫入,以指示是否以及如何通過中斷將它們“拆分” ,以及是否針對不合格的讀寫對易失性讀寫進行排序。儘管某些實現可能表現為所有讀寫都是 volatile
限定的,但是通常期望實現可以自由地以任何方式處理不合格的讀寫序列,只要有沒有中間的 volatile
訪問。
在典型的32位微控制器上,讀寫32位及以下的 volatile
限定整數類型;一個分配將由一個原子讀取和一個原子寫入組成。如果要確保以原子方式複制32位結構,請將其與 uint32_t
合併在一起,然後讀取或寫入該成員以整體讀取或寫入該結構。被配置為適合嵌入式系統使用的質量實現將允許以這種方式使用聯合,而無需考慮標準是否會要求不打算用於此類用途的實現也是如此。請注意,除非禁用各種優化,否則gcc和clang不會可靠地充當適合嵌入式系統使用的高質量實現。