定時器顧名思義就是在一段時間後會被啟動,他的運作可以是一次性的或是週期性(持續性)的,定時器也隨時可以被停止。
定時器到期的時候,將運行在軟體中斷的執行緒,所以在這段時間不可以進行任何阻斷式(blocking)的操作。
util 模組包含了一組抽象的TI-RTOS 定時器函式,如下所式:
接著我們來看範例程式中如何使用定時器。
看程式碼之前,TI 文件上有整理一張流程圖
首先可以看到有兩條直線,
他們代表兩個執行緒,
分別是SimplePeripheral的任務(Task)和軟體中斷的執行緒(Swi)
這篇文章只會先看到流程圖中的數字1和數字2這兩個區塊,
數字3下一篇文章再來看,
稍微喵一下流程圖後就接著看程式碼。
// 參考流程圖中的數字1
// 首先會先在SimplePeripheral的任務中建立定時器
static void SimplePeripheral_init(void)
{
...
// 在任務的初始化階段,先建立"clkPeriodic"定時器(可以想成這個定時器的名字叫做"clkPeriodic")
// 第二個參數是一個函式指標,當時間到的時候,會在軟體中斷的執行緒中執行這段程式碼
// 第三個參數是超時的時間,單位為毫秒
// 第四個參數是延遲時間,單位為毫秒,如果設成0,則定時器到期時間就是第三個參數所設的時間
// 第五個參數是一個布林值,True代表建立之後馬上啟動,False則要等到呼叫Util_startClock()才會啟動
// 第六個參數則是當定時器到期呼叫第二個參數所設的函式時,所帶入的參數,
// 範例程式所存入的值其實是 SP_PERIODIC_EVT
Util_constructClock(&clkPeriodic, SimplePeripheral_clockHandler,
SP_PERIODIC_EVT_PERIOD, 0, true, (UArg)&argPeriodic);
...
}
// 在SimplePeripheral 中,
// "clkPeriodic"定時器在藍牙連結建立完成時啟動
// "clkPeriodic"定時器在藍牙連結斷開時停止
static void SimplePeripheral_processGapMessage(gapEventHdr_t *pMsg)
{
switch(pMsg->opcode)
{
// 藍牙連結建立完成
case GAP_LINK_ESTABLISHED_EVENT:
{
...
// 啟動"clkPeriodic"定時器
Util_startClock(&clkPeriodic);
...
}
// 藍牙連結斷開
case GAP_LINK_TERMINATED_EVENT:
{
...
// 停止"clkPeriodic"定時器
Util_stopClock(&clkPeriodic);
...
}
...
}
// 參考流程圖中的數字2
// 參考剛剛建立定時器時候的第二個和第五個參數
// 當時間到的時候,就會呼叫SimplePeripheral_clockHandler這個函式
// 並且把 SP_PERIODIC_EVT 當作參數代入
static void SimplePeripheral_clockHandler(UArg arg)
{
spClockEventData_t *pData = (spClockEventData_t *)arg;
// 這邊會取出參數,判斷是否為定時器的事件
if (pData->event == SP_PERIODIC_EVT)
{
// 因為現在這段程式是執行在軟體中斷的執行緒,
// 所以我們不可以在這邊做太多事情,
// 只把定時器到期的這個事件放到佇列(Queue)中即可。(Queue的東西下一篇會說)
SimplePeripheral_enqueueMsg(SP_PERIODIC_EVT, NULL);
}
}