2017-08-14 02:13 PM
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,CatSolved! Go to Solution.
2017-08-14 05:58 PM
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) { }...
2017-08-14 05:58 PM
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) { }...
2017-08-15 07:39 AM
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,
Cat2017-08-15 09:49 AM
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.
2017-08-15 10:14 AM
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,
Cat2017-08-15 10:34 AM
I would do it as a single operation. Change the source and wait for it to sync. Any running source would suffice
2017-08-16 01:25 PM
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 sourceRCC->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) { }}