liteos軟件定時器(十)

1 概述

1.1 基本概念

軟件定時器,是基於系統Tick時鐘中斷且由軟件來模擬的定時器,當通過設定的Tick時鐘計數值後會觸發用戶定義的回調函數。定時精度與系統Tick時鐘的週期有關。編程

硬件定時器受硬件的限制,數量上不足以知足用戶的實際需求,所以爲了知足用戶需求,提供更多的定時器, Huawei LiteOS操做系統提供軟件定時器功能。函數

軟件定時器擴展了定時器的數量,容許建立更多的定時業務。ui

軟件定時器功能上支持:操作系統

  • 靜態裁剪:能經過宏關閉軟件定時器功能。
  • 軟件定時器建立。
  • 軟件定時器啓動。
  • 軟件定時器中止。
  • 軟件定時器刪除。
  • 軟件定時器剩餘Tick數獲取

1.2 運做機制

軟件定時器是系統資源,在模塊初始化的時候已經分配了一塊連續的內存,系統支持的最大定時器個數由los_config.h中的LOSCFG_BASE_CORE_SWTMR_LIMIT宏配置。指針

軟件定時器使用了系統的一個隊列和一個任務資源,軟件定時器的觸發遵循隊列規
則,先進先出。定時時間短的定時器老是比定時時間長的靠近隊列頭,知足優先被觸發的準則。code

軟件定時器以Tick爲基本計時單位,當用戶建立並啓動一個軟件定時器時, HuaweiLiteOS會根據當前系統Tick時間及用戶設置的定時間隔肯定該定時器的到期Tick時間,並將該定時器控制結構掛入計時全局鏈表。blog

當Tick中斷到來時,在Tick中斷處理函數中掃描軟件定時器的計時全局鏈表,看是否有定時器超時,如有則將超時的定時器記錄下來。Tick中斷處理函數結束後,軟件定時器任務(優先級爲最高)被喚醒,在該任務中調用以前記錄下來的定時器的超時回調函數。接口

定時器狀態隊列

  • OS_SWTMR_STATUS_UNUSED(未使用)

系統在定時器模塊初始化的時候將系統中全部定時器資源初始化成該狀態。事件

  • OS_SWTMR_STATUS_CREATED(建立未啓動/中止)

在未使用狀態下調用LOS_SwtmrCreate接口或者啓動後調用LOS_SwtmrStop接口後,定
時器將變成該狀態。

  • OS_SWTMR_STATUS_TICKING(計數)

在定時器建立後調用LOS_SwtmrStart接口,定時器將變成該狀態,表示定時器運行時的狀態。

定時器模式
Huawei LiteOS的軟件定時器提供二類定時器機制:

  • 第一類是單次觸發定時器,這類定時器在啓動後只會觸發一次定時器事件,而後定時器自動刪除。
  • 第二類是週期觸發定時器,這類定時器會週期性的觸發定時器事件,直到用戶手動地中止定時器,不然將永遠持續執行下去

2. 開發指導

2.1 使用場景

  • 建立一個單次觸發的定時器,超時後執行用戶自定義的回調函數。
  • 建立一個週期性觸發的定時器,超時後執行用戶自定義的回調函數。

2.2 功能

Huawei LiteOS系統中的軟件定時器模塊爲用戶提供下面幾種功能,下面具體的API詳見軟件定時器對外接口手冊。

功能分類 接口名 描述
建立、刪除定時器 LOS_SwtmrCreate 建立定時器
- LOS_SwtmrDelete 刪除定時器
啓動、中止定時器 LOS_SwtmrStart 啓動定時器
- LOS_SwtmrStop 中止定時器
得到軟件定時器剩餘Tick數 LOS_SwtmrTimeGet 得到軟件定時器剩餘Tick數

3. 開發流程

軟件定時器的典型開發流程:

  1. 配置軟件定時器。
  • 確認配置項LOSCFG_BASE_CORE_SWTMR和LOSCFG_BASE_IPC_QUEUE
    爲YES打開狀態;
  • 配置LOSCFG_BASE_CORE_SWTMR_LIMIT最大支持的軟件定時器數;
  • 配置OS_SWTMR_HANDLE_QUEUE_SIZE軟件定時器隊列最大長度;
  1. 建立定時器LOS_SwtmrCreate。
  • 建立一個指定計時時長、指定超時處理函數、指定觸發模式的軟件定時器;
  • 返回函數運行結果,成功或失敗;
  1. 啓動定時器LOS_SwtmrStart。
  2. 得到軟件定時器剩餘Tick數LOS_SwtmrTimeGet。
  3. 中止定時器LOS_SwtmrStop。
  4. 刪除定時器LOS_SwtmrDelete。

4. 軟件定時器錯誤碼

對軟件定時器存在失敗可能性的操做,包括建立、刪除、暫停、重啓定時器等等,均須要返回對應的錯誤碼,以便快速定位錯誤緣由。

序 號 定義 實際數值 描述 參考解決方案
1 LOS_ERRNO_SWTMR_PTR_NULL 0x02000300 軟件定時器回調函數爲空 定義軟件定時器回調函數
2 LOS_ERRNO_SWTMR_INTERVAL_NOT_SUITD 0x02000301 軟件定時器間隔時間爲0 從新定義間隔時間
3 LOS_ERRNO_SWTMR_MODE_INVALI D 0x02000302 不正確的軟件定時器模式 確認軟件定時器模式,範圍爲[0,2]
4 LOS_ERRNO_SWTMR_RET_PTR_NULL 0x02000303 軟件定時器ID指針入參爲NULL 定義ID變量,傳入指針
5 LOS_ERRNO_SWTMR_MAXSIZE 0x02000304 軟件定時器個數超過最大值 從新定義軟件定時器最大個數,或者等待一個軟件定時器釋放資源
6 LOS_ERRNO_SWTMR_ID_INVALID 0x02000305 不正確的軟件定時器ID入參 確保入參合法
7 LOS_ERRNO_SWTMR_NOT_CREATED 0x02000306 軟件定時器未建立 建立軟件定時器
8 LOS_ERRNO_SWTMR_NO_MEMORY 0x02000307 軟件定時器鏈表建立內存不足 申請一塊足夠大的內存供軟件定時器使用
9 LOS_ERRNO_SWTMR_MAXSIZE_INVALID 0x02000308 不正確的軟件定時器個數最大值 從新定義該值
10 LOS_ERRNO_SWTMR_HWI_ACTIVE 0x02000309 在中斷中使用定時器 修改源代碼確保不在中斷中使用
11 LOS_ERRNO_SWTMR_HANDLER_POOL_NO_MEM 0x0200030a membox內存不足 擴大內存
12 LOS_ERRNO_SWTMR_QUEUE_CREATE_FAILED 0x0200030b 軟件定時器隊列建立失敗 檢查用以建立隊列的內存是否足夠
13 LOS_ERRNO_SWTMR_TASK_CREATE_FAILED 0x0200030c 軟件定時器任務建立失敗 檢查用以建立軟件定時器任務的內存是否足夠並從新建立
14 LOS_ERRNO_SWTMR_NOT_STARTED 0x0200030d 未啓動軟件定時器 啓動軟件定時器
15 LOS_ERRNO_SWTMR_STATUS_INVALID 0x0200030e 不正確的軟件定時器狀態 檢查確認軟件定時器狀態
16 LOS_ERRNO_SWTMR_SORTLIST_NULL null 暫無 該錯誤碼暫不使用
17 LOS_ERRNO_SWTMR_TICK_PTR_NULL 0x02000310 用以獲取軟件定時器超時tick數的入參指針爲NULL 建立一個有效的變量

錯誤碼定義:錯誤碼是一個32位的存儲單元, 31~24位表示錯誤等級, 23~16位表示錯誤碼標誌, 15~8位表明錯誤碼所屬模塊, 7~0位表示錯誤碼序號,以下

#define LOS_ERRNO_OS_NORMAL(MID,ERRNO) \
(LOS_ERRTYPE_NORMAL | LOS_ERRNO_OS_ID | ((UINT32)(MID) << 8) | (ERRNO))
LOS_ERRTYPE_NORMAL :Define the error level as critical
LOS_ERRNO_OS_ID :OS error code flag.
MID:OS_MOUDLE_ID
ERRNO:error ID number

例如:

#define LOS_ERRNO_SWTMR_PTR_NULL \
LOS_ERRNO_OS_ERROR(LOS_MOD_SWTMR, 0x00)

5. 編程實例

5.1 實例描述

在下面的例子中,演示以下功能:

  1. 軟件定時器建立、啓動、刪除、暫停、重啓操做。
  2. 單次軟件定時器,週期軟件定時器使用方法。

    5.2 編程示例

    前提條件:
  • 在los_config.h中,將LOSCFG_BASE_CORE_SWTMR配置項打開。
  • 配置好LOSCFG_BASE_CORE_SWTMR_LIMIT最大支持的軟件定時器數。
  • 配置好OS_SWTMR_HANDLE_QUEUE_SIZE軟件定時器隊列最大長度。

代碼實現以下:

void Timer1_Callback(uint32_t arg); // callback fuction
void Timer2_Callback(uint32_t arg);
UINT32 g_timercount1 = 0;
UINT32 g_timercount2 = 0;
void Timer1_Callback(uint32_t arg)//回調函數1
{
    unsigned long tick_last1;
    g_timercount1++;
    tick_last1=(UINT32)LOS_TickCountGet();//獲取當前Tick數
    dprintf("g_timercount1=%d\n",g_timercount1);
    dprintf("tick_last1=%d\n",tick_last1);
}
void Timer2_Callback(uint32_t arg)//回調函數2
{
    unsigned long tick_last2;
    tick_last2=(UINT32)LOS_TickCountGet();
    g_timercount2 ++;
    dprintf("g_timercount2=%d\n",g_timercount2);
    dprintf("tick_last2=%d\n",tick_last2);
}
void Timer_example (void) {
    UINT16 id1;
    UINT16 id2;// timer id
    UINT32 uwTick;
    /*建立單次軟件定時器,Tick數爲1000,啓動到1000Tick數時執行回調函數1 */
    LOS_SwtmrCreate (1000, LOS_SWTMR_MODE_ONCE,Timer1_Callback,&id1,1);
    /*建立週期性軟件定時器,每100Tick數執行回調函數2 */
    LOS_SwtmrCreate(100,LOS_SWTMR_MODE_PERIOD,Timer2_Callback,&id2,1);
    dprintf("create Timer1 success\n");
    LOS_SwtmrStart (id1); //啓動單次軟件定時器
    dprintf("start Timer1 sucess\n");
    LOS_TaskDelay(200);//延時200Tick數
    LOS_SwtmrTimeGet(id1,&uwTick);//得到單次軟件定時器剩餘Tick數
    dprintf("uwTick =%d\n",uwTick);
    LOS_SwtmrStop(id1);//中止軟件定時器
    dprintf("stop Timer1 sucess\n");
    LOS_SwtmrStart(id1);
    LOS_TaskDelay(1000);
    LOS_SwtmrDelete(id1);//刪除軟件定時器
    dprintf("delete Timer1 sucess\n");
    LOS_SwtmrStart(id2);//啓動週期性軟件定時器
    dprintf("start Timer2\n");
    LOS_TaskDelay(1000);
    LOS_SwtmrStop(id2);
    LOS_SwtmrDelete(id2);
}

5.3 結果驗證

獲得的結果爲:

相關文章
相關標籤/搜索