AURIX-TC3xx-GTM详解三-CMU(Clock Management Unit)
1、主要框图
主要有三个子模块:EGU(外部发生单元)、CFGU(可配置的时钟发送子单元)、FXU(固定时钟产生)
2、EGU(外部产生单元)
主要作用是通过port对外输出时钟,如给一些外部芯片提供固定频率的时钟。
2.1、使能或禁止EGU功能
可通过以下CMU_CLK_EN寄存器的bit16~bit21分别使能或禁止ECLK0~ECLK2
2.2、分频
按以下公式分频:
其中ECLK[z]_NUM和ECLK[z]_DEN分别由写入以下寄存器决定,Tcls0_clk是簇时钟(在Cluster章节再讲解)
2.3、ELCKx与port对应关系
主要就是ECLK0输出到P23.1,ECLK1输出到P32.4,ECLK2输出到P11.12
另外ELCK0可通过以下寄存器使能输出到CMU_CLK8
另外ELCK1可通过以下寄存器使能输出到CMU_CLK0~CMU_CLK7
2.4、代码示例
以设置和读取ECLK2为例
2.4.1、输出1MHz频率的时钟到port P11.12
/* set ECLK2. */
void GTM_CmuEclk2(void)
{IfxGtm_enable(&MODULE_GTM); /* 使能GTM模块 */IfxGtm_Cmu_setEclkFrequency(&MODULE_GTM, IfxGtm_Cmu_Eclk_2, 1000000); /* 设置ECLK2的时钟频率,比如1MHz */IfxGtm_Cmu_enableClocks(&MODULE_GTM, IFXGTM_CMU_CLKEN_ECLK2); /* 使能ECLK2. */IfxPort_setPinModeOutput(IfxGtm_CLK2_P11_12_OUT.pin.port,IfxGtm_CLK2_P11_12_OUT.pin.pinIndex, IfxPort_OutputMode_pushPull,IfxGtm_CLK2_P11_12_OUT.select); /* 设置P11.12为输出为pushpull结构 */
}
2.4.2、读取ECLK2的时钟频率
/*get ECLK2. */
float32 ECLK2_Freq;
void Eclk2_get(void)
{ECLK2_Freq = IfxGtm_Cmu_getEclkFrequency(&MODULE_GTM,IfxGtm_Cmu_Eclk_2,TRUE);/* 获取ECLK2的时钟频率并存入ECLK2_Freq变量里*/
}
3、CFGU(可配置的时钟产生子单元)
3.1、全局分频(Global Clock Divider)
计算公式TCMU_GCLK_EN=(Z/N)*TCLS0_CLK,寄存器见如下
3.2、CLK0~CLK7时钟来源
可以来源于以下两种
1)3.1章节全局分频后的
2)2.3章节的ECLK2
通过CMU_CLK_CTRL寄存器设置来源于全局分频后的还是ECLK1
另外,
CLK6还可以通过CMU_CLK_6_CTRL寄存器的CLK_SEL(bit24和bit25)选择来源于SUB_INC1c或SUB_INC2;
CLK7还可以通过CMU_CLK_7_CTRL寄存器的CLK_SEL(bit24和bit25)选择来源于SUB_INC2c或SUB_INC1。
3.3、代码示例
3.3.1、GCLK(全局时钟)的设置和获取
设置全局分频时钟(GCLK)为200MHz
/* set GCLK. */
void GTM_CmuGclk(void)
{IfxGtm_enable(&MODULE_GTM); /* 使能GTM模块. */GTM_CMU_CLK_EN.U = 0x00555555; /* 禁用CLK0-7,禁用ECLK0-2,禁用FXCLK. */IfxGtm_Cmu_setGclkFrequency(&MODULE_GTM,200000000); /* 设置GCLK(全局分频后时钟)为200MHz */
}
读取全局分频时钟(GCLK)
/* get GCLK. */
float32 GCLK_Freq;
void Gclk_get(void)
{GCLK_Freq = IfxGtm_Cmu_getGclkFrequency(&MODULE_GTM);/* 获取GCLK时钟频率并存入GCLK_Freq变量里 */
}
3.3.2、CLK的设置和获取
以设置和获取clk0为例
设置clk0时钟频率为1MHz
/*set CLK0 */
void GTM_CmuClk0(void)
{IfxGtm_enable(&MODULE_GTM); /* 使能GTM模块. */IfxGtm_Cmu_setClkFrequency(&MODULE_GTM, IfxGtm_Cmu_Clk_0, 1000000); /* 设置CLK0时钟为1MHz. */IfxGtm_Cmu_enableClocks(&MODULE_GTM, IFXGTM_CMU_CLKEN_CLK0); /* 使能CLK0时钟. */
}
读取clk0的时钟频率
/* get CLK0 */
float32 CLK0_Freq;
void Clk0_get(void)
{CLK0_Freq = IfxGtm_Cmu_getClkFrequency(&MODULE_GTM,IfxGtm_Cmu_Clk_0,TRUE);/* 获取CLK0的时钟频率并存入CLK0_Freq变量 */
}
4、FXU(固定时钟产生)
4.1、固定时钟来源
来源可以是如下
1)GCLK(全局分频后的时钟)
2)CLK0~CLK7
通过以下寄存器选择
4.2、分频
4.1的时钟来源确定后
1)FXCLK0按2分频来源时钟后确定
2)FXCLK1按16分频来源时钟后确定
3)FXCLK2按256分频来源时钟后确定
4)FXCLK3按4096分频来源时钟后确定
5)FXCLK4按65536分频来源时钟后确定
4.3、代码示例
设置FXCLK0~FXCLK4的时钟来源
/*set FxCLK. */
void GTM_CmuFxclk(void)
{IfxGtm_enable(&MODULE_GTM); /* 使能GTM模块. */MODULE_GTM.CMU.FXCLK.CTRL.B.FXCLK_SEL = IfxGtm_Cmu_Clk_0;/* 选择时钟来源为CLK0 */IfxGtm_Cmu_enableClocks(&MODULE_GTM, IFXGTM_CMU_CLKEN_FXCLK); /* 使能固定时钟. */
}
获取FxClk时钟频率
/*get FxCLK */
float32 FxClk0_Freq;
float32 FxClk1_Freq;
float32 FxClk2_Freq;
float32 FxClk3_Freq;
float32 FxClk4_Freq;void Fxclk_get(void)
{FxClk0_Freq = IfxGtm_Cmu_getFxClkFrequency(&MODULE_GTM,IfxGtm_Cmu_Fxclk_0,TRUE);/* 获取FxClk0的时钟频率并存入FxClk0_Freq变量里 */FxClk1_Freq = IfxGtm_Cmu_getFxClkFrequency(&MODULE_GTM,IfxGtm_Cmu_Fxclk_1,TRUE);/* 获取FxClk1的时钟频率并存入FxClk1_Freq变量里 */FxClk2_Freq = IfxGtm_Cmu_getFxClkFrequency(&MODULE_GTM,IfxGtm_Cmu_Fxclk_2,TRUE);/* 获取FxClk2的时钟频率并存入FxClk2_Freq变量里 */FxClk3_Freq = IfxGtm_Cmu_getFxClkFrequency(&MODULE_GTM,IfxGtm_Cmu_Fxclk_3,TRUE);/* 获取FxClk3的时钟频率并存入FxClk3_Freq变量里 */FxClk4_Freq = IfxGtm_Cmu_getFxClkFrequency(&MODULE_GTM,IfxGtm_Cmu_Fxclk_4,TRUE);/* 获取FxClk4的时钟频率并存入FxClk4_Freq变量里 */
}
5、总结
1)ECLK主要用于给外部芯片提供时钟的场合
2)CFGU时钟主要给TIM、TBU、ATOM和MON等需要复杂时钟的场合
3)FXU时钟主要给TOM和MON等应用比较简单的场合