123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- /*
- * Copyright (c) 2020-2022, CQ 100ask Development Team
- *
- * Change Logs:
- * Date Author Notes
- * 2022-05-29 Alen first version
- */
- #include "board.h"
- #include "hal_rcc.h"
- static uint32_t SystemClockFreq = HSI_VALUE;
- static uint32_t AHBClockFreq = HSI_VALUE;
- static uint32_t APB1ClockFreq = HSI_VALUE;
- static uint32_t APB2ClockFreq = HSI_VALUE;
- static void update_systemclock(void);
- static void update_ahb_clock(void);
- static void update_apb1_clock(void);
- static void update_apb2_clock(void);
- void SystemClock_Config(void)
- {
- /* 使能总线外设时钟 */
- RCC->AHB1ENR |= (1u << 13u); // 使能FLASH外设
- FLASH->ACR |= (4<<0); // 设置Flash的等待周期
- /* 使能PWR/DBG */
- RCC->APB1ENR |= (1<<28);
- PWR->CR1 &= ~(2<<14);
- PWR->CR1 |= (2<<14); // 如果系统时钟需要达到最大频率 120MHz,需要将 VOS 设置为 2’b10 即 1.7V
- RCC->CR &= ~((1<<16) | (1<<24) ); // 关闭HSE/PLL
- /* 配置HSE和PLL */
- RCC->CR |= (1<<16); // 使能HSE
- while(0 == ((RCC->CR)&(1<<17)));// 等待HSE稳定
- RCC->PLLCFGR |= (1<<0); // 配置PLL的时钟源HSE
- RCC->PLLCFGR &= ~(1<<1); // 配置PLL的时钟源HSE不分频后再作为时钟输入源
- RCC->PLLCFGR &= ~(0x7F<<16);
- RCC->PLLCFGR |= (19<<16); // 配置PLL的倍频系数:20倍 -> 12MHz/2*20 = 120MHz
- RCC->PLLCFGR &= ~(0x7<<8);
- RCC->PLLCFGR |= (1<<8); // 配置PLL的分频系数:2
- RCC->CR |= (1<<24); // 使能PLL
- while(0 == (RCC->CR & (1<<25)));// 等待PLL时钟稳定
- /* 配置系统时钟、AHB、APB时钟 */
- RCC->CFGR |= (0<<4); // AHB不分频
- RCC->CFGR |= (4<<8); // APB1 2分频
- RCC->CFGR |= (4<<11); // APB2 2分频
- RCC->CFGR |= (2<<22); // PLL输出时钟3分频后输出给USB:120MHz/3=40MHz
- RCC->CFGR |= (7<<24); // PLL输出时钟2分频后输出到MCO
- RCC->CFGR |= (2<<0); // 选择PLL输出用作系统时钟
- while(0 == (RCC->CFGR & (2<<2))); // 等待PLL输出用作系统时钟稳定
- update_systemclock();
- update_ahb_clock();
- update_apb1_clock();
- update_apb2_clock();
- }
- static void update_systemclock(void)
- {
- uint32_t tmpreg = 0U, prediv = 0U, pllclk = 0U, pllmul = 0U;
- uint32_t sysclockfreq = HSI_VALUE;
- tmpreg = RCC->CFGR;
- /* 获取系统时钟源 */
- switch(tmpreg & RCC_CFGR_SWS_MASK)
- {
- case RCC_SYSCLKSOURCE_STATUS_HSI:
- {
- sysclockfreq = HSI_VALUE;
- break;
- }
- case RCC_SYSCLKSOURCE_STATUS_HSE:
- {
- sysclockfreq = HSE_VALUE;
- break;
- }
- case RCC_SYSCLKSOURCE_STATUS_LSI:
- {
- sysclockfreq = LSI_VALUE;
- break;
- }
- case RCC_SYSCLKSOURCE_STATUS_PLLCLK:
- {
- /* 获取PLL的输入时钟源 */
- if(RCC->PLLCFGR&0x01) // HSE用作PLL的输入时钟
- {
- if(RCC->PLLCFGR&0x02) // HSE二分频后输入给PLL
- {
- pllclk = HSE_VALUE>>1;
- }
- else // HSE部分变频直接输出给PLL
- {
- pllclk = HSE_VALUE;
- }
- }
- else // HSI用作PLL的输入时钟
- {
- pllclk = HSI_VALUE;
- }
- prediv = (RCC->PLLCFGR>>8)&0x07; // PLL的分频系数:PLLCFGR[10:8]
- pllmul = (RCC->PLLCFGR>>16)&0x7F; // PLL的倍频系数: PLLCFGR[22:16]
- sysclockfreq = pllclk * (pllmul+1) / (prediv+1);
- break;
- }
- default:break;
- }
- SystemClockFreq = sysclockfreq;
- }
- static void update_ahb_clock(void)
- {
- uint32_t tmpreg = RCC->CFGR;
- uint8_t hpre = (tmpreg>>4)&0x0F;
- if((hpre&0x08) == 0) // 不分频
- AHBClockFreq = SystemClockFreq;
- else
- {
- hpre = (hpre&0x07) + 1;
- AHBClockFreq = SystemClockFreq>>hpre;
- }
- }
- static void update_apb1_clock(void)
- {
- uint32_t tmpreg = RCC->CFGR;
- uint8_t ppre1 = (tmpreg>>8)&0x0F;
- if((ppre1&0x04) == 0) // 不分频
- APB1ClockFreq = AHBClockFreq;
- else
- {
- ppre1 = (ppre1&0x03) + 1;
- APB1ClockFreq = AHBClockFreq>>ppre1;
- }
- }
- static void update_apb2_clock(void)
- {
- uint32_t tmpreg = RCC->CFGR;
- uint8_t ppre2 = (tmpreg>>11)&0x0F;
- if((ppre2&0x04) == 0) // 不分频
- APB2ClockFreq = AHBClockFreq;
- else
- {
- ppre2 = (ppre2&0x03) + 1;
- APB2ClockFreq = AHBClockFreq>>ppre2;
- }
- }
- uint32_t HAL_GetSysClockFreq(void)
- {
- return SystemClockFreq;
- }
- uint32_t HAL_Get_AHB_Clock(void)
- {
- return AHBClockFreq;
- }
- uint32_t HAL_Get_APB1_Clock(void)
- {
- return APB1ClockFreq;
- }
- uint32_t HAL_Get_APB2_Clock(void)
- {
- return APB2ClockFreq;
- }
|