任何的作業系統都需要提供乙個時鐘節拍,以供系統處理如延時,超時等與時間相關的事件(時基)。
系統時鐘節拍是特定的週期性中斷,中斷間的時鐘間隔取決於不同的應用。(設定時基,一般是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 系統學習之時鐘節拍 我們以前在將這個作業系統在進行多工切換的時候,說過這樣的概念操作系 統怎麼進行多工切換呢?首先它把這個時間進行分片,就是劃分為 片片的,比如說這個時間都以 毫秒劃分為 個片,在第乙個 毫秒中執行乙個任務,在第二個 毫秒中執行另外乙個任務,在第三個 毫秒中執行另外乙個任務...