軟件定時器,是基於系統Tick時鐘中斷且由軟件來模擬的定時器,當通過設定的Tick時鐘計數值後會觸發用戶定義的回調函數。定時精度與系統Tick時鐘的週期有關。編程
硬件定時器受硬件的限制,數量上不足以知足用戶的實際需求,所以爲了知足用戶需求,提供更多的定時器, Huawei LiteOS操做系統提供軟件定時器功能。函數
軟件定時器擴展了定時器的數量,容許建立更多的定時業務。ui
軟件定時器功能上支持:操作系統
軟件定時器是系統資源,在模塊初始化的時候已經分配了一塊連續的內存,系統支持的最大定時器個數由los_config.h中的LOSCFG_BASE_CORE_SWTMR_LIMIT宏配置。指針
軟件定時器使用了系統的一個隊列和一個任務資源,軟件定時器的觸發遵循隊列規
則,先進先出。定時時間短的定時器老是比定時時間長的靠近隊列頭,知足優先被觸發的準則。code
軟件定時器以Tick爲基本計時單位,當用戶建立並啓動一個軟件定時器時, HuaweiLiteOS會根據當前系統Tick時間及用戶設置的定時間隔肯定該定時器的到期Tick時間,並將該定時器控制結構掛入計時全局鏈表。blog
當Tick中斷到來時,在Tick中斷處理函數中掃描軟件定時器的計時全局鏈表,看是否有定時器超時,如有則將超時的定時器記錄下來。Tick中斷處理函數結束後,軟件定時器任務(優先級爲最高)被喚醒,在該任務中調用以前記錄下來的定時器的超時回調函數。接口
定時器狀態隊列
系統在定時器模塊初始化的時候將系統中全部定時器資源初始化成該狀態。事件
在未使用狀態下調用LOS_SwtmrCreate接口或者啓動後調用LOS_SwtmrStop接口後,定
時器將變成該狀態。
在定時器建立後調用LOS_SwtmrStart接口,定時器將變成該狀態,表示定時器運行時的狀態。
定時器模式
Huawei LiteOS的軟件定時器提供二類定時器機制:
Huawei LiteOS系統中的軟件定時器模塊爲用戶提供下面幾種功能,下面具體的API詳見軟件定時器對外接口手冊。
功能分類 | 接口名 | 描述 |
---|---|---|
建立、刪除定時器 | LOS_SwtmrCreate | 建立定時器 |
- | LOS_SwtmrDelete | 刪除定時器 |
啓動、中止定時器 | LOS_SwtmrStart | 啓動定時器 |
- | LOS_SwtmrStop | 中止定時器 |
得到軟件定時器剩餘Tick數 | LOS_SwtmrTimeGet | 得到軟件定時器剩餘Tick數 |
軟件定時器的典型開發流程:
對軟件定時器存在失敗可能性的操做,包括建立、刪除、暫停、重啓定時器等等,均須要返回對應的錯誤碼,以便快速定位錯誤緣由。
序 號 | 定義 | 實際數值 | 描述 | 參考解決方案 |
---|---|---|---|---|
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)
在下面的例子中,演示以下功能:
單次軟件定時器,週期軟件定時器使用方法。
代碼實現以下:
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); }
獲得的結果爲: