Setting clock to 168MHz on the STM32F407 and enabling MCO1 [bare metal]
Hi,
I'm trying my hand at bare metal programming on the F4 Discovery board. I've been loosely following this code to get the RCC configuration sequence right to set the main sys clock to 168MHz but with my adaptations. I'm able to see 16MHz on MCO1 (PA8). However, I wanted the PLL clock (168MHz) divided by 4 (42MHz) on MCO1. Also, how do I verify that the system clock is indeed 168MHz?
I'm guessing the MCO1 source is defaulting to HSI and not PLLCLK as intended. Or the sys clock in the code below is not getting configured to 168MHz. Any help in debugging this is appreciated.
#include <stdint.h>
#include "stm32f407xx.h"
#if !defined(__SOFT_FP__) && defined(__ARM_FP)
#warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif
#define PLL_M 4U
#define PLL_N 168U
#define PLL_P 2U
//#define PLL_Q 4U
#define LEDDELAY 1000000
void SysClockConfig(void);
int main(void);
uint32_t SystemCoreClock;
int main(void)
{
SysClockConfig();
// Enable clock for AHB1 bus
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOA_CLK_ENABLE;
// Configure PA8 for MCO1
GPIOA->MODER &= ~GPIO_MODER_PIN_8_ALT_FN;
GPIOA->MODER |= GPIO_MODER_PIN_8_ALT_FN;
GPIOA->AFRH |= GPIO_PIN_8_AFN(0);
GPIOA->OTYPER &= ~GPIO_OTYPER_PIN_8_PUSH_PULL;
GPIOA->OTYPER |= GPIO_OTYPER_PIN_8_PUSH_PULL;
GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_PIN_8_VERY_HIGH_SPD;
GPIOA->OSPEEDR |= GPIO_OSPEEDR_PIN_8_VERY_HIGH_SPD;
while (1)
{
//
}
return 0;
}
void SysClockConfig(void)
{
// Use HSE as the Master clock output 1
RCC->CFGR |= RCC_CFGR_MCO1(3U) | RCC_CFGR_MCO1PRE(6U);
/* Enable HSE (CR: bit 16) */
RCC->CR |= RCC_CR_HSE_ON;
/* Wait till HSE is ready (CR: bit 17) */
while (!RCC_CR_HSERDY);
/* Enable power interface clock (APB1ENR:bit 28) */
RCC->APB1ENR |= RCC_APB1ENR_PWR_CLK_ENABLE;
/* set voltage scale to 1 for max frequency (PWR_CR:bit 14)
* (0b0) scale 2 for fCLK <= 144 MHz
* (0b1) scale 1 for 144 MHz < fCLK <= 168 MHz
*/
PWR->CR |= PWR_CR_VOS_SCALE1;
/* set AHB prescaler to /1 (CFGR:bits 7:4) */
RCC->CFGR |= RCC_CFGR_HPRE(1U);
/* set APB1 prescaler to /4 (CFGR:bits 12:10) */
RCC->CFGR |= RCC_CFGR_PPRE1(4U);
/* set APB2 prescaler to /2 (CFGR:bits 15:13) */
RCC->CFGR |= RCC_CFGR_PPRE2(2U);
/* Set PLL dividers */
RCC->PLLCFGR = RCC_PLLCFGR_PLLM(PLL_M) | RCC_PLLCFGR_PLLN(PLL_N) | RCC_PLLCFGR_PLLP(PLL_P) | RCC_PLLCFGR_PLLSRC_HSE;
/* Enable the main PLL (CR: bit 24) */
RCC->CR |= RCC_CR_PLL_ON;
/* Wait till the main PLL is ready (CR: bit 25) */
while (!RCC_CR_PLLRDY);
/* Configure Flash
* prefetch enable (ACR:bit 8)
* instruction cache enable (ACR:bit 9)
* data cache enable (ACR:bit 10)
* set latency to 5 wait states (ARC:bits 2:0)
* see Table 10 on page 80 in RM0090
*/
FLASH->ACR = FLASH_ACR_PREFECTCH_ENABLE | FLASH_ACR_ICEN_ENABLE | FLASH_ACR_DCEN_ENABLE | FLASH_ACR_LATENCY_5_WAIT_STATE;
RCC->CFGR = RCC_CFGR_SW_PLL_AS_SYSCLK;
while (!RCC_CFGR_SWS_STATUS);
// Update SystemCoreClock variable
SystemCoreClock = 168000000;
}