board.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (c) 2020-2022, CQ 100ask Development Team
  3. *
  4. * Change Logs:
  5. * Date Author Notes
  6. * 2022-05-29 Alen first version
  7. */
  8. #include "board.h"
  9. #include "hal_rcc.h"
  10. static uint32_t SystemClockFreq = HSI_VALUE;
  11. static uint32_t AHBClockFreq = HSI_VALUE;
  12. static uint32_t APB1ClockFreq = HSI_VALUE;
  13. static uint32_t APB2ClockFreq = HSI_VALUE;
  14. static void update_systemclock(void);
  15. static void update_ahb_clock(void);
  16. static void update_apb1_clock(void);
  17. static void update_apb2_clock(void);
  18. void SystemClock_Config(void)
  19. {
  20. /* 使能总线外设时钟 */
  21. RCC->AHB1ENR |= (1u << 13u); // 使能FLASH外设
  22. FLASH->ACR |= (4<<0); // 设置Flash的等待周期
  23. /* 使能PWR/DBG */
  24. RCC->APB1ENR |= (1<<28);
  25. PWR->CR1 &= ~(2<<14);
  26. PWR->CR1 |= (2<<14); // 如果系统时钟需要达到最大频率 120MHz,需要将 VOS 设置为 2’b10 即 1.7V
  27. RCC->CR &= ~((1<<16) | (1<<24) ); // 关闭HSE/PLL
  28. /* 配置HSE和PLL */
  29. RCC->CR |= (1<<16); // 使能HSE
  30. while(0 == ((RCC->CR)&(1<<17)));// 等待HSE稳定
  31. RCC->PLLCFGR |= (1<<0); // 配置PLL的时钟源HSE
  32. RCC->PLLCFGR &= ~(1<<1); // 配置PLL的时钟源HSE不分频后再作为时钟输入源
  33. RCC->PLLCFGR &= ~(0x7F<<16);
  34. RCC->PLLCFGR |= (19<<16); // 配置PLL的倍频系数:20倍 -> 12MHz/2*20 = 120MHz
  35. RCC->PLLCFGR &= ~(0x7<<8);
  36. RCC->PLLCFGR |= (1<<8); // 配置PLL的分频系数:2
  37. RCC->CR |= (1<<24); // 使能PLL
  38. while(0 == (RCC->CR & (1<<25)));// 等待PLL时钟稳定
  39. /* 配置系统时钟、AHB、APB时钟 */
  40. RCC->CFGR |= (0<<4); // AHB不分频
  41. RCC->CFGR |= (4<<8); // APB1 2分频
  42. RCC->CFGR |= (4<<11); // APB2 2分频
  43. RCC->CFGR |= (2<<22); // PLL输出时钟3分频后输出给USB:120MHz/3=40MHz
  44. RCC->CFGR |= (7<<24); // PLL输出时钟2分频后输出到MCO
  45. RCC->CFGR |= (2<<0); // 选择PLL输出用作系统时钟
  46. while(0 == (RCC->CFGR & (2<<2))); // 等待PLL输出用作系统时钟稳定
  47. update_systemclock();
  48. update_ahb_clock();
  49. update_apb1_clock();
  50. update_apb2_clock();
  51. }
  52. static void update_systemclock(void)
  53. {
  54. uint32_t tmpreg = 0U, prediv = 0U, pllclk = 0U, pllmul = 0U;
  55. uint32_t sysclockfreq = HSI_VALUE;
  56. tmpreg = RCC->CFGR;
  57. /* 获取系统时钟源 */
  58. switch(tmpreg & RCC_CFGR_SWS_MASK)
  59. {
  60. case RCC_SYSCLKSOURCE_STATUS_HSI:
  61. {
  62. sysclockfreq = HSI_VALUE;
  63. break;
  64. }
  65. case RCC_SYSCLKSOURCE_STATUS_HSE:
  66. {
  67. sysclockfreq = HSE_VALUE;
  68. break;
  69. }
  70. case RCC_SYSCLKSOURCE_STATUS_LSI:
  71. {
  72. sysclockfreq = LSI_VALUE;
  73. break;
  74. }
  75. case RCC_SYSCLKSOURCE_STATUS_PLLCLK:
  76. {
  77. /* 获取PLL的输入时钟源 */
  78. if(RCC->PLLCFGR&0x01) // HSE用作PLL的输入时钟
  79. {
  80. if(RCC->PLLCFGR&0x02) // HSE二分频后输入给PLL
  81. {
  82. pllclk = HSE_VALUE>>1;
  83. }
  84. else // HSE部分变频直接输出给PLL
  85. {
  86. pllclk = HSE_VALUE;
  87. }
  88. }
  89. else // HSI用作PLL的输入时钟
  90. {
  91. pllclk = HSI_VALUE;
  92. }
  93. prediv = (RCC->PLLCFGR>>8)&0x07; // PLL的分频系数:PLLCFGR[10:8]
  94. pllmul = (RCC->PLLCFGR>>16)&0x7F; // PLL的倍频系数: PLLCFGR[22:16]
  95. sysclockfreq = pllclk * (pllmul+1) / (prediv+1);
  96. break;
  97. }
  98. default:break;
  99. }
  100. SystemClockFreq = sysclockfreq;
  101. }
  102. static void update_ahb_clock(void)
  103. {
  104. uint32_t tmpreg = RCC->CFGR;
  105. uint8_t hpre = (tmpreg>>4)&0x0F;
  106. if((hpre&0x08) == 0) // 不分频
  107. AHBClockFreq = SystemClockFreq;
  108. else
  109. {
  110. hpre = (hpre&0x07) + 1;
  111. AHBClockFreq = SystemClockFreq>>hpre;
  112. }
  113. }
  114. static void update_apb1_clock(void)
  115. {
  116. uint32_t tmpreg = RCC->CFGR;
  117. uint8_t ppre1 = (tmpreg>>8)&0x0F;
  118. if((ppre1&0x04) == 0) // 不分频
  119. APB1ClockFreq = AHBClockFreq;
  120. else
  121. {
  122. ppre1 = (ppre1&0x03) + 1;
  123. APB1ClockFreq = AHBClockFreq>>ppre1;
  124. }
  125. }
  126. static void update_apb2_clock(void)
  127. {
  128. uint32_t tmpreg = RCC->CFGR;
  129. uint8_t ppre2 = (tmpreg>>11)&0x0F;
  130. if((ppre2&0x04) == 0) // 不分频
  131. APB2ClockFreq = AHBClockFreq;
  132. else
  133. {
  134. ppre2 = (ppre2&0x03) + 1;
  135. APB2ClockFreq = AHBClockFreq>>ppre2;
  136. }
  137. }
  138. uint32_t HAL_GetSysClockFreq(void)
  139. {
  140. return SystemClockFreq;
  141. }
  142. uint32_t HAL_Get_AHB_Clock(void)
  143. {
  144. return AHBClockFreq;
  145. }
  146. uint32_t HAL_Get_APB1_Clock(void)
  147. {
  148. return APB1ClockFreq;
  149. }
  150. uint32_t HAL_Get_APB2_Clock(void)
  151. {
  152. return APB2ClockFreq;
  153. }