Skip to main content
Cristea.Catalin
Associate II
August 14, 2017
Solved

Need help setting up and enabling Spread Spectrum Clock on STM32F405

  • August 14, 2017
  • 6 replies
  • 4356 views
Posted on August 14, 2017 at 23:13

I need help setting up and enabling (and disabling) the  Spread Spectrum Clock on STM32F405.

AN4850 is not enough, as it has no code example; says nothing about what to do with MODPER and INCSTEP once calculated.

I see file 'stm32f4xx.h' defines some related types/constants but I don't see anything anywhere on how to do it.

Thanks,

Cat
    This topic has been closed for replies.
    Best answer by Tesla DeLorean
    Posted on August 15, 2017 at 02:58

    Add the Spread Spectrum enabling code into system_stm32f4xx.c where you currently enable the PLL

    ie

    ...

    /* Select regulator voltage output Scale 1 mode */

    RCC->APB1ENR |= RCC_APB1ENR_PWREN;

    PWR->CR |= PWR_CR_VOS;

    /* HCLK = SYSCLK / 1*/

    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

    /* PCLK2 = HCLK / 2*/

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

    /* PCLK1 = HCLK / 4*/

    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

    /* Configure the main PLL */

    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |

    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

    /* Enable/Configure Spread Spectrum, when PLL isn't running */

    RCC->SSCGR = (1 << 31) | // Enable

    (0 << 30) | // Center

    (INCSTEP << 13) |

    (MODPER << 0);

    /* Enable the main PLL */

    RCC->CR |= RCC_CR_PLLON;

    /* Wait till the main PLL is ready */

    while((RCC->CR & RCC_CR_PLLRDY) == 0)

    {

    }

    ...

    6 replies

    Tesla DeLorean
    Tesla DeLoreanBest answer
    Guru
    August 15, 2017
    Posted on August 15, 2017 at 02:58

    Add the Spread Spectrum enabling code into system_stm32f4xx.c where you currently enable the PLL

    ie

    ...

    /* Select regulator voltage output Scale 1 mode */

    RCC->APB1ENR |= RCC_APB1ENR_PWREN;

    PWR->CR |= PWR_CR_VOS;

    /* HCLK = SYSCLK / 1*/

    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

    /* PCLK2 = HCLK / 2*/

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

    /* PCLK1 = HCLK / 4*/

    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

    /* Configure the main PLL */

    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |

    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

    /* Enable/Configure Spread Spectrum, when PLL isn't running */

    RCC->SSCGR = (1 << 31) | // Enable

    (0 << 30) | // Center

    (INCSTEP << 13) |

    (MODPER << 0);

    /* Enable the main PLL */

    RCC->CR |= RCC_CR_PLLON;

    /* Wait till the main PLL is ready */

    while((RCC->CR & RCC_CR_PLLRDY) == 0)

    {

    }

    ...

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Cristea.Catalin
    Associate II
    August 15, 2017
    Posted on August 15, 2017 at 16:39

    Thank you Clive; I'll try this.

    I do have a few more questions, if you can, while I try this:

    - Is there any way to do this while running some program?  Even if I need to disable PLL, change SSCGR and re-enable PLL?

    - Can I DIS-able spread spectrum while running some program? Just clear bit 31 or do the whole PLL thing?

    - Can you confirm that USB will stop working if I go SS > 0.25% or something around that?

    Thanks again,

    Cat
    Tesla DeLorean
    Guru
    August 15, 2017
    Posted on August 15, 2017 at 16:49

    You'll need to switch to an alternate clock source, turn off the PLL, adjust the SS settings, turn on the PLL, wait for it to lock, and switch back to it. This is likely to be quite disruptive to the peripherals, etc.

    I'm not looking to confirm/validate this, not my use case, you can read the documentation, and you can experiment. I would imaging USB has a limited tolerance to jitter and modulation.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Cristea.Catalin
    Associate II
    August 15, 2017
    Posted on August 15, 2017 at 17:14

    Would this work to select HSI as the alternate clock source?

        RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));

        RCC->CFGR |= RCC_CFGR_SW_HSI;

    Is the HSI always on, or do Ineed to enable it and wait for it?

    Thanks,

    Cat
    Cristea.Catalin
    Associate II
    August 16, 2017
    Posted on August 16, 2017 at 22:25

    If anybody cares, this is what I ended up with.  Thank you Clive One

    void vSSCG_Init (void)

    {

    //Switch to HSI clock source

        while((RCC->CR & RCC_CR_HSIRDY) == 0){    }                // Wait till HSI is ready

        MODIFY_REG( RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_HSI);

        while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_HSI)    {    }//Wait till the HSI is used as system clock source

        RCC->CR &= ~RCC_CR_PLLON;    //Turn PLL Off

        RCC->SSCGR = (RCC_SSCGR_MODPER    & ui32_myMODPER )

                   | (RCC_SSCGR_INCSTEP    & ui32_myINCSTEP)

     //              | RCC_SSCGR_SPREADSEL // remove this line to use center spread mode rather than down spread mode

                   | RCC_SSCGR_SSCGEN;

                   

        RCC->CR |= RCC_CR_PLLON;    //Turn PLL On

    //Switch to PLL clock source

        while((RCC->CR & RCC_CR_PLLRDY) == 0)    {    }    //Wait till the main PLL is ready

        MODIFY_REG( RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL);

         while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL)    {    }

    }