1 系統時鐘中斷驅動引擎 rt-thread操作系統中當線程時間片耗盡,或是當線程sleep一段時間後喚醒再被調度,此過程又是如何進行的呢?到底是誰來驅動這一過程的呢? 答案是時鐘中斷源。且來看看時鐘中斷例程: 在bsp/stm32f20x/drivers/board.c源文件中存在這麼一個時鐘中斷例程代碼:(這裡以stm32f20x的MCU為例) [cpp] /** * This is the timer interrupt service routine. * */ void SysTick_Handler(void) { /* enter interrupt */ rt_interrupt_enter();//進入中斷 rt_tick_increase();//增加tick /* leave interrupt */ rt_interrupt_leave();//離開中斷 } 其中rt_tick_increase的函數如下定義: [cpp] /** * This function will notify kernel there is one tick passed. Normally, * this function is invoked by clock ISR. */ void rt_tick_increase(void) { struct rt_thread *thread; /* increase the global tick */ ++ rt_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_yield函數已在之前的文章http://blog.csdn.net/flydream0/article/details/8584362一文的第7章已有介紹,而rt_timer_check函數在http://blog.csdn.net/flydream0/article/details/8570841#t4一文中第3.3節也已有介紹。 由上述代碼可見,一旦系統產生時鐘中斷,在中斷例程中,系統首先將檢查當前正在運行的線程剩余時間片是否耗盡,如果耗盡則將其從調度器就緒隊列中取出放到末尾,然後再重新調度線程,接著檢查是否有休眠的線程時間到達,如果有,則觸發其時鐘超時回調函數,這個時鐘超時回調函數在之前的文章http://blog.csdn.net/flydream0/article/details/8584362#t2一文中的2.1節介紹初始化線程函數_rt_thread_init時有如下代碼: [cpp] //... /* init thread timer */ rt_timer_init(&(thread->thread_timer),//初始化線程的定時器 thread->name, rt_thread_timeout, thread, 0, RT_TIMER_FLAG_ONE_SHOT); //... 可見在線程初始化時,就設置了線程內部時鐘的超時回調函數rt_thread_timeout函數,關鍵就是這個函數會進行一些線程調度的操作,其源碼如下定義: [cpp] /** * This function is the timeout function for thread, normally which is invoked * when thread is timeout to wait some resource. * * @param parameter the parameter of thread timeout function */ void rt_thread_timeout(void *parameter) { struct rt_thread *thread; thread = (struct rt_thread *)parameter; /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(thread->stat == RT_THREAD_SUSPEND); /* set error number */ thread->error = -RT_ETIMEOUT; /* remove from suspend list *///從掛起鏈表中移除 rt_list_remove(&(thread->tlist)); /* insert to schedule ready list */ rt_schedule_insert_thread(thread);//加入調度器 /* do schedule */ rt_schedule();//重新調度 } 可見,其會將當前掛起的線程加入到調度器就緒隊列,然後重新調度。 2 系統時鐘中斷引擎小結 綜上所述,當系統產生時鐘中斷時,首先檢查當前正在運行的線程是否還有剩余時間片,如果耗盡則從就緒隊列中移除放到末尾再重新調度,接著檢查是否存在掛起的線程有時間到達的,如果有,則加入到調度器就緒隊列中,然後重新調度。 3 軟件定時器模式下的驅動引擎 此外,需要注意地是,如果用戶設置使用軟件軟件定時器方式,則系統中還存在一時鐘線程timer_thread,見http://blog.csdn.net/flydream0/article/details/8570841一文,此線程專門隨時系統時鐘tick的增加來檢查定時器是否時間到達,這其中就包含線程的定時器,一旦線程對應的定時器時間到達,則將加入到線程調度器就緒隊列中進行調度。由此可見,在設置了軟件定時器模式時(默認情況下,rt-thread使用硬件定時器),這個timer_thread線程也是rt_thread操作系統線程調度的驅動引擎. 4 如何設置系統時鐘中斷間隔 查看rt-thread操作系統的用戶手冊時,上面有提到rt_thead操作系統的時鐘每個tick的默認間隔為10ms,那麼這個10 ms雙是如何來的呢? 答案是在/bsp/stm32f20x/drivers/board.c源文件中,且看SysTick_Configuration函數的實現: [cpp] /******************************************************************************* * Function Name : SysTick_Configuration * Description : Configures the SysTick for OS tick. * Input : None * Output : None * Return : None *******************************************************************************/ void SysTick_Configuration(void) { RCC_ClocksTypeDef rcc_clocks; rt_uint32_t cnts; RCC_GetClocksFreq(&rcc_clocks);//獲得系統的晶振頻率 cnts = (rt_uint32_t)rcc_clocks.HCLK_Frequency / RT_TICK_PER_SECOND;//計算出多少次晶振才是一個tick時間片 SysTick_Config(cnts);//配置系統tick SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//配置時鐘源 } 由上述代碼可見,rt_thread的系統tick是由RT_TICK_PER_SECOND這個宏來配置的,RT_TICK_PER_SECOND在頭文件rtconfig.h文件中定義,如下: [cpp] /* Tick per Second */ #define RT_TICK_PER_SECOND 100 此參數的含義是1秒包含多少個tick, 這裡默認是100,則默認情況下1秒包含100個tick,那麼即每個tick為10ms,現在明白了吧? 如果我們要修改每個tick的時間隔,則只需要修改RT_TICK_PER_SECOND這個宏的值即可.