cancel
Showing results for 
Search instead for 
Did you mean: 

Nucleo STM32F401

dizarker
Associate II
Posted on August 30, 2014 at 22:25

Problem with oscillator source PLL.

Nucleo plate does't have HSE oscillator, and use internal 16 MHz HSI

I want to reconfigure tacting schematic to use as SYSCLK - PLL (by default for SYSCLK use HSI directly)

PLL configuration - M = 16, N = 366, P = 4. Q = 7

Here the code (use Keil v5)

int main (void)

{

GPIO_InitTypeDef sGPIO;

// Set PLL source to HSI, M div = 16, N mul = 336, P div = 4, Q div = 7

// HSI = 16 MHz, after M div - 1 MHz, after mul - 336 MHz, PLL - /4 = 84 MHz, USB - /7 - 48 MHz

RCC_PLLConfig (RCC_PLLSource_HSI, 16, 336, 4, 7);

// Turn on PLL and wait for PLL lock

RCC->CR |= RCC_CR_PLLON;

while (!(RCC->CR & RCC_CR_PLLRDY));

// Set AHB Prescaller /1, APB1 Prescaller /2

RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;

// Set system clock to PLL and wait for RDY flag

RCC->CFGR |= RCC_CFGR_SW_1;

while (!(RCC->CFGR & RCC_CFGR_SWS_1));

// Allow clocks

RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);

RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2, ENABLE);

// Config GPIO pin

sGPIO.GPIO_Mode = GPIO_Mode_OUT;

sGPIO.GPIO_OType = GPIO_OType_PP;

sGPIO.GPIO_Pin = GPIO_Pin_5;

sGPIO.GPIO_Speed = GPIO_Speed_50MHz;

sGPIO.GPIO_PuPd = GPIO_PuPd_DOWN;

GPIO_Init (GPIOA, &sGPIO);

while (1)

{

__nop ();

__nop ();

__nop ();

}

}

In debug - after switch to SYSCLK to PLL - program drop to handler

If i set AHB prescaller to /2 - all Ok, but this is not maximum speed.

What is wrong in my clock initialization?

#nucleo-rcc
5 REPLIES 5
Posted on August 31, 2014 at 04:46

You might want to pay attention to what's actually in the registers before you arbitrarily OR bits into them.

The CMSIS model normally calls SystemInit() to set up the clocks prior to main() being called.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dizarker
Associate II
Posted on August 31, 2014 at 12:26

CMSIS startup turn on the HSI, and HSE. After timeout (because plate don't have HSE, and flag HSE RDY not set) SYSCLK switch to HSI directly.

I need the timer clk not lower 50 MHz, therefore i need the SYSCLK from PLL

In first screenshot - RCC regs after startup: HSI on, HSI ready, HSE on, HSE not ready, PLL off. SW bits - 00 (SYSCLK is HSI)

0690X00000603IHQAY.jpg

Second screenshot - set the PLL configuration. M = 16, N = 366, P = 4, Q = 7

PLL On and PLL ready

0690X00000603I7QAI.jpg

Last screenshot - after execute command RCC->CFGR |= RCC_CFGR_SW_1;

after this program fall to handler (in disassemble window infinite sequence MOVS r0, r0)

0690X00000603ICQAY.jpg

Posted on August 31, 2014 at 13:02

HSE should be viable in BYPASS mode using the 8 MHz output of the ST-LINK and SB16/SB50, etc

Might want to look at flash wait states, and aforementioned SystemInit() in system_stm32f40x.c
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dizarker
Associate II
Posted on August 31, 2014 at 20:03

Flash latency after startup set to 0

If I change this to one wait state all be work.

Thank you
Posted on August 31, 2014 at 20:08

I'd think at 84 MHz you'd want 2 wait states (3 cycles) for the flash access to meet specifications.

/**
* @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
*/
static void SetSysClock(void)
{
/******************************************************************************/
/* PLL used as System clock source */
/******************************************************************************/
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
#ifdef PLL_SOURCE_HSI
/* Enable HSI */
RCC->CR |= ((uint32_t)RCC_CR_HSION);
/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 
6
) | (((PLL_P >> 1) -1) << 
16
) |
(RCC_PLLCFGR_PLLSRC_HSI) | (PLL_Q << 24);
#else /* PLL_SOURCE_HSE_BYPASS or PLL_SOURCE_HSE */
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
#if defined (PLL_SOURCE_HSE_BYPASS)
/* HSE oscillator bypassed with external clock */
RCC->CR |= (uint32_t)(RCC_CR_HSEBYP);
#endif /* PLL_SOURCE_HSE_BYPASS */
/* 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)
{
/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 
6
) | (((PLL_P >> 1) -1) << 
16
) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
}
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 */
}
#endif /* PLL_SOURCE_HSI */
/* Select regulator voltage output Scale 2 mode, System frequency up to 84 MHz */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR &= (uint32_t)~(PWR_CR_VOS);
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK / 1*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till the main PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH->ACR = FLASH_ACR_PRFTEN |FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;
/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;
/* Wait till the main PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
{
}
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..