1. 程式人生 > >uCOS的軟體定時器、uCOS時鐘節拍和滴答定時器的關係

uCOS的軟體定時器、uCOS時鐘節拍和滴答定時器的關係

uCOS2.81後的版本中有軟體定時器的概念,如果要開啟定時器任務,需要在OS_CFG.H檔案中 #define  OS_TMR_EN                 1

軟體定時器其實跟硬體中斷是相似的,定時時間到了,就執行一次回撥函式,雖然好用,但是也會降低系統的實時性。
軟體定時器也需要一個時鐘節拍驅動,這個驅動也是由硬體實現的,一般使用uCOS中的任務延時節拍驅動來驅動軟體定時器,每個時鐘節拍OSTmrCtr(全域性變數,初始值為0)加1,當OSTmrCtr的值等於OS_TICKS_PER_SEC /OS_TMR_CFG_TICKS_PER_SEC(前者是ucos節拍頻率,後者是軟體定時器的節拍頻率,相當於分頻)時,呼叫函式OSTmrSignl()函式,傳送訊號量OSTmrSemSignal(初始值0,決定軟體定時器掃描任務OSTmr_Task的執行),也就是說,對軟體定製器的處理不在時鐘節拍中斷函式中執行,而是以發生訊號量的方式啟用任務OSTmr_Task,任務OSTmr_Task對定時器進行檢測,包括定時器定時完成的判斷,回撥函式的執行。

 舉例來講,ucos中的OS_TICKS_PER_SEC設定值為1000(最大),OS_TMR_CFG_TICKS_PER_SEC為100,則可知uCOS的節拍時間為1ms,軟體定時器的節拍時間為1000/100*1=10ms

 在軟體定時器的生成函式中:


OS_TMR  *OSTmrCreate (INT32U           dly,
                      INT32U           period,
                      INT8U            opt,
                      OS_TMR_CALLBACK  callback,
                      void            *callback_arg,
                      INT8U           *pname,
                      INT8U           *perr)
其中dly表示第一次延時時間節拍數(軟體定時器節拍,不是ucos的節拍)
period表示重複節拍數,如果設定dly為10,period為20,opt設定OS_TMR_OPT_PERIODIC,則表示這是1個重複執行軟體定時器,第一次執行定時時間為10x10=100ms,以後每隔20x10=200ms的間隔時間執行回撥函式。

 

uCOS2.81後的版本中有軟體定時器的概念,軟體定時器其實跟硬體中斷是相似的,定時時間到了,就執行一次回撥函式,雖然好用,但是也會降低系統的實時性。
軟體定時器也需要一個時鐘節拍驅動,這個驅動也是由硬體實現的,一般使用uCOS中的任務延時節拍驅動來驅動軟體定時器,每個時鐘節拍OSTmrCtr(全域性變數,初始值為0)加1,當OSTmrCtr的值等於OS_TICKS_PER_SEC /OS_TMR_CFG_TICKS_PER_SEC(前者是ucos節拍頻率,後者是軟體定時器的節拍頻率,相當於分頻)時,呼叫函式OSTmrSignl()函式,傳送訊號量OSTmrSemSignal(初始值0,決定軟體定時器掃描任務OSTmr_Task的執行),也就是說,對軟體定製器的處理不在時鐘節拍中斷函式中執行,而是以發生訊號量的方式啟用任務OSTmr_Task,任務OSTmr_Task對定時器進行檢測,包括定時器定時完成的判斷,回撥函式的執行。

 舉例來講,ucos中的OS_TICKS_PER_SEC設定值為1000(最大),OS_TMR_CFG_TICKS_PER_SEC為100,則可知uCOS的節拍時間為1ms,軟體定時器的節拍時間為1000/100*1=10ms

 在軟體定時器的生成函式中:


OS_TMR  *OSTmrCreate (INT32U           dly,
                      INT32U           period,
                      INT8U            opt,
                      OS_TMR_CALLBACK  callback,
                      void            *callback_arg,
                      INT8U           *pname,
                      INT8U           *perr)
其中dly表示第一次延時時間節拍數(軟體定時器節拍,不是ucos的節拍)
period表示重複節拍數,如果設定dly為10,period為20,opt設定OS_TMR_OPT_PERIODIC,則表示這是1個重複執行軟體定時器,第一次執行定時時間為10x10=100ms,以後每隔20x10=200ms的間隔時間執行回撥函式。

===========================================
uCOS時鐘節拍和滴答定時器的關係

在使用uCOS時,有一個非常重要,非常關鍵的概念就是作業系統的時鐘節拍,uCOS的時鐘節拍來源於滴答定時器,滴答定時器按照設定的時間不停的計時和產生中斷,在uCOS-III中滴答定時器的中斷服務函式如下:


void  OS_CPU_SysTickHandler (void)
{
    CPU_SR_ALLOC();
 
    CPU_CRITICAL_ENTER();
    OSIntNestingCtr++;                           /* Tell uC/OS-III that we are starting an ISR */
    CPU_CRITICAL_EXIT();
 
    OSTimeTick();                                /* Call uC/OS-III's OSTimeTick() */
 
    OSIntExit();                                /* Tell uC/OS-III that we are leaving the ISR */
}

其中OSTimeTick();的作用是檢查每個任務的任務控制塊中OSTCBDly減1後是否為0(翻譯過來就是檢查任務延時函式OSTimeDly中的節拍數是否減為0了),如果是,則表明這個任務剛才是掛起狀態,此時應變為就緒態,接著在任務中OSTimeDly函式進行一次任務排程。
所以可以得出一個重要關係:

滴答定時器的中斷時間  =  uCOS的1個節拍時間

這個節拍就是OSTimeDly (OS_TICK dly, OS_OPT opt,OS_ERR *p_err)函式中的dly。

在uCOS-III中針對節拍的時間有如下定義:

/* ------------------------ TICKS ----------------------- */
 #define  OS_CFG_TICK_RATE_HZ            1000u        /* Tick rate in Hertz (10 to 1000 Hz)                     */
 
這個OS_CFG_TICK_RATE_HZ表示節拍的頻率,如果設定為1000,則表示頻率為1000Hz,則1個節拍為1ms。
那麼問題來了,如果想要uCOS-III的節拍時間為1ms,如何設定滴答定時器的reload數值呢?

通過上面的分析可知,我們只需要設定滴答定時器的中斷時間為1ms即可,以STM32為例,典型的系統時鐘頻率為72MHz(外部晶振選擇為8MHz),滴答定時器時鐘源也選擇為HCLK(不是除以8),

則滴答定時器計數1次的時間為:1/72000000 s

要想中斷時間為1ms = 1/1000 s,則reload = (1/10000)/(1/72000000) = 72000

而72000 = 72000000(系統時鐘)/1000(OS_CFG_TICK_RATE_HZ)

所以在設定滴答定時器初始化函式時,只需設定:

SysTick_Config(SystemCoreClock/OS_CFG_TICK_RATE_HZ);  

就能滿足uCOS-III想要的節拍時間了。

 

摘自:https://blog.csdn.net/u012351051/article/details/51262503