clock_stm32.c
Go to the documentation of this file.00001
00038 #include <cfg/compiler.h>
00039 #include <cfg/debug.h>
00040 #include <io/stm32.h>
00041 #include "clock_stm32.h"
00042
00043 struct RCC *RCC;
00044
00045 INLINE int rcc_get_flag_status(uint32_t flag)
00046 {
00047 uint32_t id;
00048 reg32_t reg;
00049
00050
00051 id = flag >> 5;
00052
00053 if (id == 1)
00054 reg = RCC->CR;
00055
00056 else if (id == 2)
00057 reg = RCC->BDCR;
00058
00059 else
00060 reg = RCC->CSR;
00061
00062 id = flag & FLAG_MASK;
00063
00064 return reg & (1 << id);
00065 }
00066
00067 INLINE uint16_t pll_clock(void)
00068 {
00069 unsigned int div, mul;
00070
00071
00072 for (div = 2; div; div--)
00073 for (mul = 2; mul <= 16; mul++)
00074 if (CPU_FREQ <= (PLL_VCO / div * mul))
00075 break;
00076 return mul << 8 | div;
00077 }
00078
00079 INLINE void rcc_pll_config(void)
00080 {
00081 reg32_t reg = RCC->CFGR & CFGR_PLL_MASK;
00082
00083
00084 uint16_t clock = pll_clock();
00085 uint32_t pll_mul = ((clock >> 8) - 2) << 18;
00086 uint32_t pll_div = ((clock & 0xff) << 1 | 1) << 16;
00087
00088
00089 reg |= pll_div | pll_mul;
00090
00091
00092 RCC->CFGR = reg;
00093
00094
00095 *CR_PLLON_BB = 1;
00096 }
00097
00098 INLINE void rcc_set_clock_source(uint32_t source)
00099 {
00100 reg32_t reg;
00101
00102 reg = RCC->CFGR & CFGR_SW_MASK;
00103 reg |= source;
00104 RCC->CFGR = reg;
00105 }
00106
00107 void clock_init(void)
00108 {
00109
00110 RCC = (struct RCC *)RCC_BASE;
00111
00112
00113 *CR_HSION_BB = 1;
00114 while (!rcc_get_flag_status(RCC_FLAG_HSIRDY));
00115
00116
00117 rcc_set_clock_source(RCC_SYSCLK_HSI);
00118
00119
00120 RCC->CR &= CR_HSEON_RESET;
00121 RCC->CR &= CR_HSEBYP_RESET;
00122 RCC->CR |= CR_HSEON_SET;
00123 while (!rcc_get_flag_status(RCC_FLAG_HSERDY));
00124
00125
00126 rcc_pll_config();
00127 while(!rcc_get_flag_status(RCC_FLAG_PLLRDY));
00128
00129
00130 *CFGR_USBPRE_BB = RCC_USBCLK_PLLCLK_1DIV5;
00131
00132 RCC->CFGR &= CFGR_ADCPRE_RESET_MASK;
00133 RCC->CFGR |= RCC_PCLK2_DIV8;
00134
00135 RCC->CFGR &= CFGR_PPRE2_RESET_MASK;
00136 RCC->CFGR |= RCC_HCLK_DIV1 << 3;
00137
00138 RCC->CFGR &= CFGR_PPRE1_RESET_MASK;
00139 RCC->CFGR |= RCC_HCLK_DIV2;
00140
00141 RCC->CFGR &= CFGR_HPRE_RESET_MASK;
00142 RCC->CFGR |= RCC_SYSCLK_DIV1;
00143
00144
00145 *(reg32_t *)FLASH_BASE = 0x12;
00146
00147
00148 rcc_set_clock_source(RCC_SYSCLK_PLLCLK);
00149 }