搜索

[综合信息] 华大HC32F460的时钟配置

[复制链接]
411|21
 楼主 | 2021-1-18 12:37 | 显示全部楼层 |阅读模式
分享一下我这两天学习到的华大HC32F460的时钟配置过程

使用特权

评论回复
 楼主 | 2021-1-18 13:13 | 显示全部楼层
同样的,我还是参照STM32来理解的

使用特权

评论回复
 楼主 | 2021-1-18 13:20 | 显示全部楼层
时钟配置是在启动文件中用汇编调用的
  1.                 LDR     R0, =SystemInit
  2.                 BLX     R0
  3.                 LDR     R0, =__main
  4.                 BX      R0
复制代码

LDR     R0, =SystemInit
把SystemInit赋值给R0
                BLX     R0
跳转到R0开始的函数,也就是开始执行SystemInit这个函数

使用特权

评论回复
 楼主 | 2021-1-18 13:23 | 显示全部楼层
继续往下看
  1. void SystemInit(void)
  2. {
  3.     #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
  4.     SCB->CPACR |= ((3UL << 20) | (3UL << 22)); /* set CP10 and CP11 Full Access */
  5.    #endif

  6.     SystemCoreClockUpdate();
  7. }
复制代码

这个函数是这样的
显示判断是否使用了FPU也就是浮点数相关的开启,如果相关的标志为1 那么久开启浮点数的计算 也就是把那四个位都写成1
然后再调用SystemCoreClockUpdate();系统内核时钟更新函数

使用特权

评论回复
 楼主 | 2021-1-18 14:28 | 显示全部楼层
继续看
void SystemCoreClockUpdate(void)  // Update SystemCoreClock variable
{
      uint8_t tmp = 0u;
      uint32_t plln = 19u, pllp = 1u, pllm = 0u, pllsource = 0u;

      /* Select proper HRC_VALUE according to ICG1.HRCFREQSEL bit */
      /* ICG1.HRCFREQSEL = '0' represent HRC_VALUE = 20000000UL   */
      /* ICG1.HRCFREQSEL = '1' represent HRC_VALUE = 16000000UL   */
      if (1UL == (HRC_FREQ_MON() & 1UL))
      {
             HRC_VALUE = HRC_16MHz_VALUE;
      }
     else
     {
           HRC_VALUE = HRC_20MHz_VALUE;
      }

    tmp = M4_SYSREG->CMU_CKSWR_f.CKSW;
    switch (tmp)
    {
        case 0x00:  /* use internal high speed RC */
               SystemCoreClock = HRC_VALUE;
                          break;
        case 0x01:  /* use internal middle speed RC */
                        SystemCoreClock = MRC_VALUE;
                         break;
        case 0x02:  /* use internal low speed RC */
                       SystemCoreClock = LRC_VALUE;
           break;
case 0x03:  /* use external high speed OSC */
           SystemCoreClock = XTAL_VALUE;
           break;
        case 0x04:  /* use external low speed OSC */
           SystemCoreClock = XTAL32_VALUE;
           break;
        case 0x05:  /* use MPLL */
            /* PLLCLK = ((pllsrc / pllm) * plln) / pllp */
           pllsource = M4_SYSREG->CMU_PLLCFGR_f.PLLSRC;
           plln = M4_SYSREG->CMU_PLLCFGR_f.MPLLN;
           pllp = M4_SYSREG->CMU_PLLCFGR_f.MPLLP;
           pllm = M4_SYSREG->CMU_PLLCFGR_f.MPLLM;
            /* use exteranl high speed OSC as PLL source */
            if (0ul == pllsource)
            {
                  SystemCoreClock = (XTAL_VALUE) / (pllm + 1ul) * (plln + 1ul) / (pllp + 1ul);
            }
            /* use interanl high RC as PLL source */
            else if (1ul == pllsource)
            {
                  SystemCoreClock = (HRC_VALUE) / (pllm + 1ul) * (plln + 1ul) / (pllp + 1ul);
            }
            else
            {
                /* Reserved */
            }
            break;
    }
}
从头开始看这个函数
首先定义了几个局部变量并且局部变量赋初值
下面是调用了一个宏定义HRC_FREQ_MON()
他的原型是 #define HRC_FREQ_MON()                  (*((volatile unsigned int*)(0x40010684UL)))
HRC_FREQ_MON()后面有一堆的括号还有*号 咱们一层一层括号来分析
(*((volatile unsigned int*)(0x40010684UL)))
*((volatile unsigned int*)(0x40010684UL)) :指针取内容也就取(volatile unsigned int*)(0x40010684UL))中的内容
     (volatile unsigned int*)(0x40010684UL) :强制类型转换 把0x40010684转换成一个指针,什么类型的指针呢unsigned int无符号整形的指针
      volatile本意是脆弱的,在这里的意思是此指针指向的空间变化很频繁,每次访问要直接访问寄存器,而不是去访问cache里的块儿

取地址为0x40010684的内容 这个0x40010684处放的是什么呢?看一下手册里有没有介绍
手册里是这么说的:MCU 支持 4GB 的线性地址空间,地址从 0000 0000h 到 FFFF FFFFh,其中包含程序
和数据
APB1时钟:PCLK1 包含着这个地址 0x40010400  0x400107FF  1KB  EFM  带保护
找到这以后就结束了,没有找到后面他到底是什么意思,反过头来看上面的注释,注释说的是
/* Select proper HRC_VALUE according to ICG1.HRCFREQSEL bit */
    /* ICG1.HRCFREQSEL = '0' represent HRC_VALUE = 20000000UL   */
    /* ICG1.HRCFREQSEL = '1' represent HRC_VALUE = 16000000UL   */
HRC_VALUE 这个数呢根据  ICG1寄存器的这个位ICG1.HRCFREQSEL 来确定
继续看手册
在第6章里找到了,这个叫做 :初始化配置(ICG)
下面有一句话他的基地址是
ICG_BASE_ADDR:0x00000400
               寄存器名  符号  偏移地址  位宽  复位值
初始化配置寄存器0  ICG0  0x000       32  不定
初始化配置寄存器1  ICG1  0x004       32  不定
我们刚才找的正好是ICG1 基地址是0x00000400+偏移0x004 =0x00000404
在程序里判断的是0x40010684中的内容,这两个也不相等啊,啥情况?
是我没理解对吗?
看有意思了吧

使用特权

评论回复
 楼主 | 2021-1-18 15:03 | 显示全部楼层
上面有问题,不管了,继续看下去吧
  1. tmp = M4_SYSREG->CMU_CKSWR_f.CKSW;
复制代码


这个的意思是要给tmp赋值,这里就是关键了,到底选择的是哪个时钟就靠这个了
这个是什么意思呢 分析一下
#define M4_SYSREG                               ((M4_SYSREG_TypeDef *)0x40054000UL)

((M4_SYSREG_TypeDef *)0x40054000UL)
所以要找一下这个地址0x40054000

在手册里这个出现了六个地方分别是:1.1AHB1时钟:HCLK                        0x40054000  0x400547FF  2KB  SYSC  带保护
                                                       4.11寄存器说明              基准地址 3: 0x40054000
                                                       5.7寄存器说明                BASE ADDR:0x40054000
                                                       13.4 寄存器说明                基准地址: 0x40054000
                                                       29.5寄存器说明  CMU_BASE_ADDR3 : 0x40054000
                                                      29.5.8 CMU I2S  时钟配置存器 CMU_BASE_ADDR3 : 0x40054000
具体在哪里给 M4_SYSREG->CMU_CKSWR_f.CKSW赋值的暂时没有找到,没有找到就放弃吧,看另一条路能不能走的通
  1. static void SystemClk_Init(void)
  2. {
  3.     stc_clk_sysclk_cfg_t    stcSysClkCfg;
  4.     stc_clk_xtal_cfg_t      stcXtalCfg;
  5.     stc_clk_mpll_cfg_t      stcMpllCfg;

  6.     MEM_ZERO_STRUCT(stcSysClkCfg);
  7.     MEM_ZERO_STRUCT(stcXtalCfg);
  8.     MEM_ZERO_STRUCT(stcMpllCfg);

  9.     /* Set bus clk div. */
  10.     stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;   // 168MHz
  11.     stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  // 84MHz
  12.     stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  // 168MHz
  13.     stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  // 84MHz
  14.     stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  // 42MHz
  15.     stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  // 42MHz
  16.     stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  // 84MHz
  17.     CLK_SysClkConfig(&stcSysClkCfg);

  18.     /* Switch system clock source to MPLL. */
  19.     /* Use Xtal as MPLL source. */
  20.     stcXtalCfg.enMode = ClkXtalModeOsc;
  21.     stcXtalCfg.enDrv = ClkXtalLowDrv;
  22.     stcXtalCfg.enFastStartup = Enable;
  23.     CLK_XtalConfig(&stcXtalCfg);
  24.     CLK_XtalCmd(Enable);

  25.     /* MPLL config. */
  26.     stcMpllCfg.pllmDiv = 1u;
  27.     stcMpllCfg.plln = 42u;
  28.     stcMpllCfg.PllpDiv = 2u;
  29.     stcMpllCfg.PllqDiv = 2u;
  30.     stcMpllCfg.PllrDiv = 2u;
  31.     CLK_SetPllSource(ClkPllSrcXTAL);
  32.     CLK_MpllConfig(&stcMpllCfg);

  33.     /* flash read wait cycle setting */
  34.     EFM_Unlock();
  35.     EFM_SetLatency(EFM_LATENCY_4);
  36.     EFM_Lock();

  37.     /* Enable MPLL. */
  38.     CLK_MpllCmd(Enable);

  39.     /* Wait MPLL ready. */
  40.     while (Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
  41.     {
  42.     }

  43.     /* Switch system clock source to MPLL. */
  44.     CLK_SetSysClkSource(CLKSysSrcMPLL);
  45. }
复制代码

找到了一个这个函数,感觉像是配置系统时钟的,解读一下看看

使用特权

评论回复
 楼主 | 2021-1-18 15:10 | 显示全部楼层
开始分析
  1. stc_clk_sysclk_cfg_t    stcSysClkCfg;
复制代码

这个是第一行代码
具体是什么拆开看一下

  1. /**
  2. *******************************************************************************
  3. ** \brief  Configuration structure of system clock.
  4. **
  5. ** \note   Configures the system clock if needed.
  6. **
  7. ******************************************************************************/
  8. typedef struct stc_clk_sysclk_cfg
  9. {
  10.     en_clk_sysclk_div_factor_t      enHclkDiv;        ///< Division for hclk.
  11.     en_clk_sysclk_div_factor_t      enExclkDiv;       ///< Division for exclk.
  12.     en_clk_sysclk_div_factor_t      enPclk0Div;       ///< Division for pclk0.
  13.     en_clk_sysclk_div_factor_t      enPclk1Div;       ///< Division for pclk1.
  14.     en_clk_sysclk_div_factor_t      enPclk2Div;       ///< Division for pclk2.
  15.     en_clk_sysclk_div_factor_t      enPclk3Div;       ///< Division for pclk3.
  16.     en_clk_sysclk_div_factor_t      enPclk4Div;       ///< Division for pclk4.
  17. }stc_clk_sysclk_cfg_t;
复制代码



系统时钟配置结构体,怎么配置的呢?看下面
  1. /**
  2. *******************************************************************************
  3. ** \brief  The division factor of system clock.
  4. **
  5. ******************************************************************************/
  6. typedef enum en_clk_sysclk_div_factor
  7. {
  8.     ClkSysclkDiv1                   = 0u,   ///< 1 division.
  9.     ClkSysclkDiv2                   = 1u,   ///< 2 division.
  10.     ClkSysclkDiv4                   = 2u,   ///< 4 division.
  11.     ClkSysclkDiv8                   = 3u,   ///< 8 division.
  12.     ClkSysclkDiv16                  = 4u,   ///< 16 division.
  13.     ClkSysclkDiv32                  = 5u,   ///< 32 division.
  14.     ClkSysclkDiv64                  = 6u,   ///< 64 division.
  15. }en_clk_sysclk_div_factor_t;
复制代码



这个就是了一个联合体 里面定义了一堆的分频系数

使用特权

评论回复
 楼主 | 2021-1-18 15:11 | 显示全部楼层
那么第一个定义就是定义了分频系数

使用特权

评论回复
 楼主 | 2021-1-18 15:15 | 显示全部楼层
本帖最后由 binoo7 于 2021-1-18 18:00 编辑

来看第二个啊
  1.     stc_clk_xtal_cfg_t      stcXtalCfg;
复制代码



这个也是一个定义
  1. /**
  2. *******************************************************************************
  3. ** \brief  Configuration structure of XTAL.
  4. **
  5. ** \note   Configures the XTAL if needed.
  6. **
  7. ******************************************************************************/
  8. typedef struct stc_clk_xtal_cfg
  9. {
  10.     en_functional_state_t           enFastStartup;  ///< Enable fast start up or not.
  11.     en_clk_xtal_mode_t              enMode;         ///< Select xtal mode.
  12.     en_clk_xtal_drv_t               enDrv;          ///< Select xtal drive capability.
  13. }stc_clk_xtal_cfg_t;
复制代码

原型是这个定义的结构体

这个结构体是定义的外部高速振荡器(XTAL)XTAL
  1. en_functional_state_t           enFastStartup;  ///< Enable fast start up or not.
  2.     en_clk_xtal_mode_t              enMode;         ///< Select xtal mode.
  3.     en_clk_xtal_drv_t               enDrv;          ///< Select xtal drive capability.
复制代码



使用特权

评论回复
 楼主 | 2021-1-18 15:17 | 显示全部楼层
继续看第三个结构体
stc_clk_mpll_cfg_t      stcMpllCfg;
  1. /**
  2. *******************************************************************************
  3. ** \brief  Configuration structure of PLL.
  4. **
  5. ** \note   Configures the PLL if needed.
  6. **
  7. ******************************************************************************/
  8. typedef struct stc_clk_pll_cfg
  9. {
  10.     uint32_t         PllpDiv;            ///< Pllp clk, division factor of VCO out.
  11.     uint32_t         PllqDiv;            ///< Pllq clk, division factor of VCO out.
  12.     uint32_t         PllrDiv;            ///< Pllr clk, division factor of VCO out.
  13.     uint32_t         plln;               ///< Multiplication factor of vco out, ensure between 240M~480M
  14.     uint32_t         pllmDiv;            ///< Division factor of VCO in, ensure between 1M~12M.
  15. }stc_clk_mpll_cfg_t, stc_clk_upll_cfg_t;
复制代码

使用特权

评论回复
 楼主 | 2021-1-18 15:21 | 显示全部楼层
再往下用到了一个c的函数
  1. MEM_ZERO_STRUCT(stcSysClkCfg);
  2.     MEM_ZERO_STRUCT(stcXtalCfg);
  3.     MEM_ZERO_STRUCT(stcMpllCfg);
复制代码

这里面有什么呢看一下
  1. #define MEM_ZERO_STRUCT(x)              do {                                   \
  2.                                         memset((void*)&(x), 0l, (sizeof(x)));  \
  3.                                         }while(0)
复制代码

memset:作用是在一段内存块中填充某个给定的值,是对较大的结构体或数组进行清零操作的一种最快方法

使用特权

评论回复
 楼主 | 2021-1-18 15:24 | 显示全部楼层
先清理,后面肯定是赋值了,往下看
  1. /* Set bus clk div. */
  2.     stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;   // 168MHz
  3.     stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  // 84MHz
  4.     stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  // 168MHz
  5.     stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  // 84MHz
  6.     stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  // 42MHz
  7.     stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  // 42MHz
  8.     stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  // 84MHz
  9.     CLK_SysClkConfig(&stcSysClkCfg);
复制代码

果然没错
赋值结束后这个CLK_SysClkConfig是什么意思呢?
  1. /**
  2. *******************************************************************************
  3. ** \brief  Configures the division factor for hclk,exck,pclk0,pclk1,pclk2,pclk3,
  4. **         pclk4 from system clock.
  5. **
  6. ** \param  [in] pstcSysclkCfg          The system clock configures struct.
  7. **
  8. ** \retval None
  9. **
  10. ** \note   None
  11. **
  12. ******************************************************************************/
  13. void CLK_SysClkConfig(const stc_clk_sysclk_cfg_t *pstcSysclkCfg)
  14. {
  15.     __IO uint32_t timeout = 0ul;
  16.     __IO uint32_t fcg0 = M4_MSTP->FCG0;
  17.     __IO uint32_t fcg1 = M4_MSTP->FCG1;
  18.     __IO uint32_t fcg2 = M4_MSTP->FCG2;
  19.     __IO uint32_t fcg3 = M4_MSTP->FCG3;

  20.     ENABLE_FCG0_REG_WRITE();

  21.     if(NULL != pstcSysclkCfg)
  22.     {
  23.         DDL_ASSERT(IS_SYSCLK_CONFIG_VALID(pstcSysclkCfg));

  24.         /* Only current system clock source is MPLL need to close fcg0~fcg3 and
  25.         open fcg0~fcg3 during switch system clock division.
  26.         We need to backup fcg0~fcg3 before close them. */
  27.         if(CLKSysSrcMPLL == M4_SYSREG->CMU_CKSWR_f.CKSW)
  28.         {
  29.             /* Close fcg0~fcg3. */
  30.             M4_MSTP->FCG0 = DEFAULT_FCG0;
  31.             M4_MSTP->FCG1 = DEFAULT_FCG1;
  32.             M4_MSTP->FCG2 = DEFAULT_FCG2;
  33.             M4_MSTP->FCG3 = DEFAULT_FCG3;

  34.             /* Wait stable after close fcg. */
  35.             do
  36.             {
  37.                 timeout++;
  38.             }while(timeout < CLK_FCG_STABLE);
  39.         }

  40.         /* Switch to target system clock division. */
  41.         ENABLE_CLOCK_REG_WRITE();

  42.         M4_SYSREG->CMU_SCFGR = ( (uint32_t)pstcSysclkCfg->enPclk0Div           |
  43.                                 ((uint32_t)pstcSysclkCfg->enPclk1Div << 4u)    |
  44.                                 ((uint32_t)pstcSysclkCfg->enPclk2Div << 8u)    |
  45.                                 ((uint32_t)pstcSysclkCfg->enPclk3Div << 12u)   |
  46.                                 ((uint32_t)pstcSysclkCfg->enPclk4Div << 16u)   |
  47.                                 ((uint32_t)pstcSysclkCfg->enExclkDiv << 20u)   |
  48.                                 ((uint32_t)pstcSysclkCfg->enHclkDiv << 24u)    |
  49.                                 ((uint32_t)pstcSysclkCfg->enHclkDiv << 28u));

  50.         DISABLE_CLOCK_REG_WRITE();

  51.         timeout = 0ul;
  52.         do
  53.         {
  54.             timeout++;
  55.         }while(timeout < CLK_SYSCLK_STABLE);

  56.         /* Open fcg0~fcg3. */
  57.         M4_MSTP->FCG0 = fcg0;
  58.         M4_MSTP->FCG1 = fcg1;
  59.         M4_MSTP->FCG2 = fcg2;
  60.         M4_MSTP->FCG3 = fcg3;

  61.         DISABLE_FCG0_REG_WRITE();

  62.         /* Wait stable after open fcg. */
  63.         timeout = 0ul;
  64.         do
  65.         {
  66.             timeout++;
  67.         }while(timeout < CLK_FCG_STABLE);
  68.     }
  69.     else
  70.     {
  71.         /* code */
  72.     }
  73. }
复制代码

看到了吧

使用特权

评论回复
| 2021-1-18 15:37 | 显示全部楼层
你这跟帖看得我头晕眼花

使用特权

评论回复
 楼主 | 2021-1-18 16:06 | 显示全部楼层
其实这个函数的关键是这句话
  1. M4_SYSREG->CMU_SCFGR = ( (uint32_t)pstcSysclkCfg->enPclk0Div           |
  2.                                 ((uint32_t)pstcSysclkCfg->enPclk1Div << 4u)    |
  3.                                 ((uint32_t)pstcSysclkCfg->enPclk2Div << 8u)    |
  4.                                 ((uint32_t)pstcSysclkCfg->enPclk3Div << 12u)   |
  5.                                 ((uint32_t)pstcSysclkCfg->enPclk4Div << 16u)   |
  6.                                 ((uint32_t)pstcSysclkCfg->enExclkDiv << 20u)   |
  7.                                 ((uint32_t)pstcSysclkCfg->enHclkDiv << 24u)    |
  8.                                 ((uint32_t)pstcSysclkCfg->enHclkDiv << 28u));
复制代码

给这个M4_SYSREG->CMU_SCFGR寄存器赋值 继续往下看吧

使用特权

评论回复
 楼主 | 2021-1-18 16:07 | 显示全部楼层
jcky001 发表于 2021-1-18 15:37
你这跟帖看得我头晕眼花

从头开始看,最后我会总结一下的

使用特权

评论回复
 楼主 | 2021-1-18 16:08 | 显示全部楼层
赋值结束了,下面一句话是这个
  1. /* Switch system clock source to MPLL. */
  2.     /* Use Xtal as MPLL source. */
  3.     stcXtalCfg.enMode = ClkXtalModeOsc;
  4.     stcXtalCfg.enDrv = ClkXtalLowDrv;
  5.     stcXtalCfg.enFastStartup = Enable;
  6.     CLK_XtalConfig(&stcXtalCfg);
  7.     CLK_XtalCmd(Enable);

  8.     /* MPLL config. */
  9.     stcMpllCfg.pllmDiv = 1u;
  10.     stcMpllCfg.plln = 42u;
  11.     stcMpllCfg.PllpDiv = 2u;
  12.     stcMpllCfg.PllqDiv = 2u;
  13.     stcMpllCfg.PllrDiv = 2u;
  14.     CLK_SetPllSource(ClkPllSrcXTAL);
  15.     CLK_MpllConfig(&stcMpllCfg);
复制代码

使用特权

评论回复
 楼主 | 2021-1-18 16:14 | 显示全部楼层
这两句话也说赋值

  1. /* Switch system clock source to MPLL. */
  2.     /* Use Xtal as MPLL source. */
  3.     stcXtalCfg.enMode = ClkXtalModeOsc;
  4.     stcXtalCfg.enDrv = ClkXtalLowDrv;
  5.     stcXtalCfg.enFastStartup = Enable;
  6.     CLK_XtalConfig(&stcXtalCfg);
  7.     CLK_XtalCmd(Enable);
复制代码

这个赋值后有一个函数CLK_XtalConfig
还有一个CLK_XtalCmd
CLK_XtalConfig的函数原型是这样的

  1. /*******************************************************************************
  2. * Function implementation - global ('extern') and local ('static')
  3. ******************************************************************************/
  4. /**
  5. *******************************************************************************
  6. ** \brief  Configures the external high speed oscillator(XTAL).
  7. **
  8. ** \param  [in] pstcXtalCfg            The XTAL configures struct.
  9. **
  10. ** \retval None
  11. **
  12. ** \note   None
  13. **
  14. ******************************************************************************/
  15. void CLK_XtalConfig(const stc_clk_xtal_cfg_t *pstcXtalCfg)
  16. {
  17.     if(NULL != pstcXtalCfg)
  18.     {
  19.         ENABLE_CLOCK_REG_WRITE();

  20.         M4_SYSREG->CMU_XTALCFGR_f.SUPDRV = pstcXtalCfg->enFastStartup;
  21.         M4_SYSREG->CMU_XTALCFGR_f.XTALMS = pstcXtalCfg->enMode;
  22.         M4_SYSREG->CMU_XTALCFGR_f.XTALDRV = pstcXtalCfg->enDrv;

  23.         DISABLE_CLOCK_REG_WRITE();
  24.     }
  25.     else
  26.     {
  27.         /* code */
  28.     }
  29. }
复制代码

往内存写入数据  
CLK_XtalCmd(Enable);

这个函数看一函数原型是什么意思
  1. /**
  2. *******************************************************************************
  3. ** \brief  Enable or disable the XTAL.
  4. **
  5. ** \param  [in] enNewState             The new state of the XTAL.
  6. ** \arg    Enable                      Enable XTAL.
  7. ** \arg    Disable                     Disable XTAL.
  8. **
  9. ** \retval en_result_t
  10. **
  11. ** \note   XTAL can not be stopped if it is used as system clock source or pll
  12. **         clock source.
  13. **
  14. ******************************************************************************/
  15. en_result_t CLK_XtalCmd(en_functional_state_t enNewState)
  16. {
  17.     __IO uint32_t timeout = 0u;
  18.     en_flag_status_t status;
  19.     en_result_t enRet = Ok;

  20.     DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));

  21.     DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));

  22.     ENABLE_CLOCK_REG_WRITE();

  23.     if(Disable == enNewState)
  24.     {
  25.         if(ClkSysSrcXTAL == M4_SYSREG->CMU_CKSWR_f.CKSW)
  26.         {
  27.             enRet = Error;
  28.         }
  29.         else if(ClkPllSrcXTAL == M4_SYSREG->CMU_PLLCFGR_f.PLLSRC)
  30.         {
  31.             if(0u == M4_SYSREG->CMU_PLLCR_f.MPLLOFF)
  32.             {
  33.                 enRet = Error;
  34.             }
  35.             else
  36.             {
  37.                 M4_SYSREG->CMU_XTALCR_f.XTALSTP = 1u;
  38.             }
  39.         }
  40.         else
  41.         {
  42.             M4_SYSREG->CMU_XTALCR_f.XTALSTP = 1u;
  43.         }
  44.     }
  45.     else
  46.     {
  47.          M4_SYSREG->CMU_XTALCR_f.XTALSTP = 0u;
  48.          do
  49.         {
  50.             status = CLK_GetFlagStatus(ClkFlagXTALRdy);
  51.             timeout++;
  52.         }while((timeout < CLK_XTAL_TIMEOUT) && (status != Set));
  53.     }

  54.     DISABLE_CLOCK_REG_WRITE();

  55.     return enRet;
  56. }
复制代码



使用特权

评论回复
 楼主 | 2021-1-18 16:34 | 显示全部楼层
/* Switch system clock source to MPLL. */
    CLK_SetSysClkSource(CLKSysSrcMPLL);
最后总结了啊,看这个函数
  1. /**
  2. *******************************************************************************
  3. ** \brief  Select system clock source.
  4. **
  5. ** \param  [in] enTargetSysSrc         The system clock source.
  6. ** \arg    ClkSysSrcHRC                Select HRC as system clock source.
  7. ** \arg    ClkSysSrcMRC                Select MRC as system clock source.
  8. ** \arg    ClkSysSrcLRC                Select LRC as system clock source.
  9. ** \arg    ClkSysSrcXTAL               Select XTAL as system clock source.
  10. ** \arg    ClkSysSrcXTAL32             Select XTAL32 as system clock source.
  11. ** \arg    CLKSysSrcMPLL               Select MPLL as system clock source.
  12. **
  13. ** \retval None
  14. **
  15. ** \note   Must close all of the fcg register before switch system clock source.
  16. **
  17. ******************************************************************************/
  18. void CLK_SetSysClkSource(en_clk_sys_source_t enTargetSysSrc)
  19. {
  20.     __IO uint32_t timeout = 0ul;
  21.     __IO uint32_t fcg0 = M4_MSTP->FCG0;
  22.     __IO uint32_t fcg1 = M4_MSTP->FCG1;
  23.     __IO uint32_t fcg2 = M4_MSTP->FCG2;
  24.     __IO uint32_t fcg3 = M4_MSTP->FCG3;

  25.     DDL_ASSERT(IS_SYSCLK_SOURCE(enTargetSysSrc));

  26.     ENABLE_FCG0_REG_WRITE();

  27.     /* Only current system clock source or target system clock source is MPLL
  28.     need to close fcg0~fcg3 and open fcg0~fcg3 during switch system clock source.
  29.     We need to backup fcg0~fcg3 before close them. */
  30.     if((CLKSysSrcMPLL == M4_SYSREG->CMU_CKSWR_f.CKSW) ||
  31.         (CLKSysSrcMPLL == enTargetSysSrc))
  32.     {
  33.         /* Close fcg0~fcg3. */
  34.         M4_MSTP->FCG0 = DEFAULT_FCG0;
  35.         M4_MSTP->FCG1 = DEFAULT_FCG1;
  36.         M4_MSTP->FCG2 = DEFAULT_FCG2;
  37.         M4_MSTP->FCG3 = DEFAULT_FCG3;

  38.         /* Wait stable after close fcg. */
  39.         do
  40.         {
  41.             timeout++;
  42.         }while(timeout < CLK_FCG_STABLE);
  43.     }

  44.     /* Switch to target system clock source. */
  45.     ENABLE_CLOCK_REG_WRITE();

  46.     M4_SYSREG->CMU_CKSWR_f.CKSW = enTargetSysSrc;

  47.     DISABLE_CLOCK_REG_WRITE();

  48.     timeout = 0ul;
  49.     do
  50.     {
  51.         timeout++;
  52.     }while(timeout < CLK_SYSCLK_STABLE);

  53.     /* Open fcg0~fcg3. */
  54.     M4_MSTP->FCG0 = fcg0;
  55.     M4_MSTP->FCG1 = fcg1;
  56.     M4_MSTP->FCG2 = fcg2;
  57.     M4_MSTP->FCG3 = fcg3;

  58.     DISABLE_FCG0_REG_WRITE();

  59.     /* Wait stable after open fcg. */
  60.     timeout = 0ul;
  61.     do
  62.     {
  63.         timeout++;
  64.     }while(timeout < CLK_FCG_STABLE);

  65.     SystemCoreClockUpdate();
  66. }
复制代码
  1. M4_SYSREG->CMU_CKSWR_f.CKSW = enTargetSysSrc;
复制代码

看到这个语句了吧,这句话就是定义了到底选择哪个时钟源,后面的话如果再次上电后就会直接调用这个时钟源开始工作

使用特权

评论回复
 楼主 | 2021-1-18 16:36 | 显示全部楼层
  1. /**
  2. *******************************************************************************
  3. ** \brief  The system clock source.
  4. **
  5. ******************************************************************************/
  6. typedef enum en_clk_sys_source
  7. {
  8.      ClkSysSrcHRC                   = 0u,   ///< The system clock source is HRC.
  9.      ClkSysSrcMRC                   = 1u,   ///< The system clock source is MRC.
  10.      ClkSysSrcLRC                   = 2u,   ///< The system clock source is LRC.
  11.      ClkSysSrcXTAL                  = 3u,   ///< The system clock source is XTAL.
  12.      ClkSysSrcXTAL32                = 4u,   ///< The system clock source is XTAL32.
  13.      CLKSysSrcMPLL                  = 5u,   ///< The system clock source is MPLL.
  14. }en_clk_sys_source_t;
复制代码

这里就定义了到底选择 哪个时钟

使用特权

评论回复
 楼主 | 2021-1-18 16:37 | 显示全部楼层
好了结束了,有什么问题,可以回帖,我来进行在线回复

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表