on
2024-01-15
04:14 AM
- edited on
2024-03-11
02:10 AM
by
Laurids_PETERSE
This article is a continuation of Part 1: Introduction to the STM32 microcontroller clock system.
We recommend reading part 1 of the article before reading this article.
If a failure is detected on the HSE clock, the system automatically switches to the HSI, or CSI depending on the STOPWUCK bit configuration (in RCC clock configuration register 1 (RCC_CFGR1)). This is to provide a safe clock. The HSE is then automatically disabled, a clock failure event is sent to the break inputs of the advanced-control timer (TIM1). A NMI is automatically generated to inform the application about the failure, thus allowing the MCU to perform rescue operations.
If the HSE output was used as clock source for PLLs when the failure occurred, the PLLs are also disabled. If an HSE clock failure occurs when the CSS is enabled, the CSS generates an interrupt that causes the automatic generation of an NMI. The HSECSSF flag in the RCC clock source interrupt flag register (RCC_CIFR) is set to 1 to allow the application to identify the failure source. The NMI routine is executed indefinitely until the HSECSSF bit is cleared. As a consequence, the application must clear the HSECSSF flag in the NMI ISR by setting the HSECSSC bit in the RCC clock source interrupt clear register (RCC_CICR).
The clock security system on the LSE detects when the LSE disappears or in the case of over frequency. In addition, the glitches on LSE can be filtered by setting LSEGFON. LSEGFON must be written when the LSE is disabled (LSEON = 0 and LSERDY = 0). If a failure is detected on the external 32 kHz oscillator, the LSE clock is no longer supplied to the RTC, but no hardware action is made to the registers.
The clock recovery system (CRS) is an advanced digital controller acting on the internal fine-granularity trimmable RC oscillator HSI48. The CRS is ideally suited to provide a precise clock to the USB peripheral. In this case, the synchronization signal can be derived from the start-of-frame (SOF) packet signalization on the USB bus, sent by a USB host at 1 ms intervals.
The RCC feeds the Cortex® system timer (SysTick) external clock with the AHB clock (HCLK) divided by eight (default after reset), or LSE or LSI. The SysTick can work either with this clock or directly with the Cortex® clock (HCLK), configurable in the SysTick control and status register.
Various clocks can be outputted on the GPIO. The microcontroller clock output feature allows you to output clock suck as HS1, HSE, LSE, SYSCLK, PLLCLK, etc. For example, STM32H503 has three clock output (MCO1, MCO2, LSCO). These can be output to GPIO pin PA8, PC9, and PB2 respectively.
"Kernel clock" is used in many different contexts for the STM32. In the RTOS context, the kernel clock is described as the base clock for the RTOS. However, we also use kernel clock in the context of a peripheral STM32 clock (clock source for the peripheral).
Snippet 1 below shows a simple clock configuration that was generated using the STM32CubeMX tool. The configuration shown in the C code reflects the configuration shown in figure 3.
Snippet 1: The resulting clock tree configuration after the STM32CubeMX ioc configuration file has been generated.
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLL1_SOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 12;
RCC_OscInitStruct.PLL.PLLN = 250;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1_VCIRANGE_1;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1_VCORANGE_WIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_PCLK3;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
As shown in snippet 1, first, we declare the reset and clock control (RCC) structure as shown in lines 7-8 (“RCC_OscInitTypeDef” and “RCC_ClkInitTypeDef”). “RCC_OscInitTypeDef” is used to configure the oscillator and configure the phase-locked loop (PLL). In this example, the HSE clock is selected as our oscillator clock source (“RCC_OSCILLATORTYPE_CSI”).
Table 3: PLL factors and their descriptions.
PLL factors |
Description |
PLLM |
Division factor for PLL1 VCO input clock |
PLLN |
Multiplication factor for PLL1 VCO output clock |
PLLP |
Division factor for system clock |
PLLQ |
Division factor for peripheral clocks |
PLLRss |
Division factor for peripheral clocks |
PLLRGE |
PLL1 clock input range |
PLLVCOSEL |
PLL1 clock output range |
PLLFRACN |
PLLFRACN: Specifies fractional part of the multiplication factor for PLL1 |
The “RCC_ClkInitStruct” structure is used to configure the CPU core clock, AHB microcontroller main clock, and the peripheral bus clock. These structure members are further described as follows:
Clock parameters |
Description |
ClockType |
The clock to be configured |
SYSCLKSource |
The clock source used as system clock (SYSCLK) |
AHBCLKDivider |
The AHB clock (HCLK) divider. This clock is derived from the system clock (SYSCLK) |
APB1CLKDivider |
The APB1 clock (PCLK1) divider. This clock is derived from the AHB clock (HCLK) |
APB2CLKDivider |
The APB2 clock (PCLK2) divider. This clock is derived from the AHB clock (HCLK) |
APB3CLKDivider |
The APB3 clock (PCLK3) divider. This clock is derived from the AHB clock (HCLK) |