STM32H7 series spread-spectrum clock generation (SSCG)
- October 29, 2024
- 5 replies
- 4014 views
Summary
The main objective of this article is to present the STM32H7 spread-spectrum clock generation (SSCG) feature. STM32H7 differs from other series by using PLL fractional with Timer/DMA. For an overall introduction to spread-spectrum clock generation, refer to Application note 4850.
1. STM32H7 SSCG implementation using PLL fractional with Timer/DMA
STM32H7 series have a PLL fractional (phase-locked loop) which can be updated from a DMA buffer driven by a timer.
Figure 1. STM32H7 PLL fractional block diagram from the reference manuals PLL description chapter
The STM32H7 product series does not have a built-in spread-spectrum clock generation feature.
It uses Timer/DMA as a method instead. The idea is to use a table with predetermined values which will represent the type of modulation needed (for example a triangular waveform). We use this table and inject the values into the sigma delta modulator of the PLL. With the appropriate setup and sequence, the frequency of the clock changes over time. Figure 3 below shows an example.
Figure 2. Timer/DMA technique overview
Buffer containing the modulating signal declaration:
uint32_t PLLCFGR_Buffer[2] ={
0x70008, /*Value for PLLFCT OFF */
0x70008 /*Value for PLLFCT ON */
};
uint32_t PLL1FRACR_Buffer[32] ={
0x0000<<3,0x01FF<<3,0x03FF<<3,0x05FF<<3,0x07FF<<3,0x09FF<<3,0x0BFF<<3,0x0DFF<<3,
0x0FFF<<3,0x11FF<<3,0x13FF<<3,0x15FF<<3,0x17FF<<3,0x19FF<<3,0x1BFF<<3,0x1DFF<<3, 0x1FFF<<3,0x1DFF<<3,0x1BFF<<3,0x19FF<<3,0x17FF<<3,0x15FF<<3,0x13FF<<3,0x11FF<<3, 0x0FFF<<3,0x0DFF<<3,0x0BFF<<3,0x09FF<<3,0x07FF<<3,0x05FF<<3,0x03FF<<3,0x01FF<<3
};Firmware example to start the SSCG with the PLL fractional / timer and DMA peripherals:
/* Enable BDMA clock */
__HAL_RCC_BDMA_CLK_ENABLE();
/* Configure the DMA handler for Transmission process */
/* DMA mode is set to circular for an infinite DMA transfer */
DMA_Handle.Instance = BDMA_Channel0;
DMA_Handle.Init.Request = BDMA_REQUEST_GENERATOR0;
DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;
DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
DMA_Handle.Init.Mode = DMA_CIRCULAR;
DMA_Handle.Init.Priority = DMA_PRIORITY_LOW;
DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE;
DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;
/* Initialize the DMA with for Transmission process */
HAL_DMA_Init(&DMA_Handle);
/* Select Callbacks functions called after Transfer complete and Transfer error */
HAL_DMA_RegisterCallback(&DMA_Handle, HAL_DMA_XFER_CPLT_CB_ID, NULL);
HAL_DMA_RegisterCallback(&DMA_Handle, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
/* NVIC configuration for DMA transfer complete interrupt*/
HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
/*##-3- Configure and enable the DMAMUX Request generator ####################*/
dmamux_ReqGenParams.SignalID = HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT; /* External request signal is LPTIM2 signal */
dmamux_ReqGenParams.Polarity = HAL_DMAMUX_REQ_GEN_RISING; /* External request signal edge is Rising */
dmamux_ReqGenParams.RequestNumber = 1; /* 1 requests on each edge of the external request signal */
HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle, &dmamux_ReqGenParams);
/* NVIC configuration for DMAMUX request generator overrun errors*/
HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle);
DMA_Handle2.Instance = BDMA_Channel1;
DMA_Handle2.Init.Request = BDMA_REQUEST_GENERATOR1;
DMA_Handle2.Init.Direction = DMA_MEMORY_TO_PERIPH;
DMA_Handle2.Init.PeriphInc = DMA_PINC_DISABLE;
DMA_Handle2.Init.MemInc = DMA_MINC_ENABLE;
DMA_Handle2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
DMA_Handle2.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
DMA_Handle2.Init.Mode = DMA_CIRCULAR;
DMA_Handle2.Init.Priority = DMA_PRIORITY_LOW;
DMA_Handle2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
DMA_Handle2.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
DMA_Handle2.Init.MemBurst = DMA_MBURST_SINGLE;
DMA_Handle2.Init.PeriphBurst = DMA_PBURST_SINGLE;
/* Initialize the DMA with for Transmission process */
HAL_DMA_Init(&DMA_Handle2);
/* Select Callbacks functions called after Transfer complete and Transfer error */
HAL_DMA_RegisterCallback(&DMA_Handle2, HAL_DMA_XFER_CPLT_CB_ID, NULL);
HAL_DMA_RegisterCallback(&DMA_Handle2, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
/* NVIC configuration for DMA transfer complete interrupt*/
HAL_NVIC_SetPriority(BDMA_Channel1_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(BDMA_Channel1_IRQn);
/*##-3- Configure and enable the DMAMUX Request generator ####################*/
dmamux_ReqGenParams.SignalID = HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT; /* External request signal is LPTIM2 signal */
dmamux_ReqGenParams.Polarity = HAL_DMAMUX_REQ_GEN_FALLING; /* External request signal edge is Rising */
dmamux_ReqGenParams.RequestNumber = 2; /* 2 requests on each edge of the external request signal */
HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle2, &dmamux_ReqGenParams);
/* NVIC configuration for DMAMUX request generator overrun errors*/
HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle2);
/*##-4- Configure and enable the LPTIM2 used as DMA external request generator signal #####*/
LPTIM_Config();
/*##-5- Start the DMA transfer ################################################*/
/* DMA source buffer is SRC_BUFFER_LED1_TOGGLE containing values to be written
to GPIOJ ODR register in order to turn LED1 On/Off each time comes a request from the DMAMUX request generator */
HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)PLL1FRACR_Buffer, (uint32_t)&RCC->PLL1FRACR, 32);
HAL_DMA_Start_IT(&DMA_Handle2, (uint32_t)PLLCFGR_Buffer, (uint32_t)&RCC->PLLCFGR, 2);
Figure 3. Clock spectrum observation on MCO output (narrow carrier)
Figure 4. Clock spectrum observation on MCO output with SSCG enabled (wide carrier)
Conclusion
Thanks to the STM32H7 PLL fractional, timer, and DMA peripheral it’s simple to implement and shape a spread-spectrum clock generation feature. This allows to reduce the peak energy on the fundamental frequency, as well as its harmonic frequencies, keeping in mind that the generated jitter shape may not be compliant with communication standard like USB.