[综合信息]

华大HC32F460的时钟配置

[复制链接]
2629|23
手机看帖
扫描二维码
随时随地手机跟帖
binoo7|  楼主 | 2021-1-18 12:37 | 显示全部楼层 |阅读模式
分享一下我这两天学习到的华大HC32F460的时钟配置过程

使用特权

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

使用特权

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

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

使用特权

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

    SystemCoreClockUpdate();
}

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

使用特权

评论回复
binoo7|  楼主 | 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中的内容,这两个也不相等啊,啥情况?
是我没理解对吗?
看有意思了吧

使用特权

评论回复
评论
86hupeng 2022-2-19 13:35 回复TA
有意思,我也没有理解;解释 VS 程序 VS 手册对不上; 
binoo7|  楼主 | 2021-1-18 15:03 | 显示全部楼层
上面有问题,不管了,继续看下去吧
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赋值的暂时没有找到,没有找到就放弃吧,看另一条路能不能走的通
static void SystemClk_Init(void)
{
    stc_clk_sysclk_cfg_t    stcSysClkCfg;
    stc_clk_xtal_cfg_t      stcXtalCfg;
    stc_clk_mpll_cfg_t      stcMpllCfg;

    MEM_ZERO_STRUCT(stcSysClkCfg);
    MEM_ZERO_STRUCT(stcXtalCfg);
    MEM_ZERO_STRUCT(stcMpllCfg);

    /* Set bus clk div. */
    stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;   // 168MHz
    stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  // 84MHz
    stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  // 168MHz
    stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  // 84MHz
    stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  // 42MHz
    stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  // 42MHz
    stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  // 84MHz
    CLK_SysClkConfig(&stcSysClkCfg);

    /* Switch system clock source to MPLL. */
    /* Use Xtal as MPLL source. */
    stcXtalCfg.enMode = ClkXtalModeOsc;
    stcXtalCfg.enDrv = ClkXtalLowDrv;
    stcXtalCfg.enFastStartup = Enable;
    CLK_XtalConfig(&stcXtalCfg);
    CLK_XtalCmd(Enable);

    /* MPLL config. */
    stcMpllCfg.pllmDiv = 1u;
    stcMpllCfg.plln = 42u;
    stcMpllCfg.PllpDiv = 2u;
    stcMpllCfg.PllqDiv = 2u;
    stcMpllCfg.PllrDiv = 2u;
    CLK_SetPllSource(ClkPllSrcXTAL);
    CLK_MpllConfig(&stcMpllCfg);

    /* flash read wait cycle setting */
    EFM_Unlock();
    EFM_SetLatency(EFM_LATENCY_4);
    EFM_Lock();

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

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

    /* Switch system clock source to MPLL. */
    CLK_SetSysClkSource(CLKSysSrcMPLL);
}

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

使用特权

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

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

/**
*******************************************************************************
** \brief  Configuration structure of system clock.
**
** \note   Configures the system clock if needed.
**
******************************************************************************/
typedef struct stc_clk_sysclk_cfg
{
    en_clk_sysclk_div_factor_t      enHclkDiv;        ///< Division for hclk.
    en_clk_sysclk_div_factor_t      enExclkDiv;       ///< Division for exclk.
    en_clk_sysclk_div_factor_t      enPclk0Div;       ///< Division for pclk0.
    en_clk_sysclk_div_factor_t      enPclk1Div;       ///< Division for pclk1.
    en_clk_sysclk_div_factor_t      enPclk2Div;       ///< Division for pclk2.
    en_clk_sysclk_div_factor_t      enPclk3Div;       ///< Division for pclk3.
    en_clk_sysclk_div_factor_t      enPclk4Div;       ///< Division for pclk4.
}stc_clk_sysclk_cfg_t;



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



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

使用特权

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

使用特权

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

来看第二个啊
    stc_clk_xtal_cfg_t      stcXtalCfg;



这个也是一个定义
/**
*******************************************************************************
** \brief  Configuration structure of XTAL.
**
** \note   Configures the XTAL if needed.
**
******************************************************************************/
typedef struct stc_clk_xtal_cfg
{
    en_functional_state_t           enFastStartup;  ///< Enable fast start up or not.
    en_clk_xtal_mode_t              enMode;         ///< Select xtal mode.
    en_clk_xtal_drv_t               enDrv;          ///< Select xtal drive capability.
}stc_clk_xtal_cfg_t;

原型是这个定义的结构体

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



使用特权

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

使用特权

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

这里面有什么呢看一下
#define MEM_ZERO_STRUCT(x)              do {                                   \
                                        memset((void*)&(x), 0l, (sizeof(x)));  \
                                        }while(0)

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

使用特权

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

果然没错
赋值结束后这个CLK_SysClkConfig是什么意思呢?
/**
*******************************************************************************
** \brief  Configures the division factor for hclk,exck,pclk0,pclk1,pclk2,pclk3,
**         pclk4 from system clock.
**
** \param  [in] pstcSysclkCfg          The system clock configures struct.
**
** \retval None
**
** \note   None
**
******************************************************************************/
void CLK_SysClkConfig(const stc_clk_sysclk_cfg_t *pstcSysclkCfg)
{
    __IO uint32_t timeout = 0ul;
    __IO uint32_t fcg0 = M4_MSTP->FCG0;
    __IO uint32_t fcg1 = M4_MSTP->FCG1;
    __IO uint32_t fcg2 = M4_MSTP->FCG2;
    __IO uint32_t fcg3 = M4_MSTP->FCG3;

    ENABLE_FCG0_REG_WRITE();

    if(NULL != pstcSysclkCfg)
    {
        DDL_ASSERT(IS_SYSCLK_CONFIG_VALID(pstcSysclkCfg));

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

            /* Wait stable after close fcg. */
            do
            {
                timeout++;
            }while(timeout < CLK_FCG_STABLE);
        }

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

        M4_SYSREG->CMU_SCFGR = ( (uint32_t)pstcSysclkCfg->enPclk0Div           |
                                ((uint32_t)pstcSysclkCfg->enPclk1Div << 4u)    |
                                ((uint32_t)pstcSysclkCfg->enPclk2Div << 8u)    |
                                ((uint32_t)pstcSysclkCfg->enPclk3Div << 12u)   |
                                ((uint32_t)pstcSysclkCfg->enPclk4Div << 16u)   |
                                ((uint32_t)pstcSysclkCfg->enExclkDiv << 20u)   |
                                ((uint32_t)pstcSysclkCfg->enHclkDiv << 24u)    |
                                ((uint32_t)pstcSysclkCfg->enHclkDiv << 28u));

        DISABLE_CLOCK_REG_WRITE();

        timeout = 0ul;
        do
        {
            timeout++;
        }while(timeout < CLK_SYSCLK_STABLE);

        /* Open fcg0~fcg3. */
        M4_MSTP->FCG0 = fcg0;
        M4_MSTP->FCG1 = fcg1;
        M4_MSTP->FCG2 = fcg2;
        M4_MSTP->FCG3 = fcg3;

        DISABLE_FCG0_REG_WRITE();

        /* Wait stable after open fcg. */
        timeout = 0ul;
        do
        {
            timeout++;
        }while(timeout < CLK_FCG_STABLE);
    }
    else
    {
        /* code */
    }
}

看到了吧

使用特权

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

使用特权

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

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

使用特权

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

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

使用特权

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

    /* MPLL config. */
    stcMpllCfg.pllmDiv = 1u;
    stcMpllCfg.plln = 42u;
    stcMpllCfg.PllpDiv = 2u;
    stcMpllCfg.PllqDiv = 2u;
    stcMpllCfg.PllrDiv = 2u;
    CLK_SetPllSource(ClkPllSrcXTAL);
    CLK_MpllConfig(&stcMpllCfg);

使用特权

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

/* Switch system clock source to MPLL. */
    /* Use Xtal as MPLL source. */
    stcXtalCfg.enMode = ClkXtalModeOsc;
    stcXtalCfg.enDrv = ClkXtalLowDrv;
    stcXtalCfg.enFastStartup = Enable;
    CLK_XtalConfig(&stcXtalCfg);
    CLK_XtalCmd(Enable);

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

/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
*******************************************************************************
** \brief  Configures the external high speed oscillator(XTAL).
**
** \param  [in] pstcXtalCfg            The XTAL configures struct.
**
** \retval None
**
** \note   None
**
******************************************************************************/
void CLK_XtalConfig(const stc_clk_xtal_cfg_t *pstcXtalCfg)
{
    if(NULL != pstcXtalCfg)
    {
        ENABLE_CLOCK_REG_WRITE();

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

        DISABLE_CLOCK_REG_WRITE();
    }
    else
    {
        /* code */
    }
}

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

这个函数看一函数原型是什么意思
/**
*******************************************************************************
** \brief  Enable or disable the XTAL.
**
** \param  [in] enNewState             The new state of the XTAL.
** \arg    Enable                      Enable XTAL.
** \arg    Disable                     Disable XTAL.
**
** \retval en_result_t
**
** \note   XTAL can not be stopped if it is used as system clock source or pll
**         clock source.
**
******************************************************************************/
en_result_t CLK_XtalCmd(en_functional_state_t enNewState)
{
    __IO uint32_t timeout = 0u;
    en_flag_status_t status;
    en_result_t enRet = Ok;

    DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));

    DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));

    ENABLE_CLOCK_REG_WRITE();

    if(Disable == enNewState)
    {
        if(ClkSysSrcXTAL == M4_SYSREG->CMU_CKSWR_f.CKSW)
        {
            enRet = Error;
        }
        else if(ClkPllSrcXTAL == M4_SYSREG->CMU_PLLCFGR_f.PLLSRC)
        {
            if(0u == M4_SYSREG->CMU_PLLCR_f.MPLLOFF)
            {
                enRet = Error;
            }
            else
            {
                M4_SYSREG->CMU_XTALCR_f.XTALSTP = 1u;
            }
        }
        else
        {
            M4_SYSREG->CMU_XTALCR_f.XTALSTP = 1u;
        }
    }
    else
    {
         M4_SYSREG->CMU_XTALCR_f.XTALSTP = 0u;
         do
        {
            status = CLK_GetFlagStatus(ClkFlagXTALRdy);
            timeout++;
        }while((timeout < CLK_XTAL_TIMEOUT) && (status != Set));
    }

    DISABLE_CLOCK_REG_WRITE();

    return enRet;
}



使用特权

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

    DDL_ASSERT(IS_SYSCLK_SOURCE(enTargetSysSrc));

    ENABLE_FCG0_REG_WRITE();

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

        /* Wait stable after close fcg. */
        do
        {
            timeout++;
        }while(timeout < CLK_FCG_STABLE);
    }

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

    M4_SYSREG->CMU_CKSWR_f.CKSW = enTargetSysSrc;

    DISABLE_CLOCK_REG_WRITE();

    timeout = 0ul;
    do
    {
        timeout++;
    }while(timeout < CLK_SYSCLK_STABLE);

    /* Open fcg0~fcg3. */
    M4_MSTP->FCG0 = fcg0;
    M4_MSTP->FCG1 = fcg1;
    M4_MSTP->FCG2 = fcg2;
    M4_MSTP->FCG3 = fcg3;

    DISABLE_FCG0_REG_WRITE();

    /* Wait stable after open fcg. */
    timeout = 0ul;
    do
    {
        timeout++;
    }while(timeout < CLK_FCG_STABLE);

    SystemCoreClockUpdate();
}
 M4_SYSREG->CMU_CKSWR_f.CKSW = enTargetSysSrc;

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

使用特权

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

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

使用特权

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

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

454

帖子

8

粉丝