コード例 #1
0
static uint32_t pll_start(uint32_t crystal, uint32_t frequency)
{
	uint32_t div, mul, div_core, vco_input_frequency, vco_output_frequency, frequency_core;
	uint32_t best_div = 0, best_mul = 0, best_div_core = 0, best_frequency_core = 0;

	RCC_CR_HSEON_bb = 1;					// enable HSE clock
	flash_latency(frequency);				// configure Flash latency for desired frequency

	for (div = 2; div <= 63; div++)			// PLLM in [2; 63]
	{
		vco_input_frequency = crystal / div;

		if ((vco_input_frequency < 1000000ul) || (vco_input_frequency > 2000000))	// skip invalid settings
			continue;

		for (mul = 64; mul <= 432; mul++)	// PLLN in [64; 432]
		{
			vco_output_frequency = vco_input_frequency * mul;

			if ((vco_output_frequency < 64000000ul) || (vco_output_frequency > 432000000ul))	// skip invalid settings
				continue;

			for (div_core = 2; div_core <= 8; div_core += 2)	// PLLP in {2, 4, 6, 8}
			{
				frequency_core = vco_output_frequency / div_core;

				if (frequency_core > frequency)	// skip values over desired frequency
					continue;

				if (frequency_core > best_frequency_core)	// is this configuration better than previous one?
				{
					best_frequency_core = frequency_core;	// yes - save values
					best_div = div;
					best_mul = mul;
					best_div_core = div_core;
				}
			}
		}
	}

	RCC->PLLCFGR = (best_div << RCC_PLLCFGR_PLLM_bit) | (best_mul << RCC_PLLCFGR_PLLN_bit) | ((best_div_core / 2 - 1) << RCC_PLLCFGR_PLLP_bit) | RCC_PLLCFGR_PLLQ_DIV7 | RCC_PLLCFGR_PLLSRC_HSE;	// configure PLL factors, always divide USB clock by 9

	RCC->CFGR = RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_HPRE_DIV1;	// AHB - no prescaler, APB1 - divide by 4, APB2 - divide by 2

	while (!RCC_CR_HSERDY_bb);				// wait for stable clock

	RCC_CR_PLLON_bb = 1;					// enable PLL
	while (!RCC_CR_PLLRDY_bb);				// wait for PLL lock

	RCC->CFGR |= RCC_CFGR_SW_PLL;			// change SYSCLK to PLL
	while (((RCC->CFGR) & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);	// wait for switch

	return best_frequency_core;
}
コード例 #2
0
ファイル: system.c プロジェクト: JamesLinus/UniSP-firmware
/**
 * @brief Starts the PLL
 * @details Configure and enable PLL to achieve some frequency with some crystal.
 * Before the speed change Flash latency is configured via flash_latency(). PLL
 * parameters are based on both function parameters. The PLL is set up,
 * started and connected. AHB clock ratio is set to 1:1 with core clock, APB1 -
 * 1:2 (max 36MHz), APB2 - 1:1 (max 72MHz).
 *
 * @param [in] crystal is the frequency of the crystal resonator connected to the
 * STM32F334X8
 * @param [in] frequency is the desired target frequency after enabling the PLL (max 72MHz)
 *
 * @return real frequency that was set
 **/
uint32_t pll_start(uint32_t crystal, uint32_t frequency){

    volatile uint32_t mul, pll_in, pll_out;
    volatile uint32_t best_mul=0, pll_out_best=0;

#ifdef OSC_EXTERNAL
    volatile uint32_t div;
    volatile uint32_t best_div=0;

    RCC->CR |= RCC_CR_HSEON; // enable HSE

    flash_latency(frequency);				// configure Flash latency for desired frequency

    for(div =1; div<=16; div+=1) { //PREDIV [0:16]
        pll_in = crystal/div;

        for(mul=2; mul<=16; mul+=1){ //PLLMUL[2:16]
            pll_out = pll_in * mul;

            if((pll_out > 72000000ul) || (pll_out < 16000000ul)) // skip invalid value
                continue;

            if(pll_out > frequency) // skip value over desired frequnecy
                continue;

            if(pll_out > pll_out_best){
                pll_out_best = pll_out;
                best_mul = mul;
                best_div = div;
            }
        }
    }

    // configure PLL factors
    RCC->CFGR |=  ((best_mul-2) << RCC_CFGR_PLLMUL_bit); // set PLL multification factor
    RCC->CFGR2 |= ((best_div-1) << RCC_CFGR2_PREDIV_bit); // set HSE divider to PLL
    RCC->CFGR |= RCC_CFGR_PLLSRC;           // HSE/PRESCALER clk source
    while(!(RCC->CR & RCC_CR_HSERDY));      // wait for stable clock

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_HPRE_DIV1;	/// AHB - no prescaler, APB1 - divide by 4, APB2 - divide by 1
    RCC->CR |= RCC_CR_PLLON;				// enable PLL
    while(!(RCC->CR & RCC_CR_PLLRDY));   	// wait for PLL lock

    RCC->CFGR |= RCC_CFGR_SW_PLL;			// change SYSCLK to PLL
    while (((RCC->CFGR) & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);	// wait for switch

    return pll_out_best;

#else
    RCC->CR |= RCC_CR_HSION; // enable HSI

    flash_latency(frequency);				// configure Flash latency for desired frequency

    pll_in = crystal/2;

    for(mul=2; mul<=16; mul+=1){ //PLLMUL[2:16]
        pll_out = pll_in * mul;

        if((pll_out > 72000000ul) || (pll_out < 16000000ul)) // skip invalid value
            continue;

        if(pll_out > frequency) // skip value over desired frequnecy
            continue;

        if(pll_out > pll_out_best){
            pll_out_best = pll_out;
            best_mul = mul;
        }
    }

// configure PLL factors
    RCC->CFGR |=  ((best_mul-2) << RCC_CFGR_PLLMUL_bit); // set PLL multification factor

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_HPRE_DIV1;	/// AHB - no prescaler, APB1 - divide by 4, APB2 - divide by 1
    RCC->CR |= RCC_CR_PLLON;				// enable PLL
    while(!(RCC->CR & RCC_CR_PLLRDY));   	// wait for PLL lock

    RCC->CFGR |= RCC_CFGR_SW_PLL;			// change SYSCLK to PLL
    while (((RCC->CFGR) & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);	// wait for switch

    return pll_out_best;

#endif

}