BeRTOS
|
00001 00038 #include "clock_stm32.h" 00039 00040 #include <cfg/compiler.h> 00041 #include <cfg/debug.h> 00042 00043 #include <io/stm32.h> 00044 00045 struct RCC *RCC; 00046 00047 INLINE int rcc_get_flag_status(uint32_t flag) 00048 { 00049 uint32_t id; 00050 reg32_t reg; 00051 00052 /* Get the RCC register index */ 00053 id = flag >> 5; 00054 /* The flag to check is in CR register */ 00055 if (id == 1) 00056 reg = RCC->CR; 00057 /* The flag to check is in BDCR register */ 00058 else if (id == 2) 00059 reg = RCC->BDCR; 00060 /* The flag to check is in CSR register */ 00061 else 00062 reg = RCC->CSR; 00063 /* Get the flag position */ 00064 id = flag & FLAG_MASK; 00065 00066 return reg & (1 << id); 00067 } 00068 00069 INLINE uint16_t pll_clock(void) 00070 { 00071 unsigned int div, mul; 00072 00073 /* Hopefully this is evaluate at compile time... */ 00074 for (div = 2; div; div--) 00075 for (mul = 2; mul <= 16; mul++) 00076 if (CPU_FREQ <= (PLL_VCO / div * mul)) 00077 break; 00078 return mul << 8 | div; 00079 } 00080 00081 INLINE void rcc_pll_config(void) 00082 { 00083 reg32_t reg = RCC->CFGR & CFGR_PLL_MASK; 00084 00085 /* Evaluate clock parameters */ 00086 uint16_t clock = pll_clock(); 00087 uint32_t pll_mul = ((clock >> 8) - 2) << 18; 00088 uint32_t pll_div = ((clock & 0xff) << 1 | 1) << 16; 00089 00090 /* Set the PLL configuration bits */ 00091 reg |= pll_div | pll_mul; 00092 00093 /* Store the new value */ 00094 RCC->CFGR = reg; 00095 00096 /* Enable PLL */ 00097 *CR_PLLON_BB = 1; 00098 } 00099 00100 INLINE void rcc_set_clock_source(uint32_t source) 00101 { 00102 reg32_t reg; 00103 00104 reg = RCC->CFGR & CFGR_SW_MASK; 00105 reg |= source; 00106 RCC->CFGR = reg; 00107 } 00108 00109 void clock_init(void) 00110 { 00111 /* Initialize global RCC structure */ 00112 RCC = (struct RCC *)RCC_BASE; 00113 00114 /* Enable the internal oscillator */ 00115 *CR_HSION_BB = 1; 00116 while (!rcc_get_flag_status(RCC_FLAG_HSIRDY)); 00117 00118 /* Clock the system from internal HSI RC (8 MHz) */ 00119 rcc_set_clock_source(RCC_SYSCLK_HSI); 00120 00121 /* Enable external oscillator */ 00122 RCC->CR &= CR_HSEON_RESET; 00123 RCC->CR &= CR_HSEBYP_RESET; 00124 RCC->CR |= CR_HSEON_SET; 00125 while (!rcc_get_flag_status(RCC_FLAG_HSERDY)); 00126 00127 /* Initialize PLL according to CPU_FREQ */ 00128 rcc_pll_config(); 00129 while(!rcc_get_flag_status(RCC_FLAG_PLLRDY)); 00130 00131 /* Configure USB clock (48MHz) */ 00132 *CFGR_USBPRE_BB = RCC_USBCLK_PLLCLK_1DIV5; 00133 /* Configure ADC clock: PCLK2 (9MHz) */ 00134 RCC->CFGR &= CFGR_ADCPRE_RESET_MASK; 00135 RCC->CFGR |= RCC_PCLK2_DIV8; 00136 /* Configure system clock dividers: PCLK2 (72MHz) */ 00137 RCC->CFGR &= CFGR_PPRE2_RESET_MASK; 00138 RCC->CFGR |= RCC_HCLK_DIV1 << 3; 00139 /* Configure system clock dividers: PCLK1 (36MHz) */ 00140 RCC->CFGR &= CFGR_PPRE1_RESET_MASK; 00141 RCC->CFGR |= RCC_HCLK_DIV2; 00142 /* Configure system clock dividers: HCLK */ 00143 RCC->CFGR &= CFGR_HPRE_RESET_MASK; 00144 RCC->CFGR |= RCC_SYSCLK_DIV1; 00145 00146 /* Set 1 wait state for the flash memory */ 00147 *(reg32_t *)FLASH_BASE = 0x12; 00148 00149 /* Clock the system from the PLL */ 00150 rcc_set_clock_source(RCC_SYSCLK_PLLCLK); 00151 }