openmv/src/omv/rcc_ctrl.c
2014-06-14 12:28:45 +02:00

75 lines
2.1 KiB
C

#include <stdint.h>
#include <stm32f4xx.h>
#include <stm32f4xx_rcc.h>
#include "rcc_ctrl.h"
void rcc_ctrl_set_frequency(enum sysclk_freq freq)
{
int freqs[] = {42, 84, 168, 200, 240};
/* USB freqs: 42MHz, 42Mhz, 48MHz, 50MHz, 48MHz */
int pll_div[] = {2, 4, 7, 8, 10};
/* PLL_VCO = (HSE_VALUE / PLL_M) * PLL_N */
/* SYSCLK = PLL_VCO / PLL_P */
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
uint32_t PLL_P = 2;
uint32_t PLL_N = freqs[freq] * 2;
uint32_t PLL_M = (HSE_VALUE/1000000);
uint32_t PLL_Q = pll_div[freq];
RCC_DeInit();
/* Enable HSE osscilator */
RCC_HSEConfig(RCC_HSE_ON);
if (RCC_WaitForHSEStartUp() == ERROR) {
return;
}
/* Configure PLL clock M, N, P, and Q dividers */
RCC_PLLConfig(RCC_PLLSource_HSE, PLL_M, PLL_N, PLL_P, PLL_Q);
/* Enable PLL clock */
RCC_PLLCmd(ENABLE);
/* Wait until PLL clock is stable */
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
/* Set PLL_CLK as system clock source SYSCLK */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Set AHB clock divider */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* Set APBx clock dividers */
switch (freq) {
/* Max freq APB1: 42MHz APB2: 84MHz */
case SYSCLK_42_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div1); /* 42MHz */
RCC_PCLK2Config(RCC_HCLK_Div1); /* 42MHz */
break;
case SYSCLK_84_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div2); /* 42MHz */
RCC_PCLK2Config(RCC_HCLK_Div1); /* 84MHz */
break;
case SYSCLK_168_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div4); /* 42MHz */
RCC_PCLK2Config(RCC_HCLK_Div2); /* 84MHz */
break;
case SYSCLK_200_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div4); /* 50MHz */
RCC_PCLK2Config(RCC_HCLK_Div2); /* 100MHz */
break;
case SYSCLK_240_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div4); /* 60MHz */
RCC_PCLK2Config(RCC_HCLK_Div2); /* 120MHz */
break;
}
/* Update SystemCoreClock variable */
SystemCoreClockUpdate();
}