2 6 系統時鐘節拍

2021-10-06 16:28:12 字數 3729 閱讀 5401

任何的作業系統都需要提供乙個時鐘節拍,以供系統處理如延時,超時等與時間相關的事件(時基)。

系統時鐘節拍是特定的週期性中斷,中斷間的時鐘間隔取決於不同的應用。(設定時基,一般是1ms左右)

時鐘的節拍中斷使得可以將任務延遲若干個時鐘節拍(釋放cpu給其他任務,若干時間後再執行)

在任務等待事件發生的時候,也提供等待超時等待;

時鐘節拍頻率越快,系統額外開銷越大

freertos通過滴答定時器產生systick中斷

#define configtick_rate_hz ( ( ticktype_t ) 1000 )
設定系統時鐘節拍1khz,也就是1ms

void xportsystickhandler( void )

basetype_t xtaskincrementtick( void ) // 更新系統時間函式

// 預設使用 pxdelayedtasklis ,每一次溢位,都會切換使用列表

else

if( xconsttickcount >= xnexttaskunblocktime ) // 當前系統時間 >= 下乙個喚醒系統的時間

else // 當前使用pxdelayedtasklist列表

else // 當前時刻 >= 第一任務喚醒值

( void ) uxlistremove( &( pxtcb->xstatelistitem ) ); // 延時到期,任務從延時列表中刪除

if( listlist_item_container( &( pxtcb->xeventlistitem ) ) != null )

else

prvaddtasktoreadylist( pxtcb ); // 任務新增到就緒列表中

#if ( configuse_preemption == 1 )

else

}#endif}}

} // 時間片排程

#if ( ( configuse_preemption == 1 ) && ( configuse_time_slicing == 1 ) )

else

}#endif

#if ( configuse_tick_hook == 1 )

else

}#endif

} else // 排程器被掛起後,記錄系統時間

#endif

} #if ( configuse_preemption == 1 )

else

}#endif

return xswitchrequired;

}// pxdelayedtasklist = &xdelayedtasklist1;

// pxoverflowdelayedtasklist = &xdelayedtasklist2;

#define taskswitch_delayed_lists() \

static void prvresetnexttaskunblocktime( void )

else // 不為空,記錄首項的歸屬任務,獲得這個任務的項值

}

任務體內的延時多使用軟體延時,讓cpu空等到達延時效果(執行空**nop)

rtos的主要優勢就是榨乾cpu的效能,讓其不空閒,

也就是加入任務需要延時的時候,不能讓cpu空等,必須讓其幹點什麼(延時釋放cpu執行低優先順序的任務)

rtos中的延時叫做阻塞函式,也就是任務需要延時會使得任務放棄cpu的使用權,cpu可以去幹其他事情

(任務放棄cpu使用權的時候,當前任務進入阻塞,cpu會去執行低優先順序任務,沒有就緒態低優先順序任務就執行空閒任務)

vtaskdelay

呼叫延時函式之後,任務進入阻塞態,剝離cpu使用權,直到延時結束,重新獲取cpu使用權

vtaskdelay 是相對延遲,也就是對於當前,延遲多長的時間;

延遲函式會使得任務陷入阻塞狀態,讓出cpu資源

在設定好延時時間之後,會呼叫函式taskyield產生pendsv中斷,

在pendsv中斷服務函式中,呼叫上下文切換函式vtaskswitchcontext,尋找最高優先順序的就緒任務,

然後更新pxcurrenttcb(就是不斷去測試其他任務的xtickstodelay是否為0

如果乙個任務要延時,那麼其tcb成員變數xtickstodelay一定不為0,當xtickstodelay為0的時候表示延時結束;

在freertos中,xtickstodelay這個變數的遞減位於systick中斷,另外遞減週期也是systick中斷週期

void vtaskdelay( const ticktype_t xtickstodelay )

// 將當前任務新增到延時列表中

xalreadyyielded = xtaskresumeall(); // 恢復任務排程器

} else

if( xalreadyyielded == pdfalse ) // 開啟排程器失敗則手動切換

else // 開啟排程器成功則自動切換任務

}

static void prvaddcurrenttasktodelayedlist( ticktype_t xtickstowait, const basetype_t xcanblockindefinitely )

#endif

if( uxlistremove( &( pxcurrenttcb->xstatelistitem ) ) == ( ubasetype_t ) 0 )

else

#if ( include_vtasksuspend == 1 )

else // 任務不支援掛起,就加入到延時列表中(支援就掛起列表)

// 按照喚醒時間插入到對應的列表中

else // 喚醒時間在系統時間溢位之前

else

}} }

#else

#endif

}

vtaskdelayuntil

vtaskdelayuntil函式,函式本身使用一定時間,其他任務使用一定時間

vtaskdelayuntil在使用之前,必須獲取當前的時刻(任務處於執行態的時刻)

void vtaskdelayuntil(	ticktype_t * const pxpreviouswaketime,	// 最後一次接觸阻塞的時間,第一次呼叫使用當前時間

const ticktype_t vtaskdelayuntil ) // 週期迴圈時間,當前時間 + vtaskdelayuntil接觸阻塞

else

}else // 系統時間沒有發生溢位

else

}*pxpreviouswaketime = xtimetowake; // 記錄上次喚醒時間,用於下一次呼叫函式

if( xshoulddelay != pdfalse )

else

}xalreadyyielded = xtaskresumeall(); // 恢復任務排程器

if( xalreadyyielded == pdfalse )

else }

void vtaska( void * pvparameters )

}

Ucos系統時鐘節拍詳解

我們以前在將這個作業系統在進行多工切換的時候,說過這樣的概念作業系統怎麼進行多工切換呢?首先它把這個時間進行分片,就是劃分為1片 1片的,比如說這個時間都以 10毫秒劃分為 1個片,在第乙個 10毫秒中執行乙個任務,在第二個 10毫秒中執行另外乙個任務,在第三個 10毫秒中執行另外乙個任務,這樣的話...

UCOSIII時鐘節拍

ucos裡,時鐘節拍就好比是人的心臟一樣重要。它對於cpu能順利在各任務間切換有著至關重要的作用。使用時鐘源有乙個特別需要注意的地方 使用者必須在多工系統啟動以後再開啟時鐘節拍器,也就是在呼叫osstart 之後。ucos中的時鐘節拍服務是通過在定時器中斷服務子程式中呼叫ostimetick 實現的...

ucos 時鐘節拍 Ucos系統學習之時鐘節拍

ucos 系統學習之時鐘節拍 我們以前在將這個作業系統在進行多工切換的時候,說過這樣的概念操作系 統怎麼進行多工切換呢?首先它把這個時間進行分片,就是劃分為 片片的,比如說這個時間都以 毫秒劃分為 個片,在第乙個 毫秒中執行乙個任務,在第二個 毫秒中執行另外乙個任務,在第三個 毫秒中執行另外乙個任務...