STM32F1 - Clock

Created:2018-02-09  Last modified:2018-02-09


  1. Introduction

    The system clock of stm32F1 can reach 72MHz. Different from AVR microcontroller that changes clock source by using fuse bits, the stm32 clock source can be changed at runtime by modifying registers.

  2. Clock sources

    clock source can be used as the system clock (Sysclk)

    The maximum input clock frequency to Sys is 72MHz

    1. HSI (high speed internal clock): a 8 MHz RC ,less accurate than HSE.
    2. HSE (high speed external clock): can be a crystal/ceramic resonator or an external clock circuit.
    3. PLL (Phase-locked loop): taking either HSI/2 or HSE as input to generate a higher frequency clock.

    clock source can drive USB

    1. PLL

    clock source can drive RTC

    1. HSE /128
    2. LSE (32.768KHz)
    3. LSI 40KHz RC

    When using LSE, the RTC can continue to work without Vdd but using Vbat (voltage of the battery) Then the LSE is said in the backup domain.

    clock source can driver independent watchdog

    1. LSI 40KHz RC

    Clock security system (CSS)

    When using HSE or HSE + PLL as system clock source, this feature can be used.

    This component can be enabled by software to monitor the HSE. If HSE or HSE + PLL fails, it switch the clock source to HSI and the HSE or HSE + PLL is disabled and cause a NMI (Non maskable interrupt).

    MCO (microcontroller clock output)

    4 clock can be output 1). sysclk, 2). HSI, 3). HSE 4) PLL clock divided by 2

  3. System clock

    1. The hardware default is using HSI oscillator.
  4. Clock registers

    Control

    1. CSR: a flag that remember which source cause the system reset, e.g. watchdog, low-power

    Source selection

    1. RC (Clock control register): PLL ready-enable, HSI ready-enable, HSI calibration, HSE ready-enable/enable-external, CSS enable
      Set and polling test ready flag.
    2. CFGR (Clock configuration register): select/check system clock source; MCO source selection; USB prescaler; HSE prescaler for PLL, PLL source, PLL prescaler; ADC Prescaler; AHB, APB1/2 prescaler
    3. CIR:set to clear clock interrupt flag, e.g. CSS, PLL ready; enable interrupt; interrupt flag;
      The way to clear interrupt flag is different from AVR microcontroller, there is a individual bit used to clear flag.
    4. BDCR: reset the backup domain, enable RTC, select RTC source, LSE enable/ready bypass it in case of debugging.
    5. CSR: LSI enable/ready

    Peripheral device reset

    1. APB2RSTR / ARB1RSTY: reset the peripheral devices on APB2/1, e.g. Timers, uart
      AVR does not have this feature

    Clock distribution

    1. AHBENR: enable the clock for each peripherals on the AHB, e.g. SRAM, DMA1/2, CRC, SDIO (sd card), FSMC (flexible static memory controller 外接存储), FLITF (flash memory instruction intreface)
      reset value will enable SRAM and FLITF.
      When a peripher is disable, trying to read its register would return 0x0.
    2. APB2/1ENR: enable peripherals
  5. Clock programming

    1. Hardware reset

      Clock: 8 MHz HSI without PLL, all APB peripherals disabled, only Flash and ROM is accessible.

    2. SystemInit(); invoked by startup.S

    3. Clock: No MCO, HSI directly used as system clock. (done by direct access register in C)

    4. User clock init(); invoked from the main

      void SystemClock_Config(void)
      {
      
        RCC_OscInitTypeDef RCC_OscInitStruct;
        RCC_ClkInitTypeDef RCC_ClkInitStruct;
      
          /**Initializes the CPU, AHB and APB busses clocks 
          */
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
        RCC_OscInitStruct.HSIState = RCC_HSI_ON;
        RCC_OscInitStruct.HSICalibrationValue = 16;
        RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
        if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
        {
          _Error_Handler(__FILE__, __LINE__);
        }
      
          /**Initializes the CPU, AHB and APB busses clocks 
          */
        RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                    |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
        RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
        RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
        RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
      
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
        {
          _Error_Handler(__FILE__, __LINE__);
        }
      
          /**Configure the Systick interrupt time 
          */
        HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
      
          /**Configure the Systick 
          */
        HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
      
        /* SysTick_IRQn interrupt configuration */
        HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
      }
      
      /** 
        * @brief  RCC Internal/External Oscillator (HSE, HSI, LSE and LSI) configuration structure definition  
        */
      typedef struct
      {
        uint32_t OscillatorType;       /*!< The oscillators to be configured.
                                             This parameter can be a value of @ref RCC_Oscillator_Type */
      
      #if defined(STM32F105xC) || defined(STM32F107xC)
        uint32_t Prediv1Source;       /*!<  The Prediv1 source value.
                                             This parameter can be a value of @ref RCCEx_Prediv1_Source */
      #endif /* STM32F105xC || STM32F107xC */
      
        uint32_t HSEState;              /*!< The new state of the HSE.
                                             This parameter can be a value of @ref RCC_HSE_Config */
                                
        uint32_t HSEPredivValue;       /*!<  The Prediv1 factor value (named PREDIV1 or PLLXTPRE in RM)
                                             This parameter can be a value of @ref RCCEx_Prediv1_Factor */
      
        uint32_t LSEState;              /*!<  The new state of the LSE.
                                              This parameter can be a value of @ref RCC_LSE_Config */
                                                
        uint32_t HSIState;              /*!< The new state of the HSI.
                                             This parameter can be a value of @ref RCC_HSI_Config */
      
        uint32_t HSICalibrationValue;   /*!< The HSI calibration trimming value (default is RCC_HSICALIBRATION_DEFAULT).
                                             This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x1F */
                                     
        uint32_t LSIState;              /*!<  The new state of the LSI.
                                              This parameter can be a value of @ref RCC_LSI_Config */
      
        RCC_PLLInitTypeDef PLL;         /*!< PLL structure parameters */      
      
      #if defined(STM32F105xC) || defined(STM32F107xC)
        RCC_PLL2InitTypeDef PLL2;         /*!< PLL2 structure parameters */      
      #endif /* STM32F105xC || STM32F107xC */
      } RCC_OscInitTypeDef;
      
      /** 
        * @brief  RCC PLL configuration structure definition  
        */
      typedef struct
      {
        uint32_t PLLState;      /*!< PLLState: The new state of the PLL.
                                    This parameter can be a value of @ref RCC_PLL_Config */
      
        uint32_t PLLSource;     /*!< PLLSource: PLL entry clock source.
                                    This parameter must be a value of @ref RCC_PLL_Clock_Source */          
      
        uint32_t PLLMUL;        /*!< PLLMUL: Multiplication factor for PLL VCO input clock
                                    This parameter must be a value of @ref RCCEx_PLL_Multiplication_Factor */
      } RCC_PLLInitTypeDef;