2014-02-13 12:41 PM
I have the STM32F303 on a custom board with an external clock. For testing firmware development, I'm using the STM32F3 Discovery board, also with an external clock.
We need to run at 72MHz, so we use the PLL with the external clock (HSE)./**
* @brief Setup the microcontroller system
* Initialize the Embedded Flash Interface, the PLL and update the
* SystemFrequency variable.
* @param None
* @retval None
*/
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL <<
10
*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset CFGR register */
RCC->CFGR &= 0xF87FC00C;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
/* Reset PREDIV1[3:0] bits */
RCC->CFGR2 &= (uint32_t)0xFFFFFFF0;
/* Reset USARTSW[1:0], I2CSW and TIMs bits */
RCC->CFGR3 &= (uint32_t)0xFF00FCCC;
/* Disable all interrupts */
RCC->CIR = 0x00000000;
/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
/* Set the system clock source
*/
SetSysClock_PLL();
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
/**
* @brief Configures the System clock source, PLL Multiplier and Divider factors,
* AHB/APBx prescalers and Flash settings
* @note This function should be called only once the RCC clock configuration
* is reset to the default reset state (done in SystemInit() function).
* @param None
* @retval None
*/
void SetSysClock_PLL(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
SystemCoreClock = 72000000;
/******************************************************************************/
/* PLL (clocked by HSE) used as System clock source */
/******************************************************************************/
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------*/
/* Enable HSE */
#ifdef CUSTOM_BOARD
RCC->CR |= ((uint32_t)RCC_CR_HSEON | (uint32_t) RCC_CR_HSEBYP);
#else
RCC->CR |= ((uint32_t)RCC_CR_HSEON); /* HSE bypass is not required on the stm32f3 discovery board */
#endif
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer and set Flash Latency */
FLASH->ACR = (uint32_t)(FLASH_ACR_PRFTBE | FLASH_Latency_2);
/* HCLK = SYSCLK / 1 */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK / 2 */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV2;
/* PCLK1 = HCLK / 2 */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
/* PLL configuration */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL3);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while(!(RCC->CR & RCC_CR_PLLRDY));
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
In the SetSycClock_PLL function, we first enable the HSE using the RCC clock control register. The mystery is in this step: on the discovery board, we do NOT need to set the HSE bypass bit(
RCC_CR_HSEBYP)
. This seems to be necessary on the custom board, otherwise HSE fails to stabilize and the system falls back to the 8MHz HSI clock.
Is there any insight to this behavior based on the software configuration? #stm32f3-pll-hse-clock2014-02-13 01:34 PM
Ok, so does your board have a crystal or an external source (tcxo, oscillator)
The BYPASS should be used on the STM32F3-DISCO because it doesn't have a crystal placed on the board, and derives it's clock from the PA8 (MCO, HSE) output of the F103 used for the ST-LINK function. If your board has a crystal, and it doesn't oscillate, then you'll need to review the component parameters and parts used. BYPASS controls if OSC_OUT is driven or NOT2014-02-13 03:26 PM
Hi Clive.
We placed an external crystal oscillator on the discovery board to run at 72MHz. The custom board has an external clock source. Not a crystal.
So this behavior is expected. HSEBYP is necessary on the custom board to bypass the signal driving the external resonator (because it doesn't exist).This is described in the External Source (HSE bypass) paragraph in section 7.2.1 of the reference manual. I've read this but didn't understand until seeing your explanation. Thanks.2014-10-12 02:34 AM
I have similar question about HSE bypass.
I begit to use stm32cubemx softeware with f3discovery board.f303 is clocked from f103 and generated code from cubemx should contain a line that selects bypass mode. But thereisn't such thing in code. Independently which mode I select RCC IP: HSE disabled or HSE bypass or even ''crystal'' - generated .c files are identical. void SystemClock_Config(void){ RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); __SYSCFG_CLK_ENABLE();}It looks like cubemx generates code that uses HSI, even if PF0 marked as osc_in.Could you please run cubemx and inspect generated code for f3disc?2014-10-12 06:41 AM
Could you please run cubemx and inspect generated code for f3disc?
Yeah, I'm not doing that. You need to use HAL_RCC_OscConfig() to set up the HSE/PLL, and you will need to adjust the wait states for the flash to operate at 72 MHzhttp://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/DM00116575.pdf