2016-11-14 23 views
3

我正在開發基於ARM Cortex M3的微控制器上運行的嵌入式項目。我們供應商提供的一些代碼使用延遲功能,設置內置硬件定時器,然後旋轉直到定時器到期。通常用於等待1到幾百微秒。這些延遲幾乎是因爲他們在等待一些寄存器,芯片或總線來完成一個動作,並且需要等待至少給定的微秒數。硬件計時器的開銷似乎至少需要6微秒才能完成設置。ARM嵌入式延遲硬件定時器與CPU週期計數器

在多線程環境中,這是一個問題,因爲有N個線程,但只有1個硬件定時器。我可以禁止中斷,而定時器正在使用,以防止上下文切換,因此競爭條件,但它似乎有點難看。我想用一個使用ARM CPU週期計數器(CCNT)的函數替換使用硬件定時器的函數。我是否缺少缺陷或其他選擇?很明顯,週期計數器功能要求將其調整到適當的CPU頻率,這對我們的系統來說永遠不會改變,但我想可以在使用硬件定時器以編程方式引導時檢測到。

+0

哪種ARM M3有單個硬件定時器?你說你有一個多線程環境,所以調度器的計時器是必需的:你是否說你唯一的計時器是分配給調度器的計時器? – LPs

+0

實際上有2個硬件定時器,還有一個系統時鐘中斷,每隔1毫秒觸發一次。系統滴答中斷不是一個計時器,你不能查詢已經過了多少時間,你只需要每1毫秒獲取一次中斷,這通常用於通知搶先調度器。 1毫秒的分辨率對於我感興趣的延遲來說也太長了。 – satur9nine

+0

對於現代MCU來說,忙碌的這麼長時間是一個非常糟糕的方法。如果他們使用這樣的東西,我會懷疑其餘的質量.. – Olaf

回答

6

在啓動時設置一次計時器,讓計數器連續運行。當您想要開始延遲時,請閱讀計數器值並記住該起始值。然後在延遲循環中再次讀取計數器值並循環,直到計數器值減去起始值大於或等於請求的延遲滴答聲爲止。 (如果你正確地做了減法運算,那麼翻滾會被洗掉,你不需要特殊處理來檢查它們。)

+2

作爲一個例子,請參閱雷蒙德陳的寫作:[使用模塊化算法,以避免時間溢出問題](https://blogs.msdn.microsoft的.com/oldnewthing/20050531-22/p = 35493)。使用無符號類型,數學就算了。 –

+0

另一件事 - 你可能想延遲一個更多的滴答計數比請求(除非請求是等待零滴答)來處理的事實,即第一次計時器讀取可能只有一個納秒秒之前計時器滴答聲增加。 –

+0

@kkrambo聽起來不錯。你能解釋爲什麼這個解決方案比使用CPU週期計數器更好嗎?我認爲這比較好,因爲這不需要根據CPU頻率進行任何調整。 – satur9nine

2

您可以複用您的計時器,以便您擁有每個線程想要關閉的表以及用於執行的函數指針/向量。當定時器中斷髮生時,觸發該線程的中斷,然後將定時器設置爲列表中的下一個,減去經過的時間。這就是我看到許多* nix操作系統在其內核代碼中執行的操作,因此應該有代碼來作爲示例。

更大的問題是您正在旋轉鎖定等待定時器的線程。除了CPU使用率以及根據您擁有的操作系​​統(或者您是否擁有操作系統),您可以輕鬆引入線程反轉問題,甚至可以完全鎖定。使用線程原語可能會更好,所以任何操作系統都可以實際上休眠線程並在需要時喚醒它們。