imx6u时钟配置
系统时钟来源
开发板的系统时钟来源于两部分:32.768KHz 和24MHz 的晶振,其中 32.768KHz 晶振是 I.MX6U 的 RTC 时钟源,24MHz 晶振是 I.MX6U 内核和其它外设的时钟源。
I.MX6U 的外设有很多,不同的外设时钟源不同,这些外设的时钟源分了7组,这 7 组时钟源都是从 24MHz 晶振 PLL 而来的,因此也叫做 7 组 PLL.
时钟树
由下面的时钟切换图可知,IMX6U总共有7组PLL:
PLL1(996M)、PLL2(528M)、PLL3(480M)、PLL4、PLL5、PLL6、PLL7
其中PLL2、PLL3各自有4组PFD,这些PFD以PLL为基础,经过不同的分频系数可以产生不同频率的时钟,在参考手册的相关寄存器的地方,可以看到官方有推荐的配置参数。(《IMX6UL参考手册》
①、 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_PFD0PLL2_PFD3,这 4 路 PFD 和 528_PLL共同作为其它很多外设的根时钟源。通常 528_PLL 和这 4 路 PFD 是 I.MX6U 内部系统总线的时钟源,比如内处理逻辑单元、DDR 接口、NAND/NOR 接口等等。PLL3_PFD3,USB1_PLL 是固定的 20 倍频,因此 USB1_PLL=24MHz *20=480MHz。
③、USB1_PLL(PLL3),此路 PLL 主要用于 USBPHY,此 PLL 也有四路 PFD,为:PLL3_PFD0
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 的输出范围在 650MHz1300MHz。此路 PLL 在最终输出的时候还可以进行分频,可选 1/2/4/8/16 分频。1300MHz,此路 PLL 在最终输出的时候也可以进行分频,可选1/2/4 分频。
⑦、AUDIO_PLL(PLL4),此路 PLL 用于音频相关的外设,此路 PLL 的倍频可以调整,PLL的输出范围同样也是 650MHz
PLL:接收锁相环输出时钟和锁相环旁路时钟。 简单来说,锁相环就是用来将外部晶振进行倍频,以实现稳定且高频的时钟信号。
内核时钟设置(PLL1)
①、pll1_sw_clk 也就是 PLL1 的最终输出频率。
②、此处是一个选择器,选择 pll1_sw_clk 的时钟源,由寄存器 CCM_CCSR 的PLL1_SW_CLK_SEL 位决定 pll1_sw_clk 是选择 pll1_main_clk 还是 step_clk。正常情况下应该选择 pll1_main_clk,但是如果要对 pll1_main_clk(PLL1)的频率进行调整的话,比如我们要设置PLL1=1056MHz,此时就要先将 pll1_sw_clk 切换到 step_clk 上。等 pll1_main_clk 调整完成以后再切换回来。
③、此处也是一个选择器,选择 step_clk 的时钟源,由寄存器 CCM_CCSR 的 STEP_SEL 位来决定 step_clk 是选择 osc_clk 还是 secondary_clk。一般选择 osc_clk,也就是 24MHz 的晶振。
首先要使用CCM_CCSR寄存器来决定使用时钟源来进行配置。
①、 设置寄存器 CCSR 的 STEP_SEL 位,设置 step_clk 的时钟源为 24M 的晶振。
②、设置寄存器 CCSR 的 PLL1_SW_CLK_SEL 位,设置 pll1_sw_clk 的时钟源为
step_clk=24MHz,通过这一步我们就将 I.MX6U 的主频先设置为 24MHz,直接来自于外部的
24M 晶振。
③、设置寄存器 CCM_ANALOG_PLL_ARMn,将 pll1_main_clk(PLL1)设置为 1056MHz。
④、设置寄存器 CCSR 的 PLL1_SW_CLK_SEL 位,重新将 pll1_sw_clk 的时钟源切换回
pll1_main_clk,切换回来以后的 pll1_sw_clk 就等于 1056MHz。
⑤、最后设置寄存器 CCM_CACRR 的 ARM_PODF 为 2 分频,I.MX6U 的内核主频就为
1056/2=528MHz。
PFD 时钟设置
设置好主频以后我们还需要设置好其他的 PLL 和 PFD 时钟,PLL1 上一小节已经设置了,PLL2、PLL3 和 PLL7 固定为 528MHz、480MHz 和 480MHz,PLL4~PLL6 都是针对特殊外设的,用到的时候再设置。因此,接下来重点就是设置 PLL2 和 PLL3 的各自 4 路 PFD,这 8 路 PFD 频率如表 所示:
设置PFD0~3需要按照寄存器的所在位进行置数。以下是寄存器CCM_ANALOG_PFD_528n的结构。
频率计算公式
PLL2_PFDX=528*18/PFDX_FRAC(X=1~3)。
*PLL3_PFDX=48018/PFDX_FRAC(X=0~3)**。
例如设置PFD3的的频率为297MHz需要进行以下设置。
1 | unsigned int reg = 0; |
AHB、IPG 和 PERCLK 根时钟设置
7 路 PLL 和 8 路 PFD 设置完成以后最后还需要设置 AHB_CLK_ROOT 和 IPG_CLK_ROOT的时钟,I.MX6U 外设根时钟可设置范围如图:
AHB_CLK_ROOT 最高可以设置 132MHz,IPG_CLK_ROOT 和PERCLK_CLK_ROOT 最高可以设置66MHz。
①、此选择器用来选择 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 的分频值,可以设置 18 分频,如果想要 AHB_CLK_ROOT=132MHz 的话就应该设置为 3 分频:396/3=132MHz。图 中虽然写的是默认 4 分频,但是 I.MX6U 的内部 boot rom 将其改为了 3 分频!4 分频,IPG_CLK_ROOT 时钟源是 AHB_CLK_ROOT,要想 IPG_CLK_ROOT=66MHz 的话就应该设置2 分频:132/2=66MHz。
④、通过 CBCDR 的 IPG_PODF 位来设置 IPG_CLK_ROOT 的分频值,可以设置 1
设置 PERCLK_CLK_ROOT 时钟频率
PERCLK_CLK_ROOT 来 源 有 两 种 : OSC(24MHz) 和IPG_CLK_ROOT,由寄存器 CCM_CSCMR1 的 PERCLK_CLK_SEL 位来决定,如果为 0 的话,PERCLK_CLK_ROOT 的时钟源就是 IPG_CLK_ROOT=66MHz 。可以通过寄存器CCM_CSCMR1 的 PERCLK_PODF 位来设置分频,如果要设置 PERCLK_CLK_ROOT 为 66MHz的话就要设置为 1 分频。
1 | void clk_enable(void) |