clock_stm32.c
Go to the documentation of this file.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
00053 id = flag >> 5;
00054
00055 if (id == 1)
00056 reg = RCC->CR;
00057
00058 else if (id == 2)
00059 reg = RCC->BDCR;
00060
00061 else
00062 reg = RCC->CSR;
00063
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
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
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
00091 reg |= pll_div | pll_mul;
00092
00093
00094 RCC->CFGR = reg;
00095
00096
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
00112 RCC = (struct RCC *)RCC_BASE;
00113
00114
00115 *CR_HSION_BB = 1;
00116 while (!rcc_get_flag_status(RCC_FLAG_HSIRDY));
00117
00118
00119 rcc_set_clock_source(RCC_SYSCLK_HSI);
00120
00121
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
00128 rcc_pll_config();
00129 while(!rcc_get_flag_status(RCC_FLAG_PLLRDY));
00130
00131
00132 *CFGR_USBPRE_BB = RCC_USBCLK_PLLCLK_1DIV5;
00133
00134 RCC->CFGR &= CFGR_ADCPRE_RESET_MASK;
00135 RCC->CFGR |= RCC_PCLK2_DIV8;
00136
00137 RCC->CFGR &= CFGR_PPRE2_RESET_MASK;
00138 RCC->CFGR |= RCC_HCLK_DIV1 << 3;
00139
00140 RCC->CFGR &= CFGR_PPRE1_RESET_MASK;
00141 RCC->CFGR |= RCC_HCLK_DIV2;
00142
00143 RCC->CFGR &= CFGR_HPRE_RESET_MASK;
00144 RCC->CFGR |= RCC_SYSCLK_DIV1;
00145
00146
00147 *(reg32_t *)FLASH_BASE = 0x12;
00148
00149
00150 rcc_set_clock_source(RCC_SYSCLK_PLLCLK);
00151 }