0
\$\begingroup\$

I was doing PLL configuration to run my STM32F103RCT6 at 72MHz. I am using CMSIS Library and hence I took help from standard peripheral library to write this code. I am getting certain doubts which i would like to get answer form.

First of all my code.

/* Project: PLL Configuration (72 MHz)
 * Author : Devjeet Mandal   
 * Date   : 13/2/2018       20:27
 * 
 */


 #include "stm32f10x.h"

 #define HPRE_RESET_MASK        ((uint32_t)0xFFFFFF0F)
 #define PPRE2_RESET_MASK       ((uint32_t)0xFFFFC7FF)
 #define PPRE1_RESET_MASK       ((uint32_t)0xFFFFF8FF)
 #define PLLCLK_CONFIG_RESET_MASK   ((uint32_t)0xFFC0FFFF)
 #define SW_RESET_MASK          ((uint32_t)0xFFFFFFFC)


 #define LED_PORT_EN()      ( RCC->APB2ENR |= RCC_APB2ENR_IOPDEN )
 #define LED_PORT           GPIOD

 #define LED_MODE_BIT1          8
 #define LED_MODE_BIT2          9
 #define LED_CNF_BIT1           10
 #define LED_CNF_BIT2           11


 #define CNF_SET_PORTD(BIT1,BIT2)   (   LED_PORT->CRL &= ~((1<<BIT1) | (1<<BIT2)) )                 //General purpose output push-pull
 #define MODE_SET_PORTD(BIT1,BIT2)  ( LED_PORT->CRL |=  (1<<BIT1) | (1<<BIT2) )                     //Output mode, max speed 50 MHz.

 #define SET_GPIO_BIT_PORTD(BIT)    ( LED_PORT->BSRR =  (1 << BIT) )                                            //For setting the Bit   
 #define RESET_GPIO_BIT_PORTD(BIT)  ( LED_PORT->BSRR =  ( (1 << BIT) << 16 )    )                       //For Resseting Bit




 void PLL_Config(void);
 void Clock_Reset(void);
 void HCLK_Config(uint32_t RCC_SYSCLK);
 void PCLK2_Config(uint32_t RCC_HCLK);
 void PCLK1_Config(uint32_t RCC_HCLK);
 void PLLCLK_Config(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul); 
 void SYSCLK_Config(uint32_t RCC_SYSCLKSource);
 void Delay(int ms);
 void Led_Init(void);
 void Blink_Led(int ms);



 int main(void)
 {
     PLL_Config();
     Led_Init();
     while(1)
     {
         Blink_Led(1000);
     }
 }


 /** @breif: For wait and doing nothing i.e for delay
     * @param: delaya time
     * @retVal: None
   */


    void Delay(int ms)
    {
        int i,j; 
        for (i = 0; i < ms; ++i) {
            for (j = 0; j < 1000; ++j);
            }
    }


 /** @breif: Initalize GPIO For Led
     * @param: None
     * @retVal: None
   */


    void Led_Init()
    {
        LED_PORT_EN();          //Enable RCC for Led Port
        CNF_SET_PORTD(LED_CNF_BIT1,LED_CNF_BIT2);   //SET CNF       General purpose output push-pull
        MODE_SET_PORTD(LED_MODE_BIT1,LED_MODE_BIT2); //SET MODE  Output mode, max speed 50 MHz. 
    }


 /** @breif: Blink Led Placed in PORT D Pin 2
     * @param: Delay for each state(ON/OFF)
     * @retVal: None
   */


    void Blink_Led(int ms)
    {
        RESET_GPIO_BIT_PORTD(2);            //Make Led High
        Delay(ms);                          //wait
        SET_GPIO_BIT_PORTD(2);              //Make Led Low
        Delay(ms);                          //wait
    }

 /** @breif: Configure PLL 72 MHz
     * @param: None
     * @retVal: None
   */

 void PLL_Config(void)
 {
     Clock_Reset();                     //RESET Clock
     RCC->CR    |=  RCC_CR_HSEON;       //ENABLE HSE

     /* wait till HSE Ready */
     while ( !( RCC->CR & RCC_CR_HSERDY ));

     /* Doubt: Enable Prefetch Buffer */
   /* Doubt: Flash 2 wait state     */   

     HCLK_Config(RCC_CFGR_HPRE_DIV1);   //configure HCLK  AHB clock
     PCLK2_Config(RCC_CFGR_PPRE2_DIV1); //cofigure PCLK2  APB2 clock
     PCLK1_Config(RCC_CFGR_PPRE1_DIV2); //configure PCLK1 APB1 clock
     PLLCLK_Config(RCC_CFGR_PLLSRC, RCC_CFGR_PLLMULL9); //configure PLLCLK 72MHz

     RCC->CR |= RCC_CR_PLLON;           //ENABLE PLL

     /* Wait till PLL is Ready */
     while (!(RCC->CR & RCC_CR_PLLRDY));

     SYSCLK_Config(RCC_CFGR_SW_PLL);

     /* wait till PLL is used as system clock */
     while (!(RCC->CFGR & RCC_CFGR_SWS_PLL));

 }


 /** @breif: Select PLL as system clock source
     * @param: RCC_CFGR_SW_PLL = ((uint32_t)0x00000002)
     * @retVal: None
   */

 void SYSCLK_Config(uint32_t RCC_SYSCLKSource)
 {
        uint32_t tmpreg = 0;

        tmpreg = RCC->CFGR;
        /* Clear SW[1:0] bits */
        tmpreg &= SW_RESET_MASK;
        /* Set SW[1:0] bits according to RCC_SYSCLKSource value */
        tmpreg |= RCC_SYSCLKSource;
        /* Store the new value */
        RCC->CFGR = tmpreg;
 }



 /** @breif: Set PCLK1 = HCLK/2
   *         HCLK divided by 2
     * @param: RCC_CFGR_PLLSRC = ((uint32_t)0x00010000)
   * @param: RCC_CFGR_PLLMULL9 = ((uint32_t)0x001C0000)
     * @retVal: None
   */
 void PLLCLK_Config(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul)
 {
      uint32_t tmpreg = 0;

        tmpreg = RCC->CFGR;
        /* Clear PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */
        tmpreg &= PLLCLK_CONFIG_RESET_MASK;
        /* Set the PLL configuration bits */
        tmpreg |= RCC_PLLSource | RCC_PLLMul;
        /* Store the new value */
        RCC->CFGR = tmpreg;
 }


 /** @breif: Set PCLK1 = HCLK/2
   *         HCLK divided by 2
     * @param: RCC_CFGR_PPRE1_DIV2 = ((uint32_t)0x00000400)
     * @retVal: None
   */ 

 void PCLK1_Config(uint32_t RCC_HCLK)
 {
   uint32_t tmpreg = 0;

   tmpreg = RCC->CFGR;
   /* Clear PPRE1[2:0] bits */
   tmpreg &= PPRE1_RESET_MASK;
   /* Set PPRE1[2:0] bits according to RCC_HCLK value */
   tmpreg |= RCC_HCLK;
   /* Store the new value */
   RCC->CFGR = tmpreg;
 }




 /** @breif: Set PCLK2 = HCLK
   *         HCLK not divided
     * @param: RCC_CFGR_PPRE2_DIV1 = ((uint32_t)0x00000000)
     * @retVal: None
   */ 

 void PCLK2_Config(uint32_t RCC_HCLK)
 {
   uint32_t tmpreg = 0;

   tmpreg = RCC->CFGR;
   /* Clear PPRE2[2:0] bits */
   tmpreg &= PPRE2_RESET_MASK;
   /* Set PPRE2[2:0] bits according to RCC_HCLK value */
   tmpreg |= RCC_HCLK;
   /* Store the new value */
   RCC->CFGR = tmpreg;
 }


 /** @breif: Set HCLK = SYSCLK
   *         SYSCLK not divided
     * @param: RCC_CFGR_HPRE_DIV1 = ((uint32_t)0x00000000)
     * @retVal: None
   */

  void HCLK_Config(uint32_t RCC_SYSCLK)
    {
        uint32_t tmpreg = 0;

        tmpreg = RCC->CFGR;
        /* Clear HPRE[3:0] bits */
        tmpreg &= HPRE_RESET_MASK;
        /* Set HPRE[3:0] bits according to RCC_SYSCLK value */
        tmpreg |= RCC_SYSCLK;
        /* Store the new value */
        RCC->CFGR = tmpreg;
    }



 /** @breif: Resets the Clock
     * @param: None
     * @retVal: None
   */
 void Clock_Reset(void)
 {
   /* Set HSION bit */
   RCC->CR |= (uint32_t)0x00000001;

   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
   RCC->CFGR &= (uint32_t)0xF0FF0000;  

   /* 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/OTGFSPRE bits */
   RCC->CFGR &= (uint32_t)0xFF80FFFF;

   /* Disable all interrupts and clear pending bits  */
   RCC->CIR = 0x009F0000;
 }

Doubts:

  1. While configuring the PLL i saw there was two line "Enable Prefetch Buffer" and "Flash 2 wait state" which was there in standard peripheral library. What does this lines mean and why i need to do this? How this lines will effect my PLL Configuration?

  2. If i don't set up PLL my system will run on 8MHz i.e the crystal provided on board,right??

  3. Here i Blink an LED after configuring PLL. But while configuring LED we need to set MODE, which is "Output mode, max speed 50 MHz." according to USER MANUAL. So how my PLL setup is affecting Blinking of LED? Is my Led operating on 72MHz or 50MHz?

  4. Is this code sets system clock at 72MHz? Is there any easy way to know at what frequency my system is operating?

I will be doing Timers and USART after this and i believe PLL setup is required for that. Any suggestions will be really helpful.

Thanks in advance

\$\endgroup\$
0
\$\begingroup\$

1) The flash isn't as fast as the processor, so you need to insert 'wait states' when reading it. The number required depends on how fast you're running the processor. The number you need is described in section 3.3.3 Embedded Flash memory (page 57) of the reference manual. The prefetch buffer is similar to a cache, and prefetches some flash so it's available to the cpu without blocking for a flash read.

2) Not necessarily, it will run on whichever clock you set it to run from in the RCC block, the default is an internal high speed oscillator (8 MHz I believe on that part), to use an external crystal you need to enable it and wait for it to become stable, this is managed by the RCC 'peripheral' in the IC, and described in the above mentioned reference manual in the RCC section.

3) The 50MHz there is referring to the the pin toggling speed, not the PLL or system clock speed. The GPIO peripheral runs from a seperate clock to the processor, the APB2 clock, which is ultimately derived from the system clock and can run up to 72 MHz.

4) I haven't been through your PLL configuration very closely, but there is a mismatch between comments and code on the lines

PCLK2_Config(RCC_CFGR_PPRE2_DIV1); //cofigure PCLK2  APB2 clock
PCLK2_Config(RCC_CFGR_PPRE1_DIV2); //configure PCLK1 APB1 clock

They're both setting the APB2 clock, rather than setting APB1 and APB2.

The easiest way to confirm how fast you're running is to configure the MCO, main clock out to be the sysclk, and have a look at it with an oscilloscope.

The reference manual is quite big and daunting, but is worth studying, most questions about the processor can be answered with it.

\$\endgroup\$
  • \$\begingroup\$ Thank you for your help in reference to my question 1. i wanted to know why we r doing flash prefetch? what is the significance of that with PLL setup? How it is effecting PLL Setup? Thanks again and there was a was a typo on PCLK2_Config it should be PCLK1_Config i have corrected it \$\endgroup\$ – Devjeet Mandal Feb 14 '18 at 9:03
  • \$\begingroup\$ The flash prefetch is separate to the PLL. The issue is that when clocking the processor from the PLL, it's possible to run the processor quicker than the flash can manage, the prefetch helps mitigate against this, by providing faster access for sequential flash reads. It's not essential, and you could run without it, but there's no reason to. Without using the PLL the prefetch isn't required as you aren't running the processor as quickly. \$\endgroup\$ – Colin Feb 14 '18 at 9:05
  • \$\begingroup\$ can you answer stackoverflow.com/questions/48644637/… \$\endgroup\$ – Devjeet Mandal Feb 14 '18 at 9:12
  • \$\begingroup\$ I doubt Delay works as expected (probably is much faster, if not optimized out). \$\endgroup\$ – Michel Keijzers Feb 14 '18 at 9:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.