2011-03-23 54 views
3

我認爲這是「vi vs. emacs」類型的問題之一,但無論如何,我會問,因爲我想聽聽人們的意見。重複軟件定時器何時應該與之前的超時有關?

通常在嵌入式系統時間中,微控制器具有硬件定時器外圍設備提供了一種用於軟件定時器子系統的定時基。該子系統允許開發人員創建可用於生成和管理系統事件的任意數量的定時器(受系統資源限制)。通常管理軟件定時器的方式是硬件定時器設置爲以固定的時間間隔(或者有時僅在下一個活動定時器將到期時)生成。在中斷處理程序中,會調用回調函數來執行該計時器的特定事件。像往常一樣,這些回調例程應該很短,因爲它們在中斷環境中運行。

比方說,我創建一個觸發每1ms的計時器,其回調例程需要100us的執行,這是在系統發生興趣的唯一的事情。計時器子系統應該何時安排下一次軟件定時器的處理?從中斷髮生時起1ms,還是回調結束後1ms?

爲了讓事情更有趣,說硬件開發人員走過來說,在某些操作模式中,CPU的速度需要降低至最多20%以節省電力。現在回調例程需要500us而不是100us,但定時器的間隔仍爲1ms。假設這種增加的回撥延遲對待機模式下的系統沒有負面影響。同樣,計時器子系統應該在什麼時候安排下次處理這個軟件時間? T + 1ms或T + 500us + 1ms?

在這兩種情況下

或許應該採取折中的辦法,並在T +(execution_time/2)+ 1ms的安排?

回答

5

在實時OS兩個定時器和延遲被同步到系統時鐘,因此,如果事件處理花費不到一個計時器滴答,並啓動定時器蜱邊界上,將有使用之間沒有調度差定時器或延遲。

如果在另一方面,處理了超過一個滴答,你將需要一個計時器事件,以確保確定性抖動自由時間。

在大多數情況下,決定論是重要的或必不可少的,並且使系統行爲更具可預測性。如果時序是從處理結束時開始遞增的,則處理中的變化(無論是靜態 - 通過代碼更改還是運行時間通過差異執行路徑)都可能導致變量行爲和未經測試的角落案例難以調試或可能導致系統失敗。

3

我會讓硬件定時器每隔1ms觸發一次。我從來沒有聽說過硬件計時器考慮這樣一個快速的例程。特別是因爲每次軟件更改時都必須重新計算。或者找出當CPU改變時鐘速度後該怎麼做。或者如果您決定升級/降級您正在使用的CPU,請指出該怎麼做。

1

添加另一對夫婦的理由是什麼,在這一點上達成共識的答案(定時器應觸發每1ms):

  • 如果每1ms定時器觸發,和你真正想要的是一個1ms的差距在執行之間,您可以在回調函數的出口重置計時器,從該點開始1ms。

  • 然而,如果定時器觸發1ms的回調函數退出後,你想其他的行爲,你是那種卡住。

此外,它在硬件上每隔1ms觸發複雜得多。要做到這一點,它只會產生事件和重置,除了設置點之外,軟件沒有反饋回定時器。如果定時器離開1毫秒間隙,則軟件需要通過某種方式向定時器發送信號,告知它正在退出回叫。

而你絕對不應該「分裂差異」。這對大家做錯了事情,如果有人想讓別人做別的事情,那更讓人討厭。

0

我的默認行爲是讓例行程序以儘可能接近統一的間隔啓動,並讓一個遲到的例行程序試圖在限制範圍內「趕上」。有時候,一個好的模式可以是這樣的:

 
/* Assume 32,768Hz interrupt, and that we want foo() to execute 1024x/second */ 

    typedef unsigned short ui; /* Use whatever size int works out best */ 
    ui current_ticks; /* 32768Hz ticks */ 

    ui next_scheduled_event; 
    ui next_event; 

void interrupt_handler(void) 
{ 
    current_ticks++; 
    ... 
    if ((ui)(current_ticks - next_event) EVENT_INTERVAL*EVENT_MAX_BACKLOG) /* We're 32 ticks behind -- don't even try to catch up */ 
    { 
     delta = EVENT_INTERVAL*EVENT_MAX_BACKLOG; 
     next_scheduled_event = current_ticks - delta; 
    } 
    next_scheduled_event += EVENT_INTERVAL; 
    next_event = next_scheduled_event; 

    foo(); 

    /* See how much time there is before the next event */ 
    delta = (ui)(current_ticks - next_event - EVENT_MIN_SPACING); 
    if (delta > 32768) 
     next_event = current_ticks + EVENT_MIN_GAP; 
    } 

此代碼(未經測試)將在一個均勻的速度,如果它可以運行FOO(),但將始終允許執行之間EVENT_MIN_SPACING。如果它有時無法以所需的速度運行,則在EVENT_MIN_SPACING執行之間它會運行幾次,直到它「陷入困境」。如果它落後得太遠,它試圖「趕上」的嘗試將受到限制。

相關問題