2010-05-02 42 views
7

我有一些代碼需要運行,因爲特定的中斷髮生。哪些Cortex-M3中斷可用於通用目的?

我不想在中斷本身的上下文中執行它,但我也不希望它在線程模式下執行。

我想運行它的優先級低於導致其運行的高級中斷,但優先級高於線程級別(以及其他一些中斷)。

我想我需要使用其他中斷處理程序之一。

哪些是最好的使用和最好的方式來調用它們?

目前我正在計劃僅使用中斷處理程序來處理一些我不使用的外設,並通過直接通過NVIC設置位來調用它們,但我希望有更好,更正式的方法。

謝謝,

回答

15

ARM Cortex支持一種非常特殊的稱爲PendSV的異常。看來你可以完全使用這個例外來完成你的工作。幾乎所有針對ARM Cortex的搶佔式RTOS都使用PendSV來實現上下文切換。

爲了使其工作,您需要優先PendSV低(向NVIC中的PRI_14寄存器寫入0xFF)。您還應該優先考慮PendSV以上的所有IRQ(在NVIC的相應優先級寄存器中寫入較低的數字)。當您準備處理整個消息,從高優先級ISR觸發PendSV的:然後

*((uint32_t volatile *)0xE000ED04) = 0x10000000; // trigger PendSV 

在ARM Cortex CPU將完成你的ISR和可能被它搶佔所有其他的ISR,並最終將其將會尾隨PendSV異常。這是解析消息的代碼應該在的地方。

請注意,PendSV可能會被其他ISR搶佔。這一切都很好,但是您顯然需要記住通過一段關鍵代碼來保護所有共享資源(簡要地禁用和啓用中斷)。在ARM Cortex中,通過執行__asm(「cpsid i」)來禁止中斷,並通過__asm(「cpsie i」)啓用中斷。 (大多數C編譯器爲此提供了內置的內部函數或宏。)

+0

謝謝,米羅!我到處搜索如何觸發PendSV中斷的信息,這是我終於找到它的地方!雖然我想如果我更仔細地閱讀了我的Cortex M3 r1p1技術參考手冊,我會在描述中斷控制狀態寄存器的頁面上找到它: http://infocenter.arm.com/help/topic/com.arm .doc.ddi0337e/DDI0337E_cortex_m3_r1p1_trm.pdf – 2010-06-18 02:21:04

+0

從我的閱讀中,幾乎CortexM3上的所有RTOS都使用Systick Timer中斷(45十進制,二進制二進制)來運行其調度程序。那麼PendSV是啓動一種特殊的「系統調用」的方式?希望我明白這一點。 – 2010-07-08 00:02:15

+1

@WarrenP:PendSV用於實際處理上下文切換。 sys tick用於循環任務 - sys tick會一般設置PendSV。 – 2011-10-02 20:48:52

3

您是否正在使用RTOS?通常,這種類型的事情將通過具有高優先級的線程來處理,該高優先級的線程被中斷信號通知來做一些工作。

如果你不使用RTOS,你只有幾項任務,並且由中斷啓動的工作不是太耗費資源,可能最簡單的做法是在上下文中完成高優先級的工作中斷處理程序。如果這些條件不成立,那麼實施你所說的將是基本的多任務操作系統本身的開始。這本身可能是一個有趣的項目,但如果您只是想完成工作,您可能需要考慮一個簡單的RTOS。

既然你提到你正在做的工作的一些細節,下面是我是如何處理在過去類似的問題的概述:

對於處理接收到的數據通過UART一個方法,我已經在處理不完全支持任務的簡單系統時(即,簡單的while循環中的任務是簡單的),應該使用從UART接收的數據的共享隊列。當UART中斷觸發時,數據從UART的RDR(接收數據寄存器)讀取並放入隊列中。以這種方式處理隊列指針沒有損壞的技巧是小心地使隊列指針變爲易失性的,並且確保只有中斷處理程序修改尾指針並且只有正在讀取數據的'foreground'任務關閉隊列修改頭指針。甲高級概述:

  • 生產者(UART的中斷處理程序):

    1. queue.headqueue.tail成當地人;
    2. 遞增本地尾指針(不是實際的queue.tail指針)。如果你增加了隊列緩衝區的末尾,將它包裝到隊列緩衝區的開始位置。
    3. 比較local.taillocal.head - 如果它們相同,則隊列已滿,您必須執行任何錯誤處理。
    4. 否則你可以寫入新的數據到local.tail
    5. 只有現在你可以設置queue.tail == local.tail
    6. 從中斷返回(或者辦理其他UART相關的任務,如果合適的話,喜歡讀書從傳送隊列)
  • 消費者(前臺 '任務')

    1. queue.headqueue.tail成當地人;
    2. if local.head == local.tail隊列爲空;返回讓下一個任務做一些工作
    3. 讀取local.head指向的字節
    4. 增量local.head並在必要時包裝它;
    5. 設置queue.head = local.head
    6. 轉至步驟1

確保queue.headqueue.tailvolatile(或彙編寫這些位),以確保有沒有順序問題。

現在只要確保你的UART接收到的數據隊列足夠大,它就會保存前臺任務有機會運行之前可能收到的所有字節。前臺任務需要將隊列中的數據放入其自己的緩衝區中,以構建消息給「消息處理器」任務。

+0

我沒有使用RTOS。 我得到的是一個高優先級的中斷,每次我通過串行接收字節時都會關閉。 它以高(低優先級數)優先級運行,以便我不會錯過字節。 當收到完整的信息後,我需要做一些工作,雖然我打算讓這項工作在性質上完全不受阻礙,但我不想限制自己有最大限度的時間允許它(我不會寫這個代碼)。 我沒有做任何先發制人的多任務處理。 – 2010-05-02 10:37:55

+0

串行數據的速度是多少?速率真的如此之高,或其他中斷處理程序如此糟糕的設計,以至於中斷優先級會有所不同?爲什麼不使用DMA傳輸來減少中斷頻率或完全避免它們? – Clifford 2010-05-02 10:44:26

+0

我們在57600下運行,但可能會移動到115200.我不能在路上使用DMA傳輸,因爲什麼樣的信號表明消息的​​結束是字節超過某個特定值的時間。我有三個需要運行的任務:1.一個串行消息接收器/發送器2.一個消息處理器3.一些背景負載。中間的一個是狀態機,所以它被認爲幾乎沒有工作(只是更新狀態)。我希望他們能夠在不同的中斷級別運行,因爲在較低級別缺少最後期限不太難以調試(對我而言)。 – 2010-05-02 11:03:46

1

「更正式的方式」或更傳統的方法是使用基於優先級的搶佔式多任務調度程序和「延遲中斷處理程序」模式。

+0

@Clifford:你有鏈接到「延遲中斷模式」的描述嗎? – simon 2010-05-02 22:59:46

0

檢查處理器文檔。如果寫入通常必須在中斷內清除的位,則某些處理器會中斷。我正在使用SiLabs c8051F344和規格表部分9.3.1:

「軟件可以通過將任何中斷掛起標誌設置爲邏輯1來模擬中斷。如果中斷標誌被使能,中斷請求將會將被生成,並且CPU將會引導到與中斷掛起標誌關聯的ISR地址。「

1

您要求的內容在Cortex-M3上非常簡單。您需要啓用STIR寄存器,以便用軟件觸發低優先級的ISR。當高優先級的ISR完成關鍵任務時,它會觸發低優先級中斷並退出。如果沒有什麼更重要的事情發生,NVIC將鏈接到低優先級的處理程序。

相關問題