I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)

7 路 PLL 和 8 路 PFD 设置完成以后最后还需要设置 AHB_CLK_ROOT 和 IPG_CLK_ROOT的时钟。

AHB、 IPG时钟设置

I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)_第1张图片
简化后
I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)_第2张图片

①、此选择器用来选择 pre_periph_clk 的时钟源,可以选择 PLL2、 PLL2_PFD2、 PLL2_PFD0和 PLL2_PFD2/2。寄存器 CCM_CBCMR 的 PRE_PERIPH_CLK_SEL 位决定选择哪一个,默认选择 PLL2_PFD2,因此 pre_periph_clk=PLL2_PFD2=396MHz。
②、此选择器用来选择 periph_clk 的时钟源,由寄存器 CCM_CBCDR 的 PERIPH_CLK_SEL位与 PLL_bypass_en2 组成的或来选择。当 CCM_CBCDR 的 PERIPH_CLK_SEL 位为 0 的时候periph_clk=pr_periph_clk=396MHz。
③、通过 CBCDR 的 AHB_PODF 位来设置 AHB_CLK_ROOT 的分频值,可以设置 1~8 分频,如果想要 AHB_CLK_ROOT=132MHz 的话就应该设置为 3 分频: 396/3=132MHz。图 16.1.2中虽然写的是默认 4 分频,但是 I.MX6U 的内部 boot rom 将其改为了 3 分频!
④、通过 CBCDR 的 IPG_PODF 位来设置 IPG_CLK_ROOT 的分频值,可以设置 1~4 分频,IPG_CLK_ROOT 时钟源是 AHB_CLK_ROOT,要想 IPG_CLK_ROOT=66MHz 的话就应该设置2 分频: 132/2=66MHz。

由下图可知,AHB_CLK_ROOT 最高可以设置132MHz,IPG_CLK_ROOT和PERCLK_CLK_ROOT最高可以设置66MHz。

I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)_第3张图片

CCM->CBCMR &= ~(3 << 18); 	/* 清除设置*/ 
CCM->CBCMR |= (1 << 18);	/* pre_periph_clk=PLL2_PFD2=396MHz */

I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)_第4张图片

CCM->CBCDR &= ~(1 << 25);	/* periph_clk=pre_periph_clk=396MHz */

I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)_第5张图片

CCM->CBCDR &= ~(3 << 8);	/* CBCDR的IPG_PODF清零 */
	CCM->CBCDR |= 1 << 8;		/* IPG_PODF 2分频,IPG_CLK_ROOT=66MHz */

I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)_第6张图片

握手

在这里插入图片描述
I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)_第7张图片

while(CCM->CDHIPR & (1 << 5));/* 等待握手完成 */
		
	/* 修改AHB_PODF位的时候需要先禁止AHB_CLK_ROOT的输出,但是
	 * 我没有找到关闭AHB_CLK_ROOT输出的的寄存器,所以就没法设置。
	 * 下面设置AHB_PODF的代码仅供学习参考不能直接拿来使用!!
	 * 内部boot rom将AHB_PODF设置为了3分频,即使我们不设置AHB_PODF,
	 * AHB_ROOT_CLK也依旧等于396/3=132Mhz。
	 */
#if 0
	/* 要先关闭AHB_ROOT_CLK输出,否则时钟设置会出错 */
	CCM->CBCDR &= ~(7 << 10);	/* CBCDR的AHB_PODF清零 */
	CCM->CBCDR |= 2 << 10;		/* AHB_PODF 3分频,AHB_CLK_ROOT=132MHz */
	while(CCM->CDHIPR & (1 << 1));/
* 等待握手完成 */
#endif

在修改如下时钟选择器或者分频器的时候会引起与 MMDC 的握手发生:
①、 mmdc_podf
②、 periph_clk_sel
③、 periph2_clk_sel
④、 arm_podf
⑤、 ahb_podf
发生握手信号以后需要等待握手完成,寄存器 CCM_CDHIPR 中保存着握手信号是否完成,如果相应的位为 1 的话就表示握手没有完成,如果为 0 的话就表示握手完成,很简单,这里就不详细的列举寄存器 CCM_CDHIPR 中的各个位了。另外在修改 arm_podf 和 ahb_podf 的时候需要先关闭其时钟输出,等修改完成以后再打开,否则的话可能会出现在修改完成以后没有时钟输出的问题。需要修改寄存器CCM_CBCDR 的 AHB_PODF 位来设置 AHB_ROOT_CLK 的时钟,所以在修改之前必须先关闭AHB_ROOT_CLK 的输出。但是笔者没有找到相应的寄存器,因此目前没法关闭,那也就没法设置 AHB_PODF 了。不过 AHB_PODF 内部 boot rom 设置为了 3 分频,如果 pre_periph_clk 的时钟源选择 PLL2_PFD2 的话, AHB_ROOT_CLK 也是 396MHz/3=132MHz。

官方文档
18.5.1.5.6 Divider change handshake
Modifying the following dividers will start the handshake with MMDC.
• mmdc_podf
• periph_clk_sel
• periph2_clk_sel
• arm_podf
• ahb_podf
The dividers listed above are designed with a handshake. For dividers without ahandshake design, the following sequence must be performed when updating PODF value:

  1. Gate the output clock off before updating PODF value.
  2. Gate the output clock on after the PODF value is updated and stable.
    To update the PODF value without gating the output clock off will cause unpredictable results such as no clock output.
    I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)_第8张图片

PERCLK_CLK_ROOT 时钟频率

CCM->CSCMR1 &= ~(1 << 6);	/* PERCLK_CLK_ROOT时钟源为IPG */
	CCM->CSCMR1 &= ~(7 << 0);	/* PERCLK_PODF位清零,即1分频 */

在这里插入图片描述
I.MX6U 的时钟系统 -3(AHB、 IPG 和 PERCLK 根时钟设置)_第9张图片

你可能感兴趣的:(imx6ull)