RCC Oscillators 설정 순서

STM32에서 Oscillator를 설정하는 과정을 확인해 보았다.
SystemClock Config => HAL_RCC_OscConfig 함수가 호출되어 Oscillator가 설정이 된다. 호출 과정을 분석한 내용을 정리해 보았다.
Oscillator를 설정하기 위해 아래와 같이 설정 후 HAL_RCC_OscConfig(&RCC_OscInitStruct)를 호출 한다.
Clock 설정은 아래와 같이 세팅했다.
clock_setting
system_architecture
stm32f103xx_performace_block_diagram
clock_tree

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** 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.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
  /*------------------------------- HSE Configuration ------------------------*/
  // OscillatorType을 HSE(High Speed External 로 설정하였기 때문에 아래 조건에 성립 한다.)
  if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
  {
    ....
    /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
    // RCC_CFGR(Clock configuration register) 레지스터 값은 리셋시 0으로 설정 되며 system clock이 HSE 또는 PLLCLK으로 설정 되어 있는지 확인
    // 1. RCC_CFGR 레지스터의 SWS 비트 값 확인, 사용중인 시스템 클락이 있는지 확인한다.
    if ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_HSE)
        || ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE)))
    {
      if ((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
      {
        return HAL_ERROR;
      }
    }
    else
    {
      /* Set the new HSE configuration ---------------------------------------*/
      // RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
      // HSEState는 RCC_HSE_ON으로 설정 되어 있다.
      // 2.RCC->CR (Clock control register) 레지스터의 HSㄷON 비트 값을으로 세팅 ENABLE
      // RCC->CR 레지스터에 HSION 비트 값을으로 세팅 ENABLE로 세팅을 해도 
      // RCC->CFGR 레지스터의 SWS의 비트 HSE oscillator used as system clock 로 세팅되지는 않는다.
      __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);

      /* Check the HSE State */
      if (RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
      {
        /* Get Start Tick */
        tickstart = HAL_GetTick();

        /* Wait till HSE is ready */
        // 3. RCC->CR 레지스터에서 HSERDY 비트 값이 0 인지 확인
        // __HAL_RCC_HSE_CONFIG에서 RCC->CR을 의 HSEON이 설정되어 HSERDY도 1로 설정 됨
        while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
        {
          if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
   }   
  ....

  // RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE)
  {
    /* Check if the PLL is used as system clock or not */
    // 4. RCC_CFGR 레지스터의 SWS 비트 값이 RCC_SYSCLKSOURCE_STATUS_PLLCLK 인지 확인
    // system clock으로 PLL Clock을 사용하고 있는지 확인
    if (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK)
    {
      // RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      if ((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON)
      {
        /* Check the parameters */
        assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
        assert_param(IS_RCC_PLL_MUL(RCC_OscInitStruct->PLL.PLLMUL));

        /* Disable the main PLL. */
        // 5. RCC->CR 레지스터의 PLLON bit 값을 bit baning을 이용하여 Disable 한다.
        __HAL_RCC_PLL_DISABLE();

        /* Get Start Tick */
        tickstart = HAL_GetTick();

        /* Wait till PLL is disabled */
        // 6. RCC->CR (Clock control register )레지스터의 PLLRDY 비트가 0인지 확인
        while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
        {
          if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }

        /* Configure the HSE prediv factor --------------------------------*/
        /* It can be written only when the PLL is disabled. Not used in PLL source is different than HSE */
        // RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
        if (RCC_OscInitStruct->PLL.PLLSource == RCC_PLLSOURCE_HSE)
        {
          /* Check the parameter */
          assert_param(IS_RCC_HSE_PREDIV(RCC_OscInitStruct->HSEPredivValue));
          /* Set PREDIV1 Value */
          // RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
          // 7. RCC->CFGR 레지스터에 RCC_HSE_PREDIV_DIV1 값을 write한다.
          __HAL_RCC_HSE_PREDIV_CONFIG(RCC_OscInitStruct->HSEPredivValue);
        }

        /* Configure the main PLL clock source and multiplication factors. */
        // RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
        // RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
        // RCC->CFGR 레지스터에 PLLSource, PLLMUL 값을 write 
        8. __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
                             RCC_OscInitStruct->PLL.PLLMUL);
        /* Enable the main PLL. */
        // RCC->CR 레지스터의 PLLON bit를 bit baning을 이용하여 Enable 한다.
        // RCC->CR 레지스터에 PLLON 비트 값을으로 세팅 ENABLE로 세팅을 해도 
        // RCC->CFGR 레지스터의 SWS의 비트  PLL used as system clock 로 세팅되지는 않는다.
        9. __HAL_RCC_PLL_ENABLE();

        /* Get Start Tick */
        tickstart = HAL_GetTick();

        /* Wait till PLL is ready */
        // 10. RCC->CR의PLLRDY bit가 on 됐는지 확인
        while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)  == RESET)
        {
          if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
    }

RCC_CFGR 레지스터 값은 아래 그림과 같이 Reset이 되면 0으로 설정이 된다.


rcc_cfgr_register
rcc_cfgr_register_sws_bit

1. if ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_HSE)
        || ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE)))

#define __HAL_RCC_GET_SYSCLK_SOURCE() ((uint32_t)(READ_BIT(RCC->CFGR,RCC_CFGR_SWS)))

#define READ_BIT(REG, BIT)    ((REG) & (BIT))

#define RCC                 ((RCC_TypeDef *)RCC_BASE)
#define RCC_BASE              (AHBPERIPH_BASE + 0x00001000UL)
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x00020000UL)
#define PERIPH_BASE           0x40000000UL /*!< Peripheral base address in the alias region */

typedef struct
{
  __IO uint32_t CR;
  __IO uint32_t CFGR;
  __IO uint32_t CIR;
  __IO uint32_t APB2RSTR;
  __IO uint32_t APB1RSTR;
  __IO uint32_t AHBENR;
  __IO uint32_t APB2ENR;
  __IO uint32_t APB1ENR;
  __IO uint32_t BDCR;
  __IO uint32_t CSR;


} RCC_TypeDef;

/*!< SWS configuration */
#define RCC_CFGR_SWS_Pos                     (2U)                              
#define RCC_CFGR_SWS_Msk                     (0x3UL << RCC_CFGR_SWS_Pos)        /*!< 0x0000000C */
#define RCC_CFGR_SWS                         RCC_CFGR_SWS_Msk                   /*!< SWS[1:0] bits (System Clock Switch Status) */

#define RCC_SYSCLKSOURCE_STATUS_HSI      RCC_CFGR_SWS_HSI            /*!< HSI used as system clock */
#define RCC_SYSCLKSOURCE_STATUS_HSE      RCC_CFGR_SWS_HSE            /*!< HSE used as system clock */
#define RCC_SYSCLKSOURCE_STATUS_PLLCLK   RCC_CFGR_SWS_PLL            /*!< PLL used as system clock */

#define RCC_CFGR_SWS_HSI                     0x00000000U                       /*!< HSI oscillator used as system clock */
#define RCC_CFGR_SWS_HSE                     0x00000004U                       /*!< HSE oscillator used as system clock */
#define RCC_CFGR_SWS_PLL                     0x00000008U                       /*!< PLL used as system clock */

#define __HAL_RCC_GET_PLL_OSCSOURCE() ((uint32_t)(READ_BIT(RCC->CFGR, RCC_CFGR_PLLSRC)))

#define RCC_CFGR_PLLSRC_Pos                  (16U)                             
#define RCC_CFGR_PLLSRC_Msk                  (0x1UL << RCC_CFGR_PLLSRC_Pos)     /*!< 0x00010000 */
#define RCC_CFGR_PLLSRC                      RCC_CFGR_PLLSRC_Msk               /*!< PLL entry clock source */


rcc_cr_register

rcc_cr_register_HSEON_bit

 /* Set the new HSE configuration ---------------------------------------*/
// RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
// HSEState는 RCC_HSE_ON으로 설정 되어 있다.
// 2 .RCC->CR 레지스터 세팅 (Clock control register)
__HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);

#define __HAL_RCC_HSE_CONFIG(__STATE__)                                     \
                    do{                                                     \
                      if ((__STATE__) == RCC_HSE_ON)                        \
                      {                                                     \
                        SET_BIT(RCC->CR, RCC_CR_HSEON);                     \
                      }                                                     \
                      else if ((__STATE__) == RCC_HSE_OFF)                  \
                      {                                                     \
                        CLEAR_BIT(RCC->CR, RCC_CR_HSEON);                   \
                        CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);                  \
                      }                                                     \
                      else if ((__STATE__) == RCC_HSE_BYPASS)               \
                      {                                                     \
                        SET_BIT(RCC->CR, RCC_CR_HSEBYP);                    \
                        SET_BIT(RCC->CR, RCC_CR_HSEON);                     \
                      }                                                     \
                      else                                                  \
                      {                                                     \
                        CLEAR_BIT(RCC->CR, RCC_CR_HSEON);                   \
                        CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);                  \
                      }                                                     \
                    }while(0U)

#define RCC_CR_HSEON_Pos                     (16U)                             
#define RCC_CR_HSEON_Msk                     (0x1UL << RCC_CR_HSEON_Pos)        /*!< 0x00010000 */
#define RCC_CR_HSEON                         RCC_CR_HSEON_Msk                  /*!< External High Speed clock enable */

#define SET_BIT(REG, BIT)     ((REG) |= (BIT))


아래와 같이 RCC->CR 레지스터가 RCC->CR 의 HSEON을 Setting 후 HSERDY 값도 1로 변한 것을 알 수 있다.
rcc_cr_register

rcc_cr_register_hse_read_bit

rcc_cr_after_reset_value

rcc_cr_after_set_rcc_cr_set_hse

  /* Wait till HSE is ready */
  // RCC->CR 레지스터에서 HSERDY가 0 인지 확인
  // __HAL_RCC_HSE_CONFIG에서 RCC->CR을 의 HSEON이 설정되어 HSERDY도 1로 설정 됨
  3. while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)

typedef enum 
{
  RESET = 0, 
  SET = !RESET
} FlagStatus, ITStatus;

#define RCC_FLAG_HSERDY      ((uint8_t)((CR_REG_INDEX << 5U) | RCC_CR_HSERDY_Pos)) /*!< External High Speed clock ready flag */

#define RCC_CR_HSERDY_Pos                    (17U)                             
#define RCC_CR_HSERDY_Msk                    (0x1UL << RCC_CR_HSERDY_Pos)       /*!< 0x00020000 */
#define RCC_CR_HSERDY                        RCC_CR_HSERDY_Msk                 /*!< External High Speed clock ready flag */

/* Defines used for Flags */
#define CR_REG_INDEX                     ((uint8_t)1)
#define BDCR_REG_INDEX                   ((uint8_t)2)
#define CSR_REG_INDEX                    ((uint8_t)3)

#define __HAL_RCC_GET_FLAG(__FLAG__) (((((__FLAG__) >> 5U) == CR_REG_INDEX)?   RCC->CR   : \
                                      ((((__FLAG__) >> 5U) == BDCR_REG_INDEX)? RCC->BDCR : \
                                                                              RCC->CSR)) & (1U << ((__FLAG__) & RCC_FLAG_MASK)))

#define RCC_FLAG_MASK                    ((uint8_t)0x1F)                                                                       


rcc_cfgr_register
rcc_cfgr_register_sws_bit

4. __HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK

#define RCC_SYSCLKSOURCE_STATUS_HSI      RCC_CFGR_SWS_HSI            /*!< HSI used as system clock */
#define RCC_SYSCLKSOURCE_STATUS_HSE      RCC_CFGR_SWS_HSE            /*!< HSE used as system clock */
#define RCC_SYSCLKSOURCE_STATUS_PLLCLK   RCC_CFGR_SWS_PLL            /*!< PLL used as system clock */

#define RCC_CFGR_SWS_HSI                     0x00000000U                       /*!< HSI oscillator used as system clock */
#define RCC_CFGR_SWS_HSE                     0x00000004U                       /*!< HSE oscillator used as system clock */
#define RCC_CFGR_SWS_PLL                     0x00000008U                       /*!< PLL used as system clock */

#define __HAL_RCC_GET_SYSCLK_SOURCE() ((uint32_t)(READ_BIT(RCC->CFGR,RCC_CFGR_SWS)))

/*!< SWS configuration */
#define RCC_CFGR_SWS_Pos                     (2U)                              
#define RCC_CFGR_SWS_Msk                     (0x3UL << RCC_CFGR_SWS_Pos)        /*!< 0x0000000C */
#define RCC_CFGR_SWS                         RCC_CFGR_SWS_Msk                   /*!< SWS[1:0] bits (System Clock Switch Status) */

#define READ_BIT(REG, BIT)    ((REG) & (BIT))


rcc_cr_register

rcc_cr_register_pllon

5. __HAL_RCC_PLL_DISABLE()

#define RCC_PLL_NONE                      0x00000000U  /*!< PLL is not configured */
#define RCC_PLL_OFF                       0x00000001U  /*!< PLL deactivation */
#define RCC_PLL_ON                        0x00000002U  /*!< PLL activation */

#define __HAL_RCC_PLL_DISABLE()         (*(__IO uint32_t *) RCC_CR_PLLON_BB = DISABLE)

typedef enum 
{
  DISABLE = 0, 
  ENABLE = !DISABLE
} FunctionalState;

#define RCC_CR_PLLON_BB           ((uint32_t)(PERIPH_BB_BASE + (RCC_CR_OFFSET_BB * 32U) + (RCC_PLLON_BIT_NUMBER * 4U)))

#define RCC_CR_OFFSET_BB          (RCC_OFFSET + RCC_CR_OFFSET)

#define RCC_OFFSET                (RCC_BASE - PERIPH_BASE) // 0x40021000 - 0x40000000

#define PERIPH_BB_BASE            0x42000000UL /*!< Peripheral base address in the bit-band region */

#define RCC_CR_OFFSET             0x00U

#define RCC_BASE                  (AHBPERIPH_BASE + 0x00001000UL). 	//  0x40000000 + 0x00020000 + 0x00001000

#define AHBPERIPH_BASE           (PERIPH_BASE + 0x00020000UL)

#define PERIPH_BASE               0x40000000UL /*!< Peripheral base address in the alias region */

#define RCC_PLLON_BIT_NUMBER      RCC_CR_PLLON_Pos

#define RCC_CR_PLLON_Pos                     (24U) 


STM32의 메모리 멥은 아래 그림과 같다.
bit_banding_memory_map

STM32의 peripheral 멥은 아래 그림과 같다.
peripheral_bit_region

STM32 bit banding mapping 에 대한 설명
bit-banding-mapping


bit를 AND 또는 OR 연산자 없이 빠르게 변환 시키기 위해 bit banding을 사용한다.


참고한 홈페이지 및 STM32 문서 링크
1. https://todayis.tistory.com/254
2. https://developer.arm.com/documentation/ddi0337/h/programmers-model/bit-banding?lang=en
3. https://www.st.com/resource/en/programming_manual/pm0056-stm32f10xxx20xxx21xxxl1xxxx-cortexm3-programming-manual-stmicroelectronics.pdf
4. https://todayis.tistory.com/254
5. https://feelpass.tistory.com/entry/Cortex-M3-Bit-band
6. https://scienceprog.com/bit-band-operations-with-arm-cortex-microcontrollers/



rcc_cr_register

rcc_cr_register_pllrdy

6. while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)  != RESET)

#define RCC_FLAG_PLLRDY                  ((uint8_t)((CR_REG_INDEX << 5U) | RCC_CR_PLLRDY_Pos)) /*!< PLL clock ready flag */

#define RCC_CR_PLLRDY_Pos                (25U)

#define __HAL_RCC_GET_FLAG(__FLAG__) (((((__FLAG__) >> 5U) == CR_REG_INDEX)?   RCC->CR   : \
                                      ((((__FLAG__) >> 5U) == BDCR_REG_INDEX)? RCC->BDCR : \
                                                                              RCC->CSR)) & (1U << ((__FLAG__) & RCC_FLAG_MASK)))


rcc_cfgr_register

rcc_cfgr_pllxtpre

7. __HAL_RCC_HSE_PREDIV_CONFIG(RCC_OscInitStruct->HSEPredivValue);

#define RCC_HSE_PREDIV_DIV1              0x00000000U

#define __HAL_RCC_HSE_PREDIV_CONFIG(__HSE_PREDIV_VALUE__) \
                  MODIFY_REG(RCC->CFGR,RCC_CFGR_PLLXTPRE, (uint32_t)(__HSE_PREDIV_VALUE__))

#define MODIFY_REG(REG, CLEARMASK, SETMASK)  WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))

#define WRITE_REG(REG, VAL)   ((REG) = (VAL))

#define READ_REG(REG)         ((REG))


#define RCC_CFGR_PLLXTPRE_Pos                (17U)                             
#define RCC_CFGR_PLLXTPRE_Msk                (0x1UL << RCC_CFGR_PLLXTPRE_Pos)   /*!< 0x00020000 */
#define RCC_CFGR_PLLXTPRE                    RCC_CFGR_PLLXTPRE_Msk     

#define RCC_HSE_PREDIV_DIV1              0x00000000U


rcc_cfgr_register

rcc_cfgr_register_pllsrc_bit

rcc_cfgr_register_pllul_bit

/* Configure the main PLL clock source and multiplication factors. */
// RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
// RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
// RCC->CFGR 레지스터에 PLLSource, PLLMUL 값을 write 
8. __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
                      RCC_OscInitStruct->PLL.PLLMUL);

#define RCC_PLLSOURCE_HSE                    RCC_CFGR_PLLSRC            /*!< HSE clock selected as PLL entry clock source */
#define RCC_CFGR_PLLSRC_Pos                  (16U)                             
#define RCC_CFGR_PLLSRC_Msk                  (0x1UL << RCC_CFGR_PLLSRC_Pos)     /*!< 0x00010000 */
#define RCC_CFGR_PLLSRC                      RCC_CFGR_PLLSRC_Msk               /*!< PLL entry clock source */

#define RCC_PLL_MUL9                         RCC_CFGR_PLLMULL9

#define RCC_CFGR_PLLMULL9_Pos                (18U)                             
#define RCC_CFGR_PLLMULL9_Msk                (0x7UL << RCC_CFGR_PLLMULL9_Pos)   /*!< 0x001C0000 */
#define RCC_CFGR_PLLMULL9                    RCC_CFGR_PLLMULL9_Msk 

#define __HAL_RCC_PLL_CONFIG(__RCC_PLLSOURCE__, __PLLMUL__)\
          MODIFY_REG(RCC->CFGR, (RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL),((__RCC_PLLSOURCE__) | (__PLLMUL__) ))

/*!< PLLMUL configuration */
#define RCC_CFGR_PLLMULL_Pos                 (18U)                             
#define RCC_CFGR_PLLMULL_Msk                 (0xFUL << RCC_CFGR_PLLMULL_Pos)    /*!< 0x003C0000 */
#define RCC_CFGR_PLLMULL                     RCC_CFGR_PLLMULL_Msk     

#define MODIFY_REG(REG, CLEARMASK, SETMASK)  WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))

#define WRITE_REG(REG, VAL)   ((REG) = (VAL))

#define READ_REG(REG)         ((REG))


rcc_cr_register

rcc_cr_register_pllon

9. __HAL_RCC_PLL_ENABLE();

#define __HAL_RCC_PLL_ENABLE()          (*(__IO uint32_t *) RCC_CR_PLLON_BB = ENABLE) // Enable시 PLLRDY bit도 1로 세팅됨

typedef enum 
{
  DISABLE = 0, 
  ENABLE = !DISABLE
} FunctionalState;

#define RCC_CR_PLLON_BB           ((uint32_t)(PERIPH_BB_BASE + (RCC_CR_OFFSET_BB * 32U) + (RCC_PLLON_BIT_NUMBER * 4U)))

#define RCC_CR_OFFSET_BB          (RCC_OFFSET + RCC_CR_OFFSET)

#define RCC_OFFSET                (RCC_BASE - PERIPH_BASE) // 0x40021000 - 0x40000000

#define PERIPH_BB_BASE            0x42000000UL /*!< Peripheral base address in the bit-band region */

#define RCC_CR_OFFSET             0x00U

#define RCC_BASE                  (AHBPERIPH_BASE + 0x00001000UL). 	//  0x40000000 + 0x00020000 + 0x00001000

#define AHBPERIPH_BASE           (PERIPH_BASE + 0x00020000UL)

#define PERIPH_BASE               0x40000000UL /*!< Peripheral base address in the alias region */

#define RCC_PLLON_BIT_NUMBER      RCC_CR_PLLON_Pos

#define RCC_CR_PLLON_Pos                     (24U) 


rcc_cr_register

rcc_cr_register_pllrdy

10. while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)  == RESET)

#define     __IO    volatile             /*!< Defines 'read / write' permissions */

#define RCC_FLAG_PLLRDY                  ((uint8_t)((CR_REG_INDEX << 5U) | RCC_CR_PLLRDY_Pos)) /*!< PLL clock ready flag */

#define RCC_CR_PLLRDY_Pos                (25U) 

/* Defines used for Flags */
#define CR_REG_INDEX                     ((uint8_t)1)
#define BDCR_REG_INDEX                   ((uint8_t)2)
#define CSR_REG_INDEX                    ((uint8_t)3)
                            
#define __HAL_RCC_GET_FLAG(__FLAG__) (((((__FLAG__) >> 5U) == CR_REG_INDEX)?   RCC->CR   : \
                                      ((((__FLAG__) >> 5U) == BDCR_REG_INDEX)? RCC->BDCR : \
                                                                              RCC->CSR)) & (1U << ((__FLAG__) & RCC_FLAG_MASK)))