[IMX] 03.时钟树 - Clock Tree
目录
1.PLL 时钟源
2.Clock Tree 时钟树
3.ARM 内核时钟
3.1.频率设置 - CCM_ANALOG_PLL_ARMn
3.2.时钟分频 - CCM_CACRR
3.3.时钟源选择 - CCM_CCSR
3.4.修改 ARM 内核时钟
4.PFD 时钟
4.1.PLL2_PFD 频率 - CCM_ANALOG_PFD_528n
4.2.PLL3_PFD 频率 - CCM_ANALOG_PFD_480n
5.AHB、IPG、PERCLK 时钟
5.1.根时钟
5.2.时钟设置 - CCM_CBCDR
5.3.总线时钟复用 - CCM_CBCMR
5.4.串行时钟复用 - CCM_CSCMR1
5.5.注意事项
I.MX6U-ALPHA 开发板的系统时钟源有两部分:32.768KHz 的晶振和 24MHz 的晶振
32.768KHz 晶振是 I.MX6U 的 RTC 时钟源,24MHz 晶振是 I.MX6U 内核和其它外设的时钟源
硬件原理图如下:
1.PLL 时钟源
I.MX6U 的外设有很多,不同外设的时钟源不同
NXP 将这些时钟源分为 7 组(PLL1 ~ PLL7),7 组 PLL 时钟源均为 24MHz 晶振通过 PLL 获得,因此称为 7 组 PLL
PLL 时钟源的大致结构如下所示:
图中每组 PLL 的作用如下:
-
PLL1:ARM_PLL,该 PLL 供 ARM 内核使用,用于生成 ARM 内核时钟,可通过配置相关寄存器将 ARM 频率提升至最高 1.3GHz;
-
PLL2:528_PLL,该 PLL 为 System_PLL,为固定的 22 倍频,无法通过寄存器修改,频率为 24MHz * 22 = 528MHz,因此称为 528_PLL,从该路 PLL 中分出了 4 路 PFD(PLL2_PFD0 ~ PLL2_PFD3),这 4 路 PFD 和 PLL2 本身,作为外设的时钟源以及内部总线的时钟源,如 DDR 接口、NAND/NOR 接口等;
-
PLL3:USB1_PLL,该 PLL 用于 USBPHY,同时分出了 4 路 PFD(PLL3_PFD0 ~ PLL3_PFD3),USB1_PLL 为固定的 20 倍频,频率为 24MHz * 20 = 480MHz,因此也称为 480_PLL,该 PLL 和 4 路 PFD 可以用作其他外设的根时钟源;
-
PLL7:USB2_PLL,该 PLL 用于 USB2PHY,为固定的 20 倍频,频率为 24MHz * 20 = 480MHz;
-
PLL6:ENET_PLL,该 PLL 用于以太网,为固定的 20 + 5/6 倍频,频率为 24MHz * (20 + 5 / 6) = 500MHz;
-
PLL5:VIDEO_PLL,该 PLL 用于显示外设,可以调整倍频(1/2/4/8/16 倍率),输出范围为 650MHz ~ 1300MHz;
-
PLL4:AUDIO_PLL,该 PLL 用于音频外设,可以调整倍频(1/2/4 倍率),输出范围为 650MHz ~ 1300MHz;
2.Clock Tree 时钟树
I.MX6U 所有外设的时钟源均来自 7 路 PLL 及 PLL2/PLL3 分出的 PFD,这些时钟源共同构成 I.MX6U 的时钟树,其结构如下所示:
时钟树中包含三个部分:CLOCK_ROOT_GENERATOR、CLOCK_SWITCHER、SYSTEM_CLOCKS
-
CLOCK_SWITCHER:时钟源,7 路 PLL 和 8 路 PFD;
-
SYSTEM_CLOCKS:芯片外设;
-
CLOCK_ROOT_GENERATOR:时钟分配器(多路选择器),将 CLOCK_SWITCHER 提供的时钟源,分配给对应的 SYSTEM_CLOCKS,执行分频操作和多路选择操作;
以 ESAI 外设的时钟为例,其在时钟树中的节点如下所示:
-
ESAI 有 4 路时钟源(PLL4、PLL5、PLL3_PFD2、pll3_sw_clk),由寄存器 CCM_CSCMR2 的 ESAI_CLK_SEL 字段选择时钟源:
-
该部分为 ESAI 时钟的前置分频,由寄存器 CCM_CS1CDR 的 ESAI_CLK_PRED 字段设置分频值,可设置 1~8 分频,假如 PLL4 = 650MHz,选择 PLL4 作为 ESAI 的时钟源,前置分频选择 2 分频,则此时的时钟频率为 650 / 2 = 325MHz;
-
该部分为 ESAI 时钟的后置分频,对前置分频中输出的时钟信号进一步分频,由寄存器 CCM_CS1CDR 的 ESAI_CLK_PODF 字段设置分频值,可以设置 1~8 分频,若设置为 8 分频,则经过此分频器后的时钟频率为 325 / 8 = 40.625MHz,因此最终 ESAI 外设的时钟频率为 40.625MHz;
3.ARM 内核时钟
ARM 内核时钟在时钟树中的节点如下所示:
其中各部分的含义如下:
-
时钟源 PLL1,默认频率 996MHz;
-
前置分频,由 CCM_CACRR 寄存器的 ARM_PODF 字段控制,可选择 1/2/4/8 分频,若选择 2 分频,则 ARM 内核时钟的频率为 996MHz / 2 = 498MHz;
-
后置分频,默认值为 1,即不进行分频;
-
最终输出的 ARM 内核时钟(CPU 主频);
3.1.频率设置 - CCM_ANALOG_PLL_ARMn
CCM_ANALOG_PLL_ARMn 寄存器设置内核 n 对应的时钟源:
其中关注如下几个字段:
-
ENABLE:使能时钟输出,为 1 时使能,为 0 时禁用;
-
DIV_SELECT:控制 PLL1 的输出频率,范围为 54~108,计算公式为 PLL1 CLK = Fin * div_seclec / 2.0(Fin=24MHz),若需要设置 PLL1 输出为 1056MHz,则 div_select 应该设置为 88;
3.2.时钟分频 - CCM_CACRR
CCM_CACRR 寄存器的 ARM_PODF 字段设置 ARM 时钟分频的倍率(可设置 1~8 倍),CCM_CACRR 寄存器包含的字段如下所示:
3.3.时钟源选择 - CCM_CCSR
修改 ARM 内核时钟时,需要先将时钟源切换为其他时钟源,ARM 内核可选的时钟源如下所示:
其中:
-
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 寄存器用于选择 PLL1 的时钟源,其包含的字段如下所示:
其中,关注以下字段:
-
STEP_SEL:step_clk 时钟源选择:
-
0:osc_clk(24MHz)晶振;
-
1:secondary_clk;
-
-
PLL1_SW_CLK_SEL:pll1_sw_clk 时钟源选择:
-
0:pll1_main_clk;
-
1:step_clk;
-
3.4.修改 ARM 内核时钟
修改 ARM 内核时钟频率的步骤如下:
-
设置寄存器 CCM_CCSR 的 STEP_SEL 位,设置 step_clk 的时钟源为 24MHz 的晶振;
-
设置寄存器 CCM_CCSR 的 PLL1_SW_CLK_SEL 位,设置 pll1_sw_clk 的时钟源为 step_clk = 24MHz,即将内核的主频先设置为 24MHz,(直接来自于外部的 24MHz 的晶振);
-
设置寄存器 CCM_ANALOG_PLL_ARMn 的 DIV_SELECT 字段,将 pll1_main_clk(PLL1)设置为 1056MHz;
-
设置寄存器 CCM_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;
4.PFD 时钟
PLL2、PLL3 和 PLL7 固定为 528MHz、480MHz 和 480MHz
PLL4、PLL5、PLL6 都是针对特殊外设的,用到的时候再设置
因此,接下来的重点是设置 PLL2 和 PLL3 各自的 4 路 PFD,NXP 推荐的 PFD 频率如下:
4.1.PLL2_PFD 频率 - CCM_ANALOG_PFD_528n
CCM_ANALOG_PFD_528n 寄存器用于设置 PLL2_PFD0~PLL2_PFD3,其包含的字段如下所示:
CCM_ANALOG_PFD_528n 寄存器内部分为 4 组,分别对应 PFD0~PFD3,以 PFD0 为例,其对应字段的含义如下:
-
PFD0_FRAC:PLL2_PFD0 的分频倍率,PLL2_PFD0 的计算公式为 528 * 18 / PFD0_FRAC,该字段可设置的范围为 12~35,如果 PLL2_PFD0 的频率要设置为 352MHz,则 PFD0_FRAC = 528 * 18 / 352 = 27;
-
PFD0_STABLE:此位为只读位,可以通过读取此位判断 PLL2_PFD0 是否稳定;
-
PFD0_CLKGATE:PLL2_PFD0 输出使能位,为 1 时关闭 PLL2_PFD0 的输出,为 0 的时使能输出;
PLL2_PFD 频率的计算公式为 528 * 18 / PFDx_FRAC (x = 1~3),若要设置 PLL2_PFD0 的频率为 352MHz,则需要设置 PFD0_FRAC 为 27, PFD0_CLKGATE 为 0,PLL2_PFD1~PLL2_PFD3 的设置类似
PLL2_PFD1 = 594MHz 时,PFD1_FRAC = 16
PLL2_PFD2 = 400MHz 时 PFD2_FRAC 无法整除,因此取最近的整数值,即 PFD2_FRAC = 24, 因此 PLL2_PFD2 实际为 396MHz
PLL2_PFD3 = 297MHz 时,PFD3_FRAC = 32
4.2.PLL3_PFD 频率 - CCM_ANALOG_PFD_480n
CCM_ANALOG_PFD_480n 寄存器用于设置 PLL3_PFD0~PLL3_PFD3,其包含的字段如下所示:
寄存器 CCM_ANALOG_PFD_480n 和 CCM_ANALOG_PFD_528n 的结构一样,寄存器位的含义也一样,只是频率计算公式不同,PLL3_PFD 频率的计算公式为 PLL3_PFDx = 480 * 18 / PFDx_FRAC(x = 0~3)
PLL3_PFD0 = 720MHz 时,PFD0_FRAC = 12
PLL3_PFD1 = 540MHz 时,PFD1_FRAC = 16
PLL3_PFD2 = 508.2MHz 时,PFD2_FRAC = 17
PLL3_PFD3 = 454.7MHz 时,PFD3_FRAC = 19
5.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
因此,将 AHB_CLK_ROOT、IPG_CLK_ROOT 和 PERCLK_CLK_ROOT 分别设置为 132MHz、66MHz、66MHz
5.1.根时钟
AHB_CLK_ROOT 和 IPG_CLK_ROOT 的结构如下图所示:
-
该选择器用于选择 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,时钟树图中虽然写的是默认为 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;
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 分频
5.2.时钟设置 - CCM_CBCDR
CCM_CBCDR 用于设置时钟的分频值以及外设的根时钟,其包含的字段如下所示:
其中各字段的含义如下:
-
PERIPH_CLK2_PODF:periph2 的分频值,可设置为 0~7,分别对应 1~8 分频;
-
PERIPH2_CLK_SEL:选择 peripheral2 的根时钟,为 0 时选择 PLL2,为 1 时选择 periph2_clk2_clk,修改此位会触发一次 MMDC 握手,所以修改完成后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定的位表示;
-
PERIPH_CLK_SEL:peripheral 根时钟选择,为 0 时选择 PLL2,为 1 时选择 periph_clk2_clock,修改此位会触发一次 MMDC 握手,所以修改完成后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定的位表示;
-
AXI_PODF:axi 时钟分频,可设置为 0~7,分别对应 1~8 分频;
-
AHB_PODF:ahb 时钟分频,可设置为 0~7,分别对应 1~8 分频,修改此位会触发一次 MMDC 握手,所以修改完成后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定的位表示;
-
IPG_PODF:ipg 时钟分频,可设置为 0~3,分别对应 1~4 分频;
-
AXI_ALT_CLK_SEL:axi_alt 时钟选择,为 0 时选择 PLL2_PFD2,为 1 时选择 PLL3_PFD1;
-
AXI_CLK_SEL:axi 时钟源选择,为 0 时选择 periph_clk,为 1 时选择 axi_alt 时钟;
-
FABRIC_MMDC_PODF:fabric/mmdc 时钟分频,可设置为 0~7,分别对应 1~8 分频;
-
PERIPH2_CLK2_PODF:periph2_clk2 的时钟分频,可设置为 0~7,分别对应 1~8 分频;
5.3.总线时钟复用 - CCM_CBCMR
CCM_CBCMR 寄存器控制总线时钟的多路复用,其包含的字段如下所示:
其中各字段的含义如下:
-
LCDIF1_PODF:lcdif1 的时钟分频,可设置为 0~7,分别对应 1~8 分频;
-
PRE_PERIPH2_CLK_SEL:pre_periph2 时钟源选择,00 选择 PLL2,01 选择 PLL2_PFD2,10 选择 PLL2_PFD0,11 选择 PLL4;
-
PERIPH2_CLK2_SEL:periph2_clk2 时钟源选择,为 0 时选择 pll3_sw_clk,为 1 时选择 OSC;
-
PRE_PERIPH_CLK_SEL:pre_periph 时钟源选择,00 选择 PLL2,01 选择 PLL2_PFD2,10 选择 PLL2_PFD0,11 选择 PLL2_PFD2/2;
-
PERIPH_CLK2_SEL:peripheral_clk2 时钟源选择,00 选择 pll3_sw_clk,01 选择 osc_clk,10 选择 pll2_bypass_clk;
5.4.串行时钟复用 - CCM_CSCMR1
CCM_CBCMR1 寄存器控制串行外设时钟的多路复用,其包含的字段如下所示:
其中主要关注以下几个字段:
-
PERCLK_CK_SEL:perclk 时钟源选择,为 0 时选择 ipg_clk,为 1 时选择 osc_clk;
-
PERCLK_PODF:perclk 的时钟分频,可设置为 0~7,分别对应 1~8 分频;
5.5.注意事项
修改如下时钟选择器或分频器时会触发 MMDC 握手:
-
mmdc_podf;
-
periph_clk_sel;
-
periph2_clk_sel;
-
arm_podf;
-
ahb_podf;
触发握手信号后需要等待握手完成,寄存器 CCM_CDHIPR 中的相关字段指示握手是否完成,相应位为 1 表示握手没有完成,为 0 表示握手完成
修改 arm_podf 和 ahb_podf 时需要先关闭时钟输出,等修改完成后再打开,否则可能会出现在修改完成后没有时钟输出的问题
教程中需要修改寄存器 CCM_CBCDR 的 AHB_PODF 位设置 AHB_ROOT_CLK 的时钟,所以在修改前必须先关闭 AHB_ROOT_CLK 的输出,但未找到相应的寄存器,因此目前没法关闭,也就没法设置 AHB_PODF,不过内部 Boot ROM 已经将其设置为 3 分频,若 pre_periph_clk 的时钟源选择 PLL2_PFD2,AHB_ROOT_CLK 也是 396MHz / 3 = 132MHz