// rcc.h
#pragma once
#include <stdint.h>

typedef enum ahb1_bits_enum {
  AHB1_GPIOA,
  AHB1_GPIOB,
  AHB1_GPIOC,
  AHB1_GPIOD,
  AHB1_GPIOE,
  AHB1_GPIOF,
  AHB1_GPIOG,
  AHB1_GPIOH,
  AHB1_GPIOI,
  AHB1_rsvd_a,
  AHB1_rsvd_b,
  AHB1_rsvd_c,
  AHB1_CRC,
  AHB1_rsvd_d,
  AHB1_rsvd_e,
  AHB1_FLITF,
  AHB1_SRAM1,
  AHB1_SRAM2,
  AHB1_BKPSRAM,
  AHB1_rsvd_f,
  AHB1_rsvd_g,
  AHB1_DMA1,
  AHB1_DMA2,
  AHB1_rsvd_h,
  AHB1_rsvd_i,
  AHB1_ETHMAC,
  AHB1_ETHTX,
  AHB1_ETHRX,
  AHB1_ETHPTP,
  AHB1_OTGHS,
  AHB1_OTGHSULPI
} ahb1_bits_enum;

typedef enum ahb2_bits_enum {
  AHB2_DCMIRST,
  AHB2_rsvd_a,
  AHB2_rsvd_b,
  AHB2_rsvd_c,
  AHB2_CRYPRST,
  AHB2_HASHRST,
  AHB2_RNGRST,
  AHB2_OTGFSRST
} ahb2_bits_enum;

typedef enum ahb3_bits_enum {
  AHB3_FSMCRST
} ahb3_bits_enum;

typedef enum apb1_bits_enum {
  APB1_TIM2,
  APB1_TIM3,
  APB1_TIM4,
  APB1_TIM5,
  APB1_TIM6,
  APB1_TIM7,
  APB1_TIM12,
  APB1_TIM13,
  APB1_TIM14,
  APB1_rsvd_a,
  APB1_rsvd_b,
  APB1_WWDG,
  APB1_rsvd_c,
  APB1_rsvd_d,
  APB1_SPI2,
  APB1_SPI3,
  APB1_rsvd_e,
  APB1_USART2,
  APB1_USART3,
  APB1_UART4,
  APB1_UART5,
  APB1_I2C1,
  APB1_I2C2,
  APB1_I2C3,
  APB1_rsvd_f,
  APB1_CAN1,
  APB1_CAN2,
  APB1_rsvd_g,
  APB1_PWR,
  APB1_DAC
} apb1_bits_enum;

typedef enum apb2_bits_enum {
  APB2_TIM1,
  APB2_TIM8,
  APB2_rsvd_a,
  APB2_rsvd_b,
  APB2_USART1,
  APB2_USART6,
  APB2_rsvd_c,
  APB2_rsvd_d,
  APB2_ADC1,
  APB2_ADC2,
  APB2_ADC3,
  APB2_SDIO,
  APB2_SPI1,
  APB2_rsvd_e,
  APB2_SYSCFG,
  APB2_rsvd_f,
  APB2_TIM9,
  APB2_TIM10,
  APB2_TIM11
} apb2_bits_enum;

typedef volatile struct /* rcc_struct */ {  // byte/half/word access
  // 00 Clock control (RCC_CR)
  uint32_t  CR_HSION        :  1;
  uint32_t  CR_HSIRDY       :  1;
  uint32_t                  :  1;
  uint32_t  CR_HSITRIM      :  5;
  uint32_t  CR_HSICAL       :  8;
  uint32_t  CR_HSEON        :  1;
  uint32_t  CR_HSERDY       :  1;
  uint32_t  CR_HSRBYP       :  1;
  uint32_t  CR_CSSON        :  1; // Clock security system enable
  uint32_t                  :  4;
  uint32_t  CR_PLLON        :  1;
  uint32_t  CR_PLLRDY       :  1;
  uint32_t  CR_PLLI2SON     :  1;
  uint32_t  CR_PLLI2SRDY    :  1;
  uint32_t                  :  4;
  // 04 PLL configuration (RCC_PLLCFGR)
  uint32_t  PLLCFGR_PLLM    :  6;
  uint32_t  PLLCFGR_PLLN    :  9;
  uint32_t                  :  1;
  uint32_t  PLLCFGR_PLLP    :  2;
  uint32_t                  :  4;
  uint32_t  PLLCFGR_PLLSRC  :  1;
  uint32_t                  :  1;
  uint32_t  PLLCFGR_PLLQ    :  4;
  uint32_t                  :  4;
  // 08 Clock configuration (RCC_CFGR)
  uint32_t  CFGR_SW         :  2;
  uint32_t  CFGR_SWS        :  2;
  uint32_t  CFGR_HPRE       :  4;
  uint32_t                  :  2;
  uint32_t  CFGR_PPRE1      :  3;
  uint32_t  CFGR_PPRE2      :  3;
  uint32_t  CFGR_RTCPRE     :  5;
  uint32_t  CFGR_MCO1       :  2;
  uint32_t  CFGR_I2SSCR     :  1;
  uint32_t  CFGR_MCO1PRE    :  3;
  uint32_t  CFGR_MCO2PRE    :  3;
  uint32_t  CFGR_MCO2       :  2;
  // 0C Clock interrupt (RCC_CIR)
  uint32_t  CIR_LSIRDYF     :  1;
  uint32_t  CIR_LSERDYF     :  1;
  uint32_t  CIR_HSIRDYF     :  1;
  uint32_t  CIR_HSERDYF     :  1;
  uint32_t  CIR_PLLRDYF     :  1;
  uint32_t  CIR_PLLI2SRDYF  :  1;
  uint32_t                  :  1;
  uint32_t  CIR_CSSF        :  1;
  uint32_t  CIR_LSIRDYIE    :  1;
  uint32_t  CIR_LSERDYIE    :  1;
  uint32_t  CIR_HSIRDYIE    :  1;
  uint32_t  CIR_HSRYDYIE    :  1;
  uint32_t  CIR_PLLRDYIE    :  1;
  uint32_t  CIR_PLLI2SRDYIE :  1;
  uint32_t                  :  2;
  uint32_t  CIR_LSIRDYC     :  1;
  uint32_t  CIR_LSERDYC     :  1;
  uint32_t  CIR_HSIRDYC     :  1;
  uint32_t  CIR_HSERDYC     :  1;
  uint32_t  CIR_PLLRDYC     :  1;
  uint32_t  CIR_PLLI2SRDYC  :  1;
  uint32_t                  :  1;
  uint32_t  CIR_CSSC        :  1;
  uint32_t                  :  8;
  // 10 AHB1 peripheral reset (RCC_AHB1RSTR)
  uint32_t  AHB1RSTR;
  // 14 AHB2 peripheral reset (RCC_AHB2RSTR)
  uint32_t  AHB2RSTR;
  // 18 AHB3 peripheral reset (RCC_AHB3RSTR)
  uint32_t  AHB3RSTR;
  // 1C
  uint32_t  rsvd_1C;
  // 20 APB1 peripheral reset (RCC_APB1RSTR)
  uint32_t  APB1RSTR;
  // 24 APB2 peripheral reset (RCC_APB2RSTR)
  uint32_t  APB2RSTR;
  // 28
  uint32_t  rsvd_28;
  uint32_t  rsvd_2C;
  // 30 AHB1 peripheral clock register (RCC_AHB1ENR)
  uint32_t  AHB1ENR;
  // 34 AHB2 peripheral clock enable register (RCC_AHB2ENR)
  uint32_t  AHB2ENR;
  // 38 AHB3 peripheral clock enable register (RCC_AHB3ENR)
  uint32_t  AHB3ENR;
  // 3C
  uint32_t  rsvd_3C;
  // 40 APB1 peripheral clock enable register (RCC_APB1ENR)
  uint32_t  APB1ENR;
  // 44 APB2 peripheral clock enable register (RCC_APB2ENR)
  uint32_t  APB2ENR;
  // 48
  uint32_t  rsvd_48;
  uint32_t  rsvd_4C;
  // 50 AHB1 peripheral clock enable in low-power mode register (RCC_AHB1LPENR)
  uint32_t  AHB1LPENR;
  // 54 AHB2 peripheral clock enable in low-power mode register (RCC_AHB2LPENR)
  uint32_t  AHB2LPENR;
  // 58 AHB3 peripheral clock enable in low-power mode register (RCC_AHB3LPENR)
  uint32_t  AHB3LPENR;
  // 5C
  uint32_t  rsvd_5C;
  // 60 APB1 peripheral clock enable in low-power mode register (RCC_APB1LPENR)
  uint32_t  APB1LPENR;
  // 64 APB2 peripheral clock enabled in low-power mode register (RCC_APB2LPENR)
  uint32_t  APB2LPENR;
  // 68
  uint32_t  rsvd_68;
  uint32_t  rsvd_6C;
  // 70 Backup domain control register (RCC_BDCR)
  uint32_t  BDCR_LSEON      :  1;
  uint32_t  BDCR_LSERDY     :  1;
  uint32_t  BDCR_LSEBYP     :  1;
  uint32_t                  :  5;
  uint32_t  BDCR_RTCSEL     :  2;
  uint32_t                  :  5;
  uint32_t  BDCR_RTCEN      :  1;
  uint32_t  BDCR_BDRST      :  1;
  uint32_t                  : 15;
  // 74 Clock control & status register (RCC_CSR)
  union {
    uint32_t  CSR;
    struct {
      uint32_t  CSR_LSION    :  1;
      uint32_t  CSR_LSIRDY   :  1;
      uint32_t               : 22;
      uint32_t  CSR_RMVF     :  1;
      uint32_t  CSR_BORRSTF  :  1;
      uint32_t  CSR_PINRSTF  :  1;
      uint32_t  CSR_PORRSTF  :  1;
      uint32_t  CSR_SFTRSTF  :  1;
      uint32_t  CSR_IWDGRSTF :  1;
      uint32_t  CSR_WWDGRSTF :  1;
      uint32_t  CSR_LPWRRSTF :  1;
    };
  };
  // 78
  uint32_t  rsvd_78;
  uint32_t  rsvd_7C;
  // 80 Spread spectrum clock generation register (RCC_SSCGR)
  uint32_t  SSCGR_MODPER    : 13;
  uint32_t  SSCGR_INCSTEP   : 15;
  uint32_t                  :  2;
  uint32_t  SSCGR_SPREADSEL :  1;
  uint32_t  SSCGR_SSCGEN    :  1;
  // 84 PLLI2S configuration register (RCC_PLLI2SCFGR)
  uint32_t                  :  6;
  uint32_t  PLLI2SN         :  9;
  uint32_t                  :  1;
  uint32_t                  : 12;
  uint32_t  PLLI2SR         :  3;
  uint32_t                  :  1;
} rcc_struct;

_Static_assert (sizeof(rcc_struct) == 136, " rcc_struct: bad size");

static rcc_struct * const RCC = (rcc_struct *)0x40023800;

