題:
是否可以通過嵌入式C中的中斷來中斷結構的複製過程?
Stani
2018-09-06 14:27:06 UTC
view on stackexchange narkive permalink

在驅動程序內部,我有一個功能可以將數據從內部結構複製到應用程序的結構中。

此過程可以被微控制器中斷觸發器中斷嗎?

  uint16_t getRawData(結構數據* Data_external)
{
  如果(Data_external == NULL)
  {
    返回ERR_PARA;
  }
  其他
  {
    * Data_external =數據_內部;//複製過程。可以打擾一下嗎?
  }
  返回ERR_NONE;
}
 
並沒有真正的“複製過程”,會有指令在周圍複製字節,如果它們不是原子字節,則可以被中斷,具體取決於您的體系結構,編譯器,設置和對齊方式
在C中不能保證不能中斷結構複製過程。但是,通常應該將中斷返回到代碼中可以完成複製過程的點。因此,除非中斷代碼出於某種原因依賴於它(在大多數情況下不太可能),否則可能無關緊要。但是,如果這些結構是上/下層中斷驅動程序對的一部分,那麼如果上層中斷驅動程序對存在,則可能會出現問題。當發生中斷時,它正在刪除或向緩衝區添加“塊”的過程,該中斷還必須處理同一緩衝區中的“塊”。
@jonk:請不要在評論中回答問題,因為這會繞過正常的答案回答過程,如[在meta中討論](https://meta.stackexchange.com/questions/117251)
@DaveTweed然後,您和本網站將***失去我的評論。除非我有時間寫完整的答案,否則我不會寫答案。這是我唯一的操作方式,我不會更改。如果我有足夠的時間來定義一個“正確答案”,我將像以前一樣繼續。但是我在幾個不同的活動項目上都非常努力,並且沒有時間按照我通常的水平回答上下文和內容。因此,我要么寫一些簡短的評論作為評論,要么網站失去對我的時間的訪問權限。您的來電。我的時間是按我的條件分配的,或者根本不分配。
-1
@DaveTweed感謝您的推動。點大多無關緊要。我認為一旦達到200分的“精打細算廣告”,我就不會在乎其餘(也沒有使用過)。我也不認為我現在應該獲得如此高的數字。天哪,我只是一個業餘愛好者。我非常擔心,人們可能會誤以為聲譽號對他們來說意義不大。我寧願我的言語始終保持“可疑”並應受到批評,而不應被視為某種福音。如果我可以削減代表人數,我會這樣做。
@jonk如果您確實希望人們能夠“懷疑”您的答案,那麼請允許人們對其進行正確的投票。在(不太可能!)情況下,您發表了一些錯誤的評論,用戶將無法投票。如果人們贊成最初看起來正確的評論,這可能尤其成問題(再次,我並不是在質疑您的評論/答案的質量:))
@mbrig您可能會誤解我。我可以選擇*僅*這樣寫***答案***,如果它們包含完整的上下文和內容,或者我認為我可能提供*不尋常*或*獨特*的方法,請附加我的名字。從某種意義上來說,我也不會一直在研究它們,因為我不會在尋找自己與我的立場以及我可以引用的參考資料和支持材料進行“雙重”核對之前,不發表答案。我不只是寫我寫,然後研究,交叉檢查和驗證。然後發布。否則,它不會作為我的答案。
@mbrig最後,我的代表電話號碼*沒有意義。*我寫的可能是。但這是一個單獨的問題。我只是希望我可以清空或刪除我的銷售代表號碼。我很高興有人發現我(或兩個)的回答很有幫助。但是根據我的代表電話號碼,人們自然會想到其他東西,但我希望他們不會。就這樣。您的建議沒有解決我的任何擔憂。
@jonk:您可以提出懸賞問題,並獎勵29k信譽的人擺脫它;)
@Rev1.0如果它也不必太費勁地去思考一個值得解決的問題/問題,並且也許也沒有消除我要指出的問題,而是將其傳遞給我,我可能會這樣做不過,還有其他人(沒有解決我的問題)。;)
@jonk:嘿嘿,讓我們變得瘋狂;)1.創建第二個帳戶2.用第一個帳戶寫一個很棒的問題+賞金3.使用第二個帳戶回答一個發布了一個很棒的答案的問題4.刪除第二個帳戶->結果:您寫了一個好問題,一個很好的答案,而你甚至在這樣做的時候都失去了聲譽。
@Rev1.0(1)我有預感,這會違反某些對政策的解釋並被禁止。(2)我仍然希望人們知道我是誰,並且更改帳戶非常複雜,否則就無法實現該目標。(3)某個人(即使是我)仍然會發現這些代表點。(4)我喜歡創造性思維!謝謝。
七 答案:
filo
2018-09-06 16:30:30 UTC
view on stackexchange narkive permalink

是的。MCU中的幾乎所有內容都可以被中斷請求中斷。中斷處理程序完成後,先前的代碼將繼續執行,因此通常不會出現問題。

在特殊情況下,中斷處理程序可以被更高優先級的中斷(嵌套中斷)自己中斷。

如果一定不能中斷一系列指令,那麼您需要實施一個關鍵部分(基本上全局禁用中斷,執行此操作,然後再次啟用)。

請記住,根據目標CPU的體系結構,單行C可以編譯為許多彙編指令。如果 i 例如是 uint32_t ,則AVR上的簡單 i ++ 會編譯為多條指令。

關於您的最後一段,我認為這僅適用於16/8位系統,對嗎?我知道你在說AVR ..只是確保。
結構的memcpy(如問題中所示)在32位ARM上也是多個指令。在32位ARM上uint64_t的增量也不是原子的。按位操作也可以讀-修改-寫(除非使用位帶)。
@HarrySvensson在任何RMW體系結構上均不可用,並且大多數uC是讀-修改-寫的(大多數RISC處理器是RMW)。因此,在許多情況下,i ++都會生成(在此處不是這種情況,除非該值僅保存在寄存器中)在現代32/64位ARM uC上也會生成三條指令。
啊,這裡有點誤會。我當時在考慮執行增量(溢出)時要注意進位,並且你們倆都在談論從內存中檢索和回寫。- 那好吧。
通常:所有對大於數據總線寬度的類型的操作都是“笨拙的”。
Sam
2018-09-06 20:25:26 UTC
view on stackexchange narkive permalink

任何不是 atomic的操作都會受到中斷的干擾。這種編程通常與大多數其他編程有很大不同,並且可能使那些尚未研究處理器設計或計算機體系結構的人感到困惑。

您可能會想:“這將永遠不會發生,這段代碼需要花費多長時間複製,中斷發生的可能性有多大?”但是對於大多數生產嵌入式應用程序來說,這是會發生的,因為該產品已啟用多年且沒有更新。

像這樣的結構副本的另一個問題是,當它們確實發生時,它們極難調試,因為它們僅在中斷恰好在正確的時間(可能只有一個週期)發生時才發生。

Echelon
2018-09-06 18:39:19 UTC
view on stackexchange narkive permalink

中斷的全部要點是它們可以(並且確實)一直發生,並且設計為對發生時正在運行的任何代碼產生零影響。保存所有寄存器,並且根據CPU體系結構,可以交換一個完全不同的寄存器集,由中斷處理,然後恢復原始寄存器,並使代碼繼續正常運行。

當中斷服務例程本身嘗試訪問正在運行的中斷代碼正在訪問的內存時,可能會出現問題。 當時間緊迫的I / O進程中斷時,甚至可能發生更細微的錯誤。這些問題在較舊的,更簡單的,不太安全的體系結構中很常見,在“用戶”和“主管/內核”模式代碼之間可能幾乎沒有分隔。

這類問題可能很難識別,而且通常很難重現,但是一旦識別出來,使用防禦性編程,互斥量/信號量或僅通過禁用代碼關鍵部分中的中斷來解決這些問題通常就非常簡單。

已經廣泛研究了一般問題類別,如果尚未嘗試和測試多種解決方案,現代多核CPU甚至多任務操作系統將無法實現。

Joshua
2018-09-07 04:32:01 UTC
view on stackexchange narkive permalink

我將繼續前進,並假設您出於非常充分的理由問這個問題。

  * Data_external =數據內部;
 

可以拆分(除非存在一些不太可能在此處發揮作用的極端情況)。

我不知道您的CPU,但我還沒有看到一個CPU在道德上不能做到:

  cli();/ *屏蔽所有中斷* /
* Data_external =數據_內部;
sti();/ *恢復中斷掩碼* /
 

現在不能在任何單核CPU上拆分它,因為在中斷關閉時沒有任何東西可以中斷。這是否一個好主意,取決於很多我根本沒有資格評估的事情。

如果您是多核的(我最後記得市場上有多核嵌入式CPU),請不要這樣做。這是毫無價值的。您將需要開發適當的鎖定。

什麼是cli和sti?從谷歌他們似乎是x86指令?
@Sam:好,是的,這些是x86中指令的名稱。我認為它們在PDP-11中具有相同的名稱,因為起源於此的某些代碼在用戶模式(掩碼進程間信號)中具有等效的邏輯等效功能名稱。這是Arduino的說明:https://www.tldp.org/LDP/tlk/dd/interrupts.html
通常,您將禁用中斷,但只有在實際啟用中斷後才能重新啟用它們。否則,即使在調用代碼之前將其禁用,您的代碼也會始終啟用中斷。
Dmitry Grigoryev
2018-09-07 18:08:31 UTC
view on stackexchange narkive permalink

您提供的代碼確實可以被打斷。但是,在開始到處製作關鍵部分之前,應檢查以下幾件事:

  • 您說此功能位於“驅動程序內部”。調用此函數時是否已禁用中斷?還是在阻止其他中斷觸發的中斷處理程序中調用它?如果是,則實際上無法中斷該操作。

  • 是否曾經在中斷處理程序中訪問過 Data_internal ?如果沒有,即使中斷操作也不會造成傷害。

studog
2018-09-07 23:49:40 UTC
view on stackexchange narkive permalink

[沒有足夠的評論意見]

具有這種結構副本的另一個gotchya是它是淺副本。您可能需要深拷貝。

根據機器體系結構,淺表副本可能(但不可能)是原子副本。幾乎可以肯定,在任何體系結構上,深拷貝都不是原子的。

一個公平的點;但是深拷貝更可能是原子拷貝,因為它幾乎總是通過指針交換來放置的。但是在這種情況下,如果它應該是一個深複製的版本,則絕對不是原子的。
supercat
2018-09-07 23:51:55 UTC
view on stackexchange narkive permalink

適合嵌入式系統使用的質量實現將記錄如何足夠詳細地執行 volatile 限定的各種類型的讀取或寫入,以指示是否以及如何通過中斷將它們“拆分” ,以及是否針對不合格的讀寫對易失性讀寫進行排序。儘管某些實現可能表現為所有讀寫都是 volatile 限定的,但是通常期望實現可以自由地以任何方式處理不合格的讀寫序列,只要有沒有中間的 volatile 訪問。

在典型的32位微控制器上,讀寫32位及以下的 volatile 限定整數類型;一個分配將由一個原子讀取和一個原子寫入組成。如果要確保以原子方式複制32位結構,請將其與 uint32_t 合併在一起,然後讀取或寫入該成員以整體讀取或寫入該結構。被配置為適合嵌入式系統使用的質量實現將允許以這種方式使用聯合,而無需考慮標準是否會要求不打算用於此類用途的實現也是如此。請注意,除非禁用各種優化,否則gcc和clang不會可靠地充當適合嵌入式系統使用的高質量實現。



該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 4.0許可。
Loading...