Tick工作原理其實就是硬件定時器的工作原理,1個系統tick就代表一個定時器硬件中斷。定時器的工作原理很簡單,就是內部有一個遞減的計數器,當減到0時產生一個中斷,如圖 1-1所示:
圖 1-1定時器工作原理
假設定時器模塊的輸入頻率是1MHz,系統定義的1S內tick數是100,也就是100Hz,可以計算出遞減計數器要設置的值為1MHz/100Hz=10000??梢钥闯鲞f減計數器相當于一個分頻器,輸入端每來一個脈沖,其值就減去1,當減到0時產生一個中斷,同時其值自動重載成10000,如此循環下去。
系統獲取時間相關接口是基于tick來工作的,但是這是有誤差的,如圖 2-1所示:
圖 2-1系統獲取時間
虛線表示下一個tick中斷還未產生,如果此時來獲取時間,獲取到的時間只是之前tick累計的時間。假設tick中斷產生時刻和獲取時間那一時刻之間的跨度是4ms,那么獲取的時間就有4ms的誤差,高精度時鐘就是為了消除這種誤差而誕生的。
上述誤差產生的根本原因是沒有將tick中斷產生時刻和獲取時間那一時刻之間的跨度更新到時間里去,如果計算出這段時間并加到獲取的時間里去就可以校正獲取的時間了。結合圖 1-1和圖 2-1,基本的校正原理如下所述:
1個tick時間等價于遞減計數器的初始值,假設是10000,也就是說遞減10000次相當于過了一個tick時間
用1000 * 1000 * 1000 / 10000得到遞減一次的時間,單位是ns
用計數器初始值減去獲取時間那一時刻計數器中的值,就得到了獲取時間時刻計數器已經遞減的次數
用遞減一次的時間 *遞減的次數,就得到tick中斷產生時刻和獲取時間那一時刻之間的時間跨度
當系統是多核時,系統產生一個由CPU0來處理的tick中斷,當CPU0還沒有更新整個系統的tick數時,這時CPU1來獲取時間,按照基本原理的計算之后還要加上一個tick的時間才是正確的。
程序清單 4-1
VOID bspTickHighResolution (struct timespec *ptv)
{
REGISTER UINT32 uiCntCur, uiDone;
uiCntCur = (UINT32)timerGetCnt(4);
uiDone = GuiFullCnt - uiCntCur;
/*
*檢查是否有 TICK中斷請求
*/
if (rSRCPND & BIT_TIMER4) {
/*
*這里由于 TICK沒有及時更新,所以需要重新獲取并且加上一個 TICK的時間
*/
uiCntCur = (UINT32)timerGetCnt(4);
uiDone = GuiFullCnt - uiCntCur;
if (uiCntCur != 0) {
uiDone += GuiFullCnt;
}
}
ptv->tv_nsec += (LONG)((Gui64NSecPerCnt7 * uiDone) >> 7);
if (ptv->tv_nsec >= 1000000000) {
ptv->tv_nsec -= 1000000000;
ptv->tv_sec++;
}
}
GuiFullCnt表示遞減計數器的初始值,也就是產生1個tick時間的計數值;Gui64NSecPerCnt7表示遞減一次的時間,但是這個時間被擴大了128倍,目的是為了提高計算精度
uiDone表示獲取時間時刻計數器已經遞減的次數,uiCntCur表示獲取時間時刻計數器當前值
if (rSRCPND & BIT_TIMER4)用于特殊情況的判斷,條件成立表示系統的tick數還沒來得及更新,不成立表示系統的tick數已經被更新
當uiCntCur=0時,表示tick中斷剛剛產生,這時uiDone就已經代表一個tick的計數值,所以就無需再加上一個tick的計數值了
最后將修正后的時間賦值給tv_nsec成員
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。