一路向北lm 发表于 2020-7-31 09:06

6ull 时钟配置流程

6ULL的时钟源6ULL的时钟比较复杂,我们先来看一下6ULL的7 路 PLL 时钟源,结构图如下所示:

一路向北lm 发表于 2020-7-31 09:07

①.ARM_PLL(PLL1) 此路 PLL 是供 ARM 内核使用的, ARM 内核时钟就是由此 PLL
生成的,此 PLL 通过编程的方式最高可倍频到 1.3GHz。②.528_PLL(PLL2),此路 PLL 也叫做 System_PLL,此路 PLL 是固定的 22 倍频,不可编程修改。因此,此路 PLL 时钟=24MHz * 22 = 528MHz,这也是为什么此 PLL 叫做 528_PLL 的原因。此 PLL 分出了 4 路 PFD,分别为: PLL2_PFD0~PLL2_PFD3,这 4 路 PFD 和 528_PLL共同作为其它很多外设的根时钟源。通常 528_PLL 和这 4 路 PFD 是 I.MX6U 内部系统总
线的时钟源,比如内处理逻辑单元、 DDR 接口、 NAND/NOR 接口等等。③.USB1_PLL(PLL3),此路 PLL 主要用于 USBPHY,此 PLL也有四路 PFD,为:
PLL3_PFD0~PLL3_PFD3,USB1_PLL 是固定的 20 倍频,因此USB1_PLL=24MHz *20=480MHz。USB1_PLL虽然主要用于 USB1PHY,但是其和四路 PFD同样也可以作为其他外设的根时钟源。④. USB2_PLL(PLL7,没有写错!就是 PLL7,虽然序号标为 4,但是实际是 PLL7),看名字就知道此路 PLL是给 USB2PHY使用的。同样的,此路 PLL固定为20倍频,因此也是480MHz。⑤. ENET_PLL(PLL6),此路 PLL固定为 20+5/6 倍频,因此 ENET_PLL=24MHz * (20+5/6)= 500MHz。此路 PLL 用于生成网络所需的时钟,可以在此 PLL 的基础上生成 25/50/100/125MHz的网络时钟。⑥. VIDEO_PLL(PLL5),此路 PLL用于显示相关的外设,比如 LCD,此路PLL 的倍频可以调整, PLL 的输出范围在 650MHz~1300MHz。此路 PLL 在最终输出的时候还可以进行分频,可选 1/2/4/8/16分频。⑦. AUDIO_PLL(PLL4),此路 PLL用于音频相关的外设,此路 PLL 的倍频可以调整, PLL的输出范围同样也是 650MHz~1300MHz,此路 PLL 在最终输出的时候也可以进行分频,可选1/2/4分频。

一路向北lm 发表于 2020-7-31 09:08

6ULL的时钟树

一路向北lm 发表于 2020-7-31 09:09

时钟树图中一共有三部分: CLOCK_SWITCHER、 CLOCK ROOT GENERATOR 和SYSTEM CLOCKS。其中左边的 CLOCK_SWITCHER 就是7 路 PLL 和8 路 PFD,右边的 SYSTEM CLOCKS 就是芯片外设,中间的 CLOCK ROOT GENERATOR 是最复杂的!这一部分就像“月老”一样, 给左边的 CLOCK_SWITCHER和右边的 SYSTEM CLOCKS进行牵线搭桥。外设时钟源是有多路可以选择的, CLOCK ROOT GENERATOR 就负责从 7 路PLL 和 8 路 PFD 中选择合适的时钟源给外设使用,具体操作肯定是设置相应的寄存器。

一路向北lm 发表于 2020-7-31 09:09

①.内核时钟设置:将 I.MX6U 的主频设置为 528MHz,根据图可以看到ARM 内核时钟,内核时钟源来自于 PLL1,假如此时 PLL1 为 996MHz,通过寄存器 CCM_CACRR 的 ARM_PODF 位对 PLL1 进行分频,可选择 1/2/4/8 分频,假如我们选择 2 分频,那么经过分频以后的时钟频率是 996/2=498MHz,经过2 分频以后的 498MHz 就是 ARM 的内核时钟,也就是 I.MX6U 的主频。

一路向北lm 发表于 2020-7-31 09:10

②. PFD 时钟设置,设置好主频以后我们还需要设置好其他的 PLL 和 PFD 时钟, PLL1 已经设置了,PLL2、 PLL3 和 PLL7 固定为 528MHz、 480MHz 和 480MHz, PLL4~PLL6 都是针对特殊外设的,用到的时候再设置。因此,接下来重点就是设置 PLL2 和 PLL3 的各自 4 路 PFD, NXP 推荐的这 8 路 PFD 频率如表所示:

一路向北lm 发表于 2020-7-31 09:11

时钟程序编写如下:/************************************
* ClockInit()
* imx6ull时钟初始化
* 1.设置ARM内核时钟为528M
* 2.设置PLL2各个PFD
* 3.设置PLL3各个PFD
* 4.设置AHB时钟,最大132M
* 5.设置IPG_CLK_ROOT 最大 66Mhz
* 6.设置PERCLK_CLK_ROOT时钟
************************************/
void ClockInit()
{
unsigned int reg = 0;
//设置ARM内核时钟为528M
CCM_CCSR &= ~(1<<8);//配置step_clk时钟源为24MHz OSC
CCM_CCSR |= (1<<2);   //配置pll1_sw_clk时钟源为step_clk
CCM_Analog_PLL_ARM = (1<<13)|((88<<0)&0x7f);//设置pll1_main_clk为 1056MHz
CCM_CCSR &= ~(1<<2);//pll1_sw_clk时钟源切换为pll1_main_clk
CCM_CACRR |= (1<<0);//2分频,ARM内核时钟为pll1_sw_clk/2=1056/2=528Mhz
//设置PLL2各个PFD
reg = CCM_ANALOG_PFD_528;   //读取PLL2之前PFD的设置
reg &= ~(0x3f3f3f3f);       //清除原来设置
reg |= 32<<24;                                // PLL2_PFD3=528*18/32=297Mhz
reg |= 24<<16;                                // PLL2_PFD2=528*18/24=396Mhz(DDR使用的时钟,最大400Mhz)
reg |= 16<<8;                                        // PLL2_PFD1=528*18/16=594Mhz        
reg |= 27<<0;                                        // PLL2_PFD0=528*18/27=352Mhz       
CCM_ANALOG_PFD_528 = reg;   //设置PLL2 PFD时钟
//设置PLL3各个PFD
reg = 0;                  //清0
reg = CCM_ANALOG_PFD_480;   //读取PLL3之前PFD的设置
reg &= ~(0x3f3f3f3f);       //清除原来设置
reg |= 19<<24;                                      //PLL3_PFD3=480*18/19=454.74Mhz
        reg |= 17<<16;                                //PLL3_PFD2=480*18/17=508.24Mhz        
        reg |= 16<<8;                                        //PLL3_PFD1=480*18/16=540Mhz               
        reg |= 12<<0;                                        //PLL3_PFD0=480*18/12=720Mhz       
        CCM_ANALOG_PFD_480=reg;          //设置PLL3_PFD0~3        
//设置AHB时钟,最大132M
CCM_CBCMR &= ~(3<<18);       //清除设置
CCM_CBCMR |= (1<<18);      //pre_periph_clk=PLL2_PFD2=396MHz
CCM_CBCDR &= ~(1 << 25);           //periph_clk=pre_periph_clk=396MHz
while(CCM_CDHIPR & (1 << 5));//等待握手完成
//内部boot rom将AHB_PODF设置为了3分频,我们不需要设置AHB_PODF,AHB_ROOT_CLK 等于 396/3=132Mhz。
//设置IPG_CLK_ROOT 最大 66Mhz
CCM_CBCDR &= ~(3 << 8);             //CBCDR的IPG_PODF清零
        CCM_CBCDR |= 1 << 8;                     //IPG_PODF 2分频,IPG_CLK_ROOT=66MHz
//设置PERCLK_CLK_ROOT时钟
CCM_CSCMR1 &= ~(1 << 6);          //PERCLK_CLK_ROOT时钟源为IPG
        CCM_CSCMR1 &= ~(7 << 0);          //PERCLK_PODF位清零,即1分频
}


一路向北lm 发表于 2020-7-31 09:11

测试代码,仍旧是LED的翻转,只是我们的延时函数会减少一半,LED闪烁更快。void main()
{
    ClockInit();
    EnableClock();
    LedInit();
    BeepInit();
    KeyInit();
    while(1)
    {   
      LedSwitch(0);   /* 关闭 LED */
      delay(500);
      LedSwitch(1);   /* 打开 LED */      
      delay(500);
    }

}


页: [1]
查看完整版本: 6ull 时钟配置流程