RT-thread內核之系統時鐘

1、系統時鐘函數

rt-thread的系統時鐘模塊採用全局變量rt_tick做爲系統時鐘節拍,該變量在系統時鐘中斷函數中不斷加1。而系統時鐘中斷源和中斷間隔通常由MCU硬件定時器(如stm32的嘀嗒定時器)決定,rt_tick初始值爲0,每次MCU產生硬件定時中斷後,在中斷函數中不斷加1,即rt_tick變量值與MCU硬件定時器定時中斷間隔的乘積爲系統真正運行時間(例如rt_tick=10,stm32嘀嗒定時器每隔1ms產生中斷,則系統上電運行時間爲10ms)。ui

在bsp/stm32f40x/drivers/board.c中設置MCU硬件定時器定時間隔,以及執行相應定時器中斷函數:spa

void  SysTick_Configuration(void)
{
    RCC_ClocksTypeDef  rcc_clocks;
    rt_uint32_t         cnts;

    RCC_GetClocksFreq(&rcc_clocks);//得到系統的晶振頻率

//RT_TICK_PER_SECOND在rtconfig.h中配置,表示每秒包含的系統時鐘節拍數。默認配置爲100,則嘀嗒定時器中斷間隔爲10ms,rt_tick每隔10ms加1,即默認狀況下1s內包含100個系統時鐘節拍,每一個時鐘節拍tick表示10ms。爲了提升 精度,通常修改宏定義爲1000,即1s內包含1000個系統時鐘節拍(此時嘀嗒定時器中斷間隔爲1ms,每一個時鐘節拍tick則表示1ms)。
cnts = (rt_uint32_t)rcc_clocks.HCLK_Frequency / RT_TICK_PER_SECOND;
cnts = cnts / 8;
    SysTick_Config(cnts);                                //配置系統tick,函數在core_cm4.h中實現,使能嘀嗒定時器中斷、定時器時鐘源頻率HCLK=168MHZ、啓動嘀嗒定時器
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//配置定時器時鐘源,函數在misc.c中實現,將定時器時源鍾頻率設置爲HCLK/8=21MHZ
}

void SysTick_Handler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();//表示進入中斷,在src/irp.c中定義,中斷嵌套計數器rt_interrupt_nest加1

    rt_tick_increase();  //rt_tick加1,並檢查當前運行線程的剩餘時間片是否耗盡,若耗盡則讓出處理器並從新調度線程,接着執行硬件定時器中斷模式下的定時器超時檢查rt_timer_check(); /* leave interrupt */
    rt_interrupt_leave();//表示進入中斷,在src/irp.c中定義,中斷嵌套計數器rt_interrupt_nest減1
}

2、硬件定時器中斷模式下線程調度驅動線程

在src/clock.c中:code

void rt_tick_increase(void)
{
    struct rt_thread *thread;

    /* increase the global tick */
    ++ rt_tick;                     //全局變量系統時鐘節拍數加1  

    /* check time slice */
    thread = rt_thread_self();      //獲取當前運行的線程  

    -- thread->remaining_tick;      //當前運行線程的剩餘時間片減1  
    if (thread->remaining_tick == 0)//若是當前運行線程無剩餘時間
    {
        /* change to initialized tick */
        thread->remaining_tick = thread->init_tick;//從新將線程的剩餘時間片設置爲初始化時間片

        /* yield */
        rt_thread_yield();//將此線程從調度器就緒隊列中取出來放到同優先級線程鏈表末尾,而後再次調度  
    }

    /* check timer */
    rt_timer_check();//檢查定時器鏈表上是否有時間到達的時鐘,即包括自定義的定時器,也包括線程睡眠時啓動的線程定時器
}

由上述代碼可見,一旦系統產生時鐘中斷,在嘀嗒定時器中斷函數中,系統首先將檢查當前正在運行的線程剩餘時間片是否耗盡,若是耗盡則將其從調度器就緒隊列中取出放到同優先級線程鏈表末尾,而後再從新調度線程;接着檢查是否有休眠的線程時間到達(即線程睡眠時啓動的線程定時器是否超時),若是有則觸發相應的線程定時器超時函數rt_thread_timeout(將當前掛起的線程加入到調度器就緒隊列後從新調度),從而將線程從睡眠中喚醒。blog

總而言之,在硬件定時器中斷模式下,系統時鐘中斷(MCU硬件定時器中斷或嘀嗒定時器中斷)是rt-thread線程調度的驅動力。隊列

3、軟件定時器線程模式下線程調度驅動v8

若在rtconfig.h中定義了宏RT_USING_TIMER_SOFT,則使用軟件定時器線程模式,此模式下系統中存在定時器線程timer_thread(在rt_system_timer_thread_init中初始化)。在此線程入口函數中經過rt_tick的增長不停地檢查定時器鏈表中是否有定時器超時,其中也包含線程睡眠時啓動的線程定時器,一旦線程對應的定時器超時,則觸發相應的線程定時器超時函數rt_thread_timeout(將當前掛起的線程加入到調度器就緒隊列後從新調度),從而將線程從睡眠中喚醒。rem

因而可知,在軟件定時器線程模式下,rt_system_timer_thread_init中初始化的定時器線程timer_thread就是rt-thread線程調度的驅動力。it

相關文章
相關標籤/搜索