同樣還是由主函數(shù)入手,當(dāng)然不是說的用戶層的主函數(shù)脊僚,而是
int $Sub$$main(void)
{
rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
然后進入rtthread_startup();函數(shù)相叁,時鐘肯定是第一批需要處理的事兒,在進入rt_hw_board_init();函數(shù)辽幌,便能看見對系統(tǒng)時鐘的初始化
/* System clock initialization */
SystemClock_Config();
rt_hw_systick_init();
第一句便是所以STM32代碼都會有的函數(shù)增淹,對硬件時鐘進行初始化,選擇內(nèi)部還是外部乌企,分頻之類的操作虑润。
第二句便和系統(tǒng)相關(guān)了
該函數(shù)用于系統(tǒng)時鐘的硬件初始化,內(nèi)部初始化了滴答定時器
void rt_hw_systick_init(void)
{
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / RT_TICK_PER_SECOND);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
HAL_RCC_GetHCLKFreq() 函數(shù)返回系統(tǒng)時鐘加酵,我L151工程里面是32M拳喻,RT_TICK_PER_SECOND宏在rt_config.h中被定義哭当。HAL_SYSTICK_Config()該函數(shù)實際就是設(shè)定一個滴答定時器的中斷間隔,假設(shè)RT_TICK_PER_SECOND被定義為1冗澈,那么每32M個節(jié)拍中斷一次則等于1秒钦勘,系統(tǒng)的最小時間間隔就為1s。我工程里面設(shè)定的是1000亚亲,則表示我設(shè)定的定時器最小時間間隔為1ms彻采。
第二句和第三句分別是設(shè)定定時器的分頻和中斷等級。
執(zhí)行完畢則滴答定時器開始不斷發(fā)生中斷
下列函數(shù)即是滴答定時器的中斷函數(shù)
void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_IncTick();
rt_tick_increase();
/* enter interrupt */
rt_interrupt_leave();
}
HAL_IncTick();是庫函數(shù)層面的累加捌归,在系統(tǒng)中實際是沒有意義的肛响。
rt_tick_increase()則進行了和系統(tǒng)相關(guān)的處理,實現(xiàn)如下:
void rt_tick_increase(void)
{
struct rt_thread *thread;
/* increase the global tick */
#ifdef RT_USING_SMP
rt_cpu_self()->tick ++;
#else
++ rt_tick;
#endif
/* check time slice */
thread = rt_thread_self();
-- thread->remaining_tick;
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_USING_SMP宏陨溅,所以即是單純的系統(tǒng)時間累計加到rt_tick變量上终惑,并且rt_thread_self函數(shù)也是之間返回了當(dāng)前運行的線程,之后將線程時間片減1门扇,將減盡線程可用事件片后就使該線程放出執(zhí)行權(quán)雹有。線程部分具體還是在之后研究該部分的時候說明,最后rt_timer_check函數(shù)是在檢查有沒有發(fā)生定時器超時事件臼寄,同樣具體放到定時器研究去詳細說明霸奕。
綜上其實和硬件相關(guān)的僅僅是void rt_hw_systick_init(void)函數(shù)和硬件中斷回調(diào)void SysTick_Handler(void)。如果相關(guān)更換系統(tǒng)時鐘的類型吉拳,例如使用RTC质帅,則只需要在初始化中配置RTC按照RT_TICK_PER_SECOND宏周期中斷,并在RTC的中斷回調(diào)函數(shù)中執(zhí)行rt_tick_increase()即可留攒。
和系統(tǒng)時鐘相關(guān)的函數(shù)存放于Kennel/clock.c中都是一些給時鐘變量rt_tick服務(wù)的函數(shù)煤惩。注意的是tick已經(jīng)表示的是系統(tǒng)節(jié)拍,也就是1/RT_TICK_PER_SECOND秒炼邀,可不是晶振分配得到的32M時鐘魄揉。