本帖最后由 xyzjacky 于 2020-1-8 12:52 编辑
首先,使用RTthread OS时,要配置它的系统节拍rt_tick (划重点) 系统节拍· 系统节拍是特定的周期中断,可以看作是系统心跳,中断之间的时间间隔取决于系统的需求,一般是 1ms–100ms,系统节拍率越快,系统的额外开销就越大,从系统启动开始计数的时钟节拍数称为系统时间。 · RT-Thread 中,系统节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整,等于1/RT_TICK_PER_SECOND 秒。 系统节拍实现方式· 系统节拍由配置为中断触发模式的硬件定时器产生,当中断到来时,将调用一次:void rt_tick_increase(void),通知操作系统已经过去一个系统时钟 先看这段代码: 1. void SysTick_Handler(void) 2. { 3. /* enter interrupt */ 4. rt_interrupt_enter(); 5. 6. rt_tick_increase(); 7. 8. /* leave interrupt */ 9. rt_interrupt_leave(); 10. }
其中函数rt_tick_increase()的代码是:
1. void rt_tick_increase(void) 2. { 3. struct rt_thread *thread; 4. 5. /* increase the global tick */ 6. #ifdef RT_USING_SMP 7. rt_cpu_self()->tick ++; 8. #else 9. ++ rt_tick; 10. #endif 11. 12. /* check time slice */ 13. thread = rt_thread_self(); 14. 15. -- thread->remaining_tick; 16. if (thread->remaining_tick == 0) 17. { 18. /* change to initialized tick */ 19. thread->remaining_tick = thread->init_tick; 20. 21. /* yield */ 22. rt_thread_yield(); 23. } 24. 25. /* check timer */ 26. rt_timer_check(); 27. }
若系统的硬件是外置8MHz晶振,系统时钟每秒节拍数1000表示1s内rt_tick增加1000,即时钟节拍为1ms;若设为100,则rt_tick每隔10ms加1,时钟节拍为10ms。
SysTick_Handler是STM32的硬件滴答时钟的中断库函数,既然是一个时钟,那么类似定时器,它应该有一个时间间隔才产生一次中断。这个时间间隔就由以下这个函数来设置:
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/ RT_TICK_PER_SECOND);
其中RT_TICK_PER_SECOND定义在rtconfig.h中: 1. /* Tick per Second */ 2. #define RT_TICK_PER_SECOND 1000
RT thread对于此处代码的解释是,等于 1/RT_TICK_PER_SECOND 秒,RT_TICK_PER_SECOND默认是1000。
又因HAL_RCC_GetHCLKFreq()的返回值是SystemCoreClock,所以就要查找SystemCoreClock在哪里赋值的。所以继续查看代码,找到: rtthread_startup() -> rt_hw_board_init()-> SystemClock_Config() -> SystemCoreClockUpdate ()
在函数SystemCoreClockUpdate()中有如下一段代码(关键部份为橙色): 1. /* Get SYSCLK source -------------------------------------------------------*/ 2. switch (RCC->CFGR & RCC_CFGR_SWS) 3. { 4. case 0x00: /* MSI used as system clock source */ 5. SystemCoreClock = msirange; 6. break; 7. 8. case 0x04: /* HSI used as system clock source */ 9. SystemCoreClock = HSI_VALUE; 10. break; 11. 12. case 0x08: /* HSE used as system clock source */ 13. SystemCoreClock = HSE_VALUE; 14. break; 15. 16. case 0x0C: /* PLL used as system clock source */ 17. /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN 18. SYSCLK = PLL_VCO / PLLR 19. */ 20. pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); 21. pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4U) + 1U ; 22. 23. switch (pllsource) 24. { 25. case 0x02: /* HSI used as PLL clock source */ 26. pllvco = (HSI_VALUE / pllm); 27. break; 28. 29. case 0x03: /* HSE used as PLL clock source */ 30. pllvco = (HSE_VALUE / pllm); 31. break; 32. 33. default: /* MSI used as PLL clock source */ 34. pllvco = (msirange / pllm); 35. break; 36. } 37. pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8U); 38. pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25U) + 1U) * 2U; 39. SystemCoreClock = pllvco/pllr; 40. break; 41. 42. default: 43. SystemCoreClock = msirange; 44. break; 45. } 46. 47. /* Compute HCLK clock frequency --------------------------------------------*/ 48. /* Get HCLK prescaler */ 49. tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; 50. /* HCLK clock frequency */ 51. SystemCoreClock >>= tmp;
在代码中,switch (RCC->CFGR &RCC_CFGR_SWS)显然就是硬件的时钟寄存器,一般STM32F103系列电路板上用的是外部晶振,所以就是0x08的值在起作用。 1. case 0x08: /* HSE used as system clock source */ 2. SystemCoreClock = HSE_VALUE;
查找HSE_VALUE的定义,果然能找到 #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ 一般电路板上这个外部晶振都是8MHz,所以此处HSE_VALUE为8000000U
同时,看这段代码: 52. /* Get HCLK prescaler */ 53. tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; 54. /* HCLK clock frequency */ 55. SystemCoreClock >>= tmp;
注释Get HCLK prescaler,意思是取得AHB的预分频; 注释HCLK clock frequency,意思是HCLK的频率。 一般我们都会将HCLK调整为72MHz,由此可知,SystemCoreClock算出来的值是72000000。
|