色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

RT-Thread定時器工作機制以及定時器的管理方式

RTThread物聯網操作系統 ? 來源:lq ? 2019-02-15 10:36 ? 次閱讀

前言

本文記錄RT-Thread時鐘相關知識,包括時鐘節拍、RT-Thread定時器工作機制以及定時器的管理方式,在定時器方面有硬件定時器和軟件定時器,這里不講硬件定時器,硬件定時器只需學習裸機時候的硬件定時器即可。后面進行實際的操作時采STM32L475VET6,RTT&正點原子聯合出品潘多拉開發板進行實驗。

一、時鐘節拍

任何操作系統都需要提供一個時鐘節拍,以供系統處理所有和時間有關的事件,如線程的延時、線程的時間片輪轉調度以及定時器超時等。時鐘節拍是特定的周期性中斷,這個中斷可以看做是系統心跳,中斷之間的時間間隔取決于不同的應用,一般是 1ms–100ms,時鐘節拍率越快,系統的額外開銷就越大,從系統啟動開始計數的時鐘節拍數稱為系統時間。

1、定義時鐘節拍大小

RT-Thread 中,時鐘節拍的長度可以根據 RT_TICK_PER_SECOND 的定義來調整,RT_TICK_PER_SECOND 在rtconfig.h里面定義,時鐘節拍的長度等于 1/RT_TICK_PER_SECOND 秒,如下是1個時鐘節拍為1ms:

1#defineRT_TICK_PER_SECOND1000//定義時鐘節拍,為1000時表示1000個tick每秒,一個tick為1ms

2、時鐘節拍的實現方式

時鐘節拍由配置為中斷觸發模式的硬件定時器產生。

在前面講移植RT-Thread的時候,修改board.c中,有如下函數:

1voidSysTick_Handler(void) 2{ 3/*enterinterrupt*/ 4rt_interrupt_enter(); 5 6rt_tick_increase(); 7 8/*leaveinterrupt*/ 9rt_interrupt_leave();10}

當中斷到來時,將調用一次rt_tick_increase();,而在中斷函數中調用 rt_tick_increase() 對全局變量 rt_tick 進行自加,如下代碼:

1/** 2*Thisfunctionwillnotifykernelthereisonetickpassed.Normally, 3*thisfunctionisinvokedbyclockISR. 4*/ 5voidrt_tick_increase(void) 6{ 7structrt_thread*thread; 8 9/*increasetheglobaltick*/10++rt_tick;1112/*checktimeslice*/13thread=rt_thread_self();1415--thread->remaining_tick;16if(thread->remaining_tick==0)17{18/*changetoinitializedtick*/19thread->remaining_tick=thread->init_tick;2021/*yield*/22rt_thread_yield();23}2425/*checktimer*/26rt_timer_check();27}

可以看到全局變量 rt_tick 在每經過一個時鐘節拍時,值就會加 1,rt_tick 的值表示了系統從啟動開始總共經過的時鐘節拍數,即系統時間。此外,每經過一個時鐘節拍時,都會檢查當前線程的時間片是否用完,以及是否有定時器超時。

注意:上面的中斷中的rt_timer_check()用于檢查系統硬件定時器鏈表,如果有定時器超時,將調用相應的超時函數。且所有定時器在定時超時后都會從定時器鏈表中被移除,而周期性定時器會在它再次啟動時被加入定時器鏈表。

3、獲取時鐘節拍

在RT-Thread中,全局變量rt_tick在每經過一個時鐘節拍時,值就會加 1,通過調用rt_tick_get會返回當前rt_tick的值,即可以獲取到當前的時鐘節拍值。此接口可用于記錄系統的運行時間長短,或者測量某任務運行的時間。

1/** 2*Thisfunctionwillreturncurrenttickfromoperatingsystemstartup 3* 4*@returncurrenttick 5*/ 6rt_tick_trt_tick_get(void) 7{ 8/*returntheglobaltick*/ 9returnrt_tick;10}11RTM_EXPORT(rt_tick_get);

二、軟件定時器

RT-Thread 的軟件定時器提供兩類定時器機制:第一類是單次觸發定時器,這類定時器在啟動后只會觸發一次定時器事件,然后定時器自動停止。第二類是周期觸發定時器,這類定時器會周期性的觸發定時器事件,直到用戶手動的停止,否則將永遠持續執行下去。軟件定時器的優先級為RT_TIMER_THREAD_PRIO。

1、開啟軟件定時宏

如果要開啟使用軟件定時器,需再rtconfig.h中打開軟件定時器的宏:

1#defineRT_USING_TIMER_SOFT//定義該宏可開啟軟件定時器,未定義則關閉

2、軟件定時器工作機制

(1)在 RT-Thread 定時器模塊中維護著兩個重要的全局變量:

(A)當前系統經過的 tick 時間 rt_tick(當硬件定時器中斷來臨時,它將加 1);(B)定時器鏈表 rt_timer_list。系統新創建并激活的定時器都會按照以超時時間排序的方式插入到rt_timer_list 鏈表中。

(2)如下圖所示,系統當前 tick 值為 20,在當前系統中已經創建并啟動了三個定時器,分別是定時時間為50 個tick的Timer1、100 個tick的 Timer2 和 500 個 tick 的 Timer3,這三個定時器分別加上系統當前時間rt_tick=20,從小到大排序鏈接rt_timer_list鏈表中,形成如圖所示的定時器鏈表結構。而rt_tick隨著硬件定時器的觸發一直在增長(每一次硬件定時器中斷來臨,rt_tick變量會加 1),50個tick以后,rt_tick從 20 增長到 70,與Timer1的timeout值相等,這時會觸發與Timer1定時器相關聯的超時函數,同時將 Timer1 從rt_timer_list鏈表上刪除。同理,100 個 tick 和 500 個 tick 過去后,與Timer2 和 Timer3 定時器相關聯的超時函數會被觸發,接著將 Time2 和 Timer3 定時器從rt_timer_list鏈表中刪除。

定時器鏈表插入示意圖(來源RT-Thread編程指南)

(3)如果系統當前定時器狀態在 10 個tick以后(rt_tick=30)有一個任務新創建了一個 tick 值為 300 的Timer4 定時器,由于 Timer4 定時器的timeout=rt_tick+300=330, 因此它將被插入到 Timer2 和 Timer3定時器中間,形成如下圖所示鏈表結構。

圖片占位 定時器鏈表插入示意圖(來源RT-Thread編程指南)

注意:所有定時器在定時超時后都會從定時器鏈表中被移除,而周期性定時器會在它再次啟動時被加入定時器鏈表。

3、動態創建軟件定時器函數

調用動態創建軟件定時器函數接口后,內核首先從動態內存堆中分配一個定時器控制塊,然后對該控制塊進行基本的初始化,函數如下:

1rt_timer_trt_timer_create(constchar*name,2void(*timeout)(void*parameter),3void*parameter,4rt_tick_ttime,5rt_uint8_tflag);

(1)入口參數

name:定時器的名稱。name 定時器的名稱void (timeout) (voidparameter):定時器超時函數指針(當定時器超時時,系統會調用這個函數,即定時器超時回調函數)。parameter:定時器超時函數的入口參數(當定時器超時時,調用超時回調函數會把這個參數做為入口參數傳遞給超時函數)。time:定時器的超時時間,單位是時鐘節拍。flag:定時器創建時的參數,支持的值包括單次定時、周期定時、硬件定時器、軟件定時器等(可以用 “或” 關系取多個值)。

(2)返回值:

RT_NULL:創建失敗(通常會由于系統內存不夠用而返回 RT_NULL)定時器的句柄:定時器創建成功時返回定時句柄。

(3)include/rtdef.h中定義了一些定時器相關的宏,通過如下4個宏或起來后賦給flag,來指定定時器類型:

1#defineRT_TIMER_FLAG_ONE_SHOT0x0/**

4、刪除動態定時器函數

當不再需要動態定時器時,可以將其刪除,執行如下函數之后系統會把這個定時器從rt_timer_list鏈表中刪除,然后釋放相應的定時器控制塊占有的內存:rt_err_t rt_timer_delete(rt_timer_t timer);

(1)入口參數:

timer:定時器句柄,指向要刪除的定時器。

(2)返回值:RT_EOK:刪除成功(如果參數 timer 句柄是一個 RT_NULL,將會導致一個 ASSERT 斷言)

5、靜態創建軟件定時器

靜態創建軟件定時器也就是《RT-Thread編程指南》里面所講的定時器初始化,如下面函數,使用該函數接口時會初始化相應的定時器控制塊,初始化相應的定時器名稱,定時器超時函數:

1voidrt_timer_init(rt_timer_ttimer,2constchar*name,3void(*timeout)(void*parameter),4void*parameter,5rt_tick_ttime,6rt_uint8_tflag);

(1)入口參數:

timer:定時器句柄,指向要初始化的定時器控制塊。name:定時器的名稱void (timeout) (voidparameter):定時器超時函數指針(當定時器超時時,系統會調用這個函數,即定時器超時回調函數)。parameter:定時器超時函數的入口參數(當定時器超時時,調用超時回調函數會把這個參數做為入口參數傳遞給超時函數)。time:定時器的超時時間,單位是時鐘節拍flag:定時器創建時的參數,支持的值包括單次定時、周期定時、硬件定時器、軟件定時器(可以用 “或” 關系取多個值)。

6、刪除靜態定時器函數

當不再需要靜態定時器時,可將它刪除,也就是《RT-Thread編程》指南里面所說的脫離定時器。脫離定時器時,系統會把定時器對象從內核對象容器中脫離,但是定時器對象所占有的內存不會被釋放:

1rt_err_trt_timer_detach(rt_timer_ttimer);

(1)入口參數:

timer:定時器句柄,指向要脫離的定時器控制塊。

(2)返回值:

RT_EOK:脫離成功。

7、啟動軟件定時器

前面講了定時器的創建,但創建好的定時器并不會立即開始工作,需要在調用啟動定時器函數接口后才開始工作,調用定時器啟動函數接口后,定時器的狀態將更改為激活狀態(RT_TIMER_FLAG_ACTIVATED),并按照超時順序插入到rt_timer_list隊列鏈表中,啟動函數如下:

1rt_err_trt_timer_start(rt_timer_ttimer);

(1)入口參數:

timer:定時器句柄,指向要啟動的定時器控制塊。

(2)返回值:

RT_EOK:啟動成功。

8、停止軟件定時器

啟動定時器以后,若想使它停止,可調用停止函數,調用定時器停止函數接口后,定時器狀態將更改為停止狀態(RT_TIMER_FLAG_DEACTIVATED),并從rt_timer_list鏈表中脫離出來不參與定時器超時檢查,函數如下:

1rt_err_trt_timer_stop(rt_timer_ttimer);

(1)入口參數:

timer:定時器句柄,指向要停止的定時器控制塊。

(2)返回值:

RT_EOK:成功停止定時器。RT_ERROR:timer 已經處于停止狀態。。

9、控制定時器

控制定時器函數接口可根據命令類型參數,來查看或改變定時器的設置,函數如下:

1rt_err_trt_timer_control(rt_timer_ttimer,intcmd,void*arg);

(1)入口參數:

timer:定時器句柄,指向要停止的定時器控制塊。cmd:用于控制定時器的命令,當前支持四個命令,分別是設置定時時間,查看定時時間,設置單次觸發,設置周期觸發。arg:與 cmd 相對應的控制命令參數比如,cmd 為設定超時時間時,就可以將超時時間參數通過arg 進行設定。

(2)函數參數 cmd 支持的命令:

1#defineRT_TIMER_CTRL_SET_TIME0x0/*設置定時器超時時間*/2#defineRT_TIMER_CTRL_GET_TIME0x1/*獲得定時器超時時間*/3#defineRT_TIMER_CTRL_SET_ONESHOT0x2/*設置定時器為單次定時器*/4#defineRT_TIMER_CTRL_SET_PERIODIC0x3/*設置定時器為周期型定時器*/

(3)返回值:

RT_EOK:成功

三、基于STM32的軟件定時器應用示例

前面講了很多RT-Thread定時器方面的東西,實際上,我如果用RT-Thread的定時相關接口的話,一般都是用軟件定時器,硬件定時器通常我們都是自己像以前學習裸機那邊去用。接下來我們來實際使用一些RT-Thread的軟件定時器,使用RTT&正點原子聯合出品的潘多拉開發板來實驗:(1)動態創建一個軟件定時器,周期執行,實現定時器超時時打印出當前獲取滴答定時器的計數值以及回調函數執行次數。(2)動態創建一個線程,通過按下KEY0來啟動軟件定時器,按下KEY1來停止軟件定時器。

1、實現代碼

1#include"main.h" 2#include"board.h" 3#include"rtthread.h" 4#include"data_typedef.h" 5#include"delay.h" 6#include"led.h" 7#include"key.h" 8 9voidrt_sw_timer1(void); 10voidkey_start(void); 11 12staticrt_timer_ttimer1;/*timer1句柄*/ 13intg_sw_timer1_count=0; 14 15intmain(void) 16{ 17rt_sw_timer1(); 18key_start(); 19 20return0; 21} 22 23/************************************************************** 24函數名稱:rt_sw_timer1_callback 25函數功能:軟件定時timer1回調函數 26輸入參數:parameter:回調函數的入口參數,當定時器超時, 27調用回調函數會把這個參數做為入口參數傳遞給回調函數。 28返回值:無 29備注:無 30**************************************************************/ 31voidrt_sw_timer1_callback(void*parameter) 32{ 33u32tick_num1; 34 35tick_num1=(u32)rt_tick_get();/*獲取滴答定時器的計數值*/ 36g_sw_timer1_count++; 37 38rt_kprintf("tick_num1=%d\r\n",tick_num1); 39rt_kprintf("enterrt_sw_timer_callback,g_sw_timer1_count=%d\r\n",g_sw_timer1_count); 40} 41 42/************************************************************** 43函數名稱:rt_sw_timer1 44函數功能:軟件定時timer1動態創建函數 45輸入參數:無 46返回值:無 47備注:無 48**************************************************************/ 49voidrt_sw_timer1(void) 50{ 51/*動態創建軟件定時器,周期執行*/ 52timer1=rt_timer_create("timer1", 53rt_sw_timer1_callback, 54RT_NULL, 555000,/*周期為5000個時鐘節拍*/ 56RT_TIMER_FLAG_SOFT_TIMER|RT_TIMER_FLAG_PERIODIC);/*軟件定時器,周期執行*/ 57} 58 59/************************************************************** 60函數名稱:key_thread_entry 61函數功能:key線程入口函數 62輸入參數:parameter:線程入口函數參數 63返回值:無 64備注:無 65**************************************************************/ 66voidkey_thread_entry(void*parameter) 67{ 68u8key; 69 70while(1) 71{ 72key=key_scan(0); 73if(key==KEY0_PRES) 74{ 75rt_timer_start(timer1); 76rt_kprintf("RT-Threadswtimer1satrt\r\n"); 77} 78elseif(key==KEY1_PRES) 79{ 80rt_timer_stop(timer1); 81rt_kprintf("RT-Threadswtimer1stop\r\n"); 82} 83rt_thread_mdelay(1); 84} 85 86} 87 88/************************************************************** 89函數名稱:key_start 90函數功能:創建并啟動key線程 91輸入參數:無 92返回值:無 93備注:無 94**************************************************************/ 95voidkey_start(void) 96{ 97rt_thread_tkey_thread=RT_NULL;; 98 99/*動態創建KEY線程*/100key_thread=rt_thread_create("key",101key_thread_entry,102RT_NULL,103512,/*線程棧大小,單位是字節*/104RT_THREAD_PRIORITY_MAX/2-5,/*優先級*/10550);/*50個時鐘節拍*/106/*創建KEY線程成功,則啟動線程*/107if(key_thread!=RT_NULL)108{109rt_thread_startup(key_thread);110}111}

2、觀察FinSH

(1)開機之后,等待超過軟件定時配置的周期過后,還是沒有打印出回調函數要打印的信息,說明回調函數沒有被執行,為什么呢?因為我們創建軟件定時器之后還沒啟動軟件定時器,我們輸入list_timer回車,可以看到timer1是處于deactivated狀態。

(2)按下KEY0按鍵,啟動軟件定時器,可觀察到每個5s打印一次當前tick的數值和回調函數的執行次數,將前后兩次tick的數值相減大概為5006ms,再次輸入list_timer,可看到timer1為activated狀態。

(3)按下KEY1按鍵,停止軟件定時器,停止打印回調函數要打印的信息,輸入list_timer,可以看到timer1為deactivated狀態。

四、軟件定時器設計注意事項

在設計日軟件定時器時,超時回調函數的要求嚴格:執行時間應該盡量短,執行時不應導致當前上下文掛起、等待。例如在中斷上下文中執行的超時函數它不應該試圖去申請動態內存、釋放動態內存等,也不允許調用rt_thread_delay()等導致上下文掛起的 API 接口。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 定時器
    +關注

    關注

    23

    文章

    3246

    瀏覽量

    114733
  • 函數
    +關注

    關注

    3

    文章

    4329

    瀏覽量

    62575
  • 時鐘管理
    +關注

    關注

    0

    文章

    16

    瀏覽量

    8348

原文標題:社區新人的RT-Thread學習筆記2——時鐘管理

文章出處:【微信號:RTThread,微信公眾號:RTThread物聯網操作系統】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    rt-thread 驅動篇(八)hwtimer 重載算法優化

    區別于 rt-thread 內核實現的兩種定時器,這種定時器依賴芯片內置的定時器外設,依靠穩定高速的晶振實現精確定時,可以實現
    的頭像 發表于 06-23 10:10 ?2997次閱讀
    <b class='flag-5'>rt-thread</b> 驅動篇(八)hwtimer 重載算法優化

    RT-Thread記錄(四、RTT時鐘節拍和軟件定時器

    RT-Thread第4課,聽聽 RT-Thread 的心跳,再學習一下基于心跳的軟件定時器使用。
    的頭像 發表于 06-20 11:50 ?7764次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(四、RTT時鐘節拍和軟件<b class='flag-5'>定時器</b>)

    rt-thread優化系列(三)軟定時器定時漂移問題分析

    所謂軟定時器,是由一個線程運行維護的定時器列表。由線程調用定時器回調函數。
    的頭像 發表于 06-23 09:35 ?3492次閱讀

    【每日一練】RT-Thread Nano-ADC(時鐘管理之軟件定時器)-3軟件定時器內核代碼分析(第十七節學習視頻)

    )【每日一練】RT-Thread Nano-ADC(時鐘管理之軟件定時器)-1軟件定時器創建(第十五節學習視頻)【每日一練】RT-Thread
    發表于 06-02 10:32

    【每日一練】課程實踐-基于RT-Thread內核定時器的電壓采集

    是基于對何老師課程的理解,做一個使用內核的定時器來周期獲取電壓的采樣值,以這個實踐來鞏固這段時間學習到的RT-Thread的知識,借這篇文章分享課程感悟,幫助更多想學習RT-Thread的小伙伴。二
    發表于 06-24 11:21

    RT-Thread提供了怎樣的定時器操作函數以及如何使用它們呢

    rt_tick 的值表示了系統從啟動到現在共經過的時鐘節拍個數。定時器工作機制RT-Thread 提供的
    發表于 04-02 11:41

    請問下rt-thread是否有更高定時器對象的實現

    查看rt-thread的源碼和相關文檔,已經了解到了rt-thread定時器的實現原理,如文檔介紹,該定時器的精度并不很高,請問下,r-thread
    發表于 05-09 11:40

    如何利用RT-Thread的接口去訪問硬件定時器設備呢

    間達到500ms后,框架會調用用戶預先設置好的回調函數。訪問硬件定時器設備應用程序通過 RT-Thread 提供的 I/O 設備管理接口來訪問硬件定時器設備,相關接口如下所示:查找
    發表于 07-22 10:31

    RT-Thread系統定時器管理相關資料介紹

    1、RT-Thread系統定時器管理  定時器,是指從指定的時刻開始,經過一個指定時間,然后觸發一個事件,類似定個時間提醒第二天能夠按時起床
    發表于 09-14 16:21

    RT-Thread軟件定時器怎么獲取定時器的狀態?

    rt-thread 軟件定時器怎么獲取定時器的狀態 比如獲取當前定時器是運行狀態,還是停止狀態 ,自己加flag的方法除外哈
    發表于 01-31 15:19

    STM32定時器-基本定時器

    目錄定時器分類基本定時器功能框圖講解基本定時器功能時鐘源計數時鐘計數自動重裝載寄存
    發表于 11-23 18:21 ?31次下載
    STM32<b class='flag-5'>定時器</b>-基本<b class='flag-5'>定時器</b>

    詳細剖析Linux和RTOS(RT-Thread)的時鐘和定時器的使用

    Linux發燒友1.RTOS篇1.1RT-Thread簡介1.2時鐘管理1.2.1時鐘節拍1.3獲取系統節拍1.4定時器分類1.5定時器源碼分析1.6
    發表于 01-17 09:31 ?4次下載
    詳細剖析Linux和RTOS(<b class='flag-5'>RT-Thread</b>)的時鐘和<b class='flag-5'>定時器</b>的使用

    RT-Thread學習筆記 -- 時鐘管理

    RT-Thread學習筆記 – 時鐘管理軟件硬件定時器區別1.定時器分為硬件定時器和軟件定時器
    發表于 01-17 09:53 ?1次下載
    <b class='flag-5'>RT-Thread</b>學習筆記 -- 時鐘<b class='flag-5'>管理</b>

    RT-Thread驅動篇:hwtimer重載值算法

    區別于 rt-thread 內核實現的兩種定時器,這種定時器依賴芯片內置的定時器外設,依靠穩定高速的晶振實現精確定時,可以實現
    的頭像 發表于 04-01 10:06 ?1771次閱讀

    定時器工作方式介紹

    定時器是計算機和嵌入式系統中常見的一種硬件模塊,用于實現定時和計數功能。定時器工作方式通常由一組寄存來控制,這些寄存
    的頭像 發表于 07-12 10:29 ?907次閱讀
    主站蜘蛛池模板: music radio在线收听| 久久综合香蕉久久久久久久| 男生扒开美女尿口戳戳| 亚洲国产在线午夜视频无| JAVASCRIPTJAVA水多多| 久久艹综合| 午夜免费福利片| 爱看吧孕妇网| 麻豆沈芯语| 伊人草久久| 国产中文字幕一区| 十八禁啪啦啪漫画| www.绿巨人| 蜜臀AV人妻久久无码精品麻豆| 亚洲欧美国产综合在线一区| 囯产少妇BBBBBB高潮喷水一| 男人日女人的b| 中国女人hd| 久草在线草a免费线看| 亚色九九九全国免费视频| 沟沟人体一区二区| 欧美在线激情| 999久久国产精品免费人妻| 久9视频这里只有精品123| 亚洲 欧美 国产 综合不卡| 囯产精品久久久久久久久免费蜜桃 | 就去色一色| 亚洲日本欧美产综合在线| 国产精品免费观看视频| 色婷婷AV99XX| 哒哒哒影院在线观看免费高清| 欧美激情一区二区三区视频| 最近日本字幕免费高清| 久久不卡免费视频| 艳妇臀荡乳欲伦岳TXT下载| 国产自拍视频在线一区| 雪恋电影完整版免费观看| 国产欧美精品一区二区三区-老狼| 色婷婷AV国产精品欧美毛片| 成人人猿泰山| 色爱AV综合区|