公司动态

ARM---I.MX6ULL时钟系统详解、时钟树、系统时钟配置等

📅 2026/7/23 23:18:25
ARM---I.MX6ULL时钟系统详解、时钟树、系统时钟配置等
一. I.MX6ULL时钟系统详解I.MX6ULL 的系统主频为 528MHz有些型号可以跑到 696MHz但是默认情况下内部 boot r om会将 I.MX6ULL 的主频设置为 396MHz。在使用 I.MX6ULL 的时候肯定是要发挥它的最大性能那么主频肯定要设置到 528MHz(其它型号可以设置更高比如 696MHz)其它的外设时钟也要设置到 NXP 推荐的值如下表所示。1.1 系统时钟的来源从图中可以看出 I.MX6ULL 开发板的系统时钟来源于两部分32.768KHz 和 2 4MHz 的晶振其中32.768KHz 晶振是 I.MX6ULL 的 RTC 时钟源(实时时钟)24MHz 晶振是 I.MX6ULL 内核和其它外设的时钟源也是重点1.2 七路 PLL 时钟源I.MX6ULL 的外设有很多不同的外设时钟源不同NXP 将这些外设的时钟源进行了分组 一共有 7 组这 7 组时钟源都是从24MHz 晶振 PLL而来的因此也叫做 7 组 PLLPLL锁相环Phase-Locked Loop全称相位锁定环路模拟高频发生电路功能外部只有低速晶振i.MX6ULL 为 24MHzPLL 可以把 24MHz 成倍放大到几百 MHz供给 CPU、DDR、高速外设。 普通分频器只能降频只有 PLL 能升频。这七个PLL如下表所示ARM PLLPLL 1作用给 Cortex-A7 CPU 内核提供主频时钟该锁相环从 24 MHz 的参考时钟中合成出具有低抖动的时钟。此锁相环的时钟输出频率范围在650 MHz 至 1.3 GHz之间。输出频率由 7 位寄存器字段CCM_ANALOG_PLL_ARM[DIV_SELECT]来选择地址0x020C8000PLL 输出频率 Fref * DIV_SEL / 2System PLL(528 PLL)PLL 2固定倍频不可软件修改,输出恒定 528MHz固定22倍频PFD 典型输出PFD0 352 MHzPFD1 594 MHzPFD2 400(396) MHzPFD3 297 MHz作用SoC 绝大多数总线、内存、通用外设时钟所使用通常 528_PLL 和这 4 路 PFD 是 I.MX6U 内部系统总线的 时钟源比如内处理逻辑单元、DDR 接口、NAND/NOR 接口等等USB1 PLL(480 PLL)PLL 3固定倍频不可软件修改,输出恒定 480 MHz固定倍频20倍频PFD 典型输出PFD0 720 MHzPFD1 540 MHzPFD2 508 MHzPFD3 454.7 MHz作用此路 PLL 主要用于 USBPHY但是其和四路 PFD 同样也可以作为其他外设的根时钟源PLL 4Audio PLL主供给音频使用音频接口SPDIF, SAI1 - SAI3输出范围650MHz ~ 1.3GHz输出频率可通过编程 CCM_ANALOG_PLL_AUDIO、CCM_ANALOG_PLL_VIDEO 和 CCM_ANALOG_MISC2 寄存器组中的字段来设定其依据以下公式计算得出PLL output frequency Fref * (DIV_SELECT NUM/DENOM)PLL 5Video PLL主供给视频外设和图像处理有关的外设egRGB LCD接口输出范围650MHz ~ 1.3GHz输出频率可通过编程 CCM_ANALOG_PLL_AUDIO、CCM_ANALOG_PLL_VIDEO 和 CCM_ANALOG_MISC2 寄存器组中的字段来设定其依据以下公式计算得出PLL output frequency Fref * (DIV_SELECT NUM/DENOM)PLL 6Ethernet PLL此路 PLL 固定为 205/6 倍频因此 ENET_PLL24MHz * (205/6) 500MHz。作用用于生成网络所需的时钟PLL 7USB2 PLL用来调试1.3 CCM clock tree 时钟树简介在图中一共有三部分CLOCK_SWITCHER、CLOCK ROOT GENERATOR和SYSTEM CLOCKS。其中左边的 CLOCK_SWITCHER 就是上一小节讲解的那 7 路 PLL 和 8 路 PFD右边的 SYSTEM CLOCKS 就是芯片外设中间的 CLOCK ROOT GENERATOR 是 最复杂的这一部分就像“月老”一样 给左边的 CLOCK_SWITCHER 和右边的 SYSTEM C LOCKS 进行牵线搭桥。外设时钟源是有多路可以选择的CLOCK ROOT GENERATOR 就负 责从 7 路 PLL 和 8 路 PFD 中选择合适的时钟源给外设使用1.4 有关时钟配置的器件1.4.1 PLL锁相环phased locked loop作用倍频倍频因子N输出24*N1.4.2 Prescaler预分频器Prescaler作用分频分频因子M输出24/M1.4.3 PFD相位分数分频器phased fraction divder作用可以倍频也可以降频倍频分频因子N M输出24 * N / MN /M 1倍频N / M1降频二. 系统时钟配置2.1 内核时钟配置使用到的寄存器CCMClock Controller Module时钟控制器模块的各种寄存器CCM_ANALOG系列寄存器2.1.1 ARM内核时钟树ARM内核时钟树如下图1、内核时钟源来自于 PLL1此时 PLL1 为 996MHz。2、通过寄存器CCM_CACRR的ARM_PODF位对PLL1进行分频可选择 1/2/4等分频假如选择 2 分频那么经过分频以后的时钟频率是 996/2498MHz也就是IMX6ULL的主频3、设置内核主频为 528MHz那么 PLL1 可以设置为 1056MHz寄存器CCM_CACRR的ARM_PODF位设置为 2 分频即可。同理如果要将主频设 置为 696MHz那么 PLL1 就可以设置为 696MHzCCM_CACRR的ARM_PODF设置为 1 分 频即可。接下来详细的看一下CCM_CACRR和CCM_ANALOG_PLL_ARMn这两个寄存器4、寄存器CCM_CACRR(CCM ARM Clock Root Register) (内核根时钟寄存器)结构如下ARM_PODF000 一分频001 二分频010 三分频011 四分频100 五分频101 六分频110 七分频111 八分频5、寄存器CCM_ANALOG_PLL_ARMn(ARM 锁相环控制寄存器)BYPASS_CLK_SRC0选择24MHz晶振作为时钟源ENABLE1使能0禁止DIV_SELECT此位设置 PLL1 的输出频率可设置范围为54~108可得出PLL1的范围648 - 1296MHz公式PLL1 CLK Fin * div_seclec/2.0Fin24MHz如果 PLL1 要输出 1056MHz 的话div_select 就要设置为 882.1.2 PLL1 时钟开关配置内核前boot rom默认配置主频为396MHz在修改内核时钟频率的时候需要先将内核时钟源改为其他的时钟源因为时钟频率突然的升高可能会导致内核工作状态死机等异常状态修改过程如下图所示1、pll1_sw_clk也就是 PLL1 的最终输出频率2、左边是一个选择器选择pll1_sw_clk的时钟源由寄存器CCM_CCSR的PLL1_SW_ CLK_SEL位决定pll1_sw_clk是选择pll1_main_clk还是step_clk。正常情况下应该选择pll1_main_clk但是如果要对pll1_main_clk(PLL1)的频率进行调整的话比如要设置PLL11056 MHz此时就要先将pll1_sw_clk切换到step_clk上。等pll1_main_clk调整完成以后再切换回来3、再下面也是一个选择器选择step_clk的时钟源由寄存器CCM_CCSR的STEP_SEL位来决定step_clk是选择osc_clk还是secondary_clk。一般选择osc_clk也就是24MHz的晶振4、寄存器CCM_CCSR(CCM Clock Switcher register)---时钟切换寄存器STEP_SEL作用选择step_clk的时钟源0 选择 osc_clk (24M)1 选择 secondary_clkPLL1_SW_CLK_SEL作用选择pll1_sw_clk的时钟源0选择pll1_main_clk1选择step_clk2.1.3 配置内核时钟示例代码/配置 ARM 时钟 CCM-CCSR ~(1 8); /选择 step_clk osc_clk 24MHz CCM-CCSR | (1 2); /选择 pll1_sw_clk step_clk 24MHz t CCM_ANALOG-PLL_ARM; t ~(3 14); /选择24MHz做为时钟源 t | (1 13); /使能时钟 t ~(0x7F 0); /先将低七位清零 t | (88 0); /DIV_SELECT 88 CCM_ANALOG-PLL_ARM t; CCM-CACRR | (1 0); /设置PLL1输出二分频 CCM-CCSR ~(1 2); /选择 pll1_sw_clk pll1_main_clk2.2 配置PLL2与PLL3的8个PFD设置好主频以后还需要设置好其他的 PLL 和 PFD 时钟PLL1 上一节已经设置了PLL2、PLL3 和 PLL7固定为528MHz、480MHz 和 480MHzPLL4~PLL6 都是针对特殊外设的用到的时候再设置。因此接下来重点就是设置 PLL2 和 PLL3 的各自 4 路 PFDNXP 推荐的这 8 路 PFD 频率如图所示这两个要通过寄存器CCM_ANALOG_PFD_528与CCM_ANALOG_PFD_480来设置2.2.1寄存器CCM_ANALOG_PFD_528其余位同理PLL2_PFD1~PLL2_PFD3 设置类似PFD0_FRACPLL2_PFD0 的分频数PLL2_PFD0 的计算公式为528*18/PFD0_FRAC范围此位可设置的范围为12~35如果 PLL2_PFD0 的频率要设置为 352MHz 的话PFD0_FRAC528* 18/35227。如果 PLL2_PFD0352 MHz 的话PFD0_FRAC27如果 PLL2_PFD1594MHz 的话PFD1_FRAC16如果 PLL2_P FD2396MHz 的话PFD2_FRAC24如果 PLL2_PFD3297MHz 的话PFD3_FRAC32PFD0_STABLE此位为只读位可以通过读取此位判断 PLL2_PFD0 是否稳定PFD0_CLKGATEPLL2_PFD0 输出使能位为 1 的时候关闭 PLL2_PFD0 的输出为 0 的时候使能输出2.2.2 寄存器CCM_ANALOG_PFD_480从图可以看出寄存器 CCM_ANALOG_PFD_480n 和 CCM_ANALOG_PFD_528n 的结构是一模一样的只是一个是 PLL2 的一个是 PLL3 的。寄存器位的含义也是一样的只是频率计算公式不同比如 PLL3_PFDX480*18/PFDX_FRAC(X0~3)如果 PLL3_PFD0720 MHz 的话PFD0_FRAC12如果 PLL3_PFD1540MHz 的话PFD1_FRAC16;如果 PLL3_P FD2508.2MHz 的话PFD2_FRAC17如果 PLL3_PFD3454.7MHz 的话PFD3_FRAC192.2.3 示例代码/配置 PLL2 的四路PFDPFD0 PFD1 PFD2 PFD3 t CCM_ANALOG-PFD_528; /配置PLL2的四路PFD输出指定频率时钟并且使能时钟 t ~((0x3F 0) | (0x3F 8) | (0x3F 16) | (0x3F 24)); t ~((1 7) | (1 15) | (1 23) | (1 31)); /启用分数分频器 t | ((27 0) | (16 8) | (24 16) | (32 24)); CCM_ANALOG-PFD_528 t; /配置 PLL3 的四路PFDPFD0 PFD1 PFD2 PFD3 t CCM_ANALOG-PFD_480; /配置PLL3的四路PFD输出指定频率时钟并且使能时钟 t ~((0x3F 0) | (0x3F 8) | (0x3F 16) | (0x3F 24)); t ~((1 7) | (1 15) | (1 23) | (1 31)); /启用分数分频器 t | ((12 0) | (16 8) | (17 16) | (19 24)); CCM_ANALOG-PFD_480 t;2.3 配置三个根时钟这一节配置三个根时钟分别是AHB_CLK_ROOT、PERCLK_CLK_ROOT、IPG_CLK_ROOT由时钟树得知很多外设如EPIT、I2C、ADC、WDOG等时钟都来自这三个根时钟故要对这三个根时钟进行配置IMX6ULL外设根时钟可设置范围如图所示又图可知AHB_CLK_ROOT最高可以设置132MHzIPG_CLK_ROOT和PERCLK_CLK_ROOT最高可以设置66MHz。那就将 AHB_CLK_ ROOT、IPG_CLK_ROOT 和 PERCLK_CLK_ROOT 分别设置为 132MHz、66MHz、66MHz。2.3.1 配置AHB_CLK_ROOT配置步骤第一步此选择器用来选择 pre_periph_clk 的时钟源可以选择PLL2、PLL2_PFD2、PLL2_PF D0 和 PLL2_PFD2/2。寄存器 CCM_CBCMR 的 PRE_PERIPH_CLK_SEL位决定选择哪一个默认选择 PLL2_PFD2因此 pre_periph_clkPLL2_PFD2396MHz寄存器 CCM_CBCMRPRE_PERIPH_CLK_SEL(19 - 18)作用pre_periph 时钟源选择00 选择 PLL2 --- 528MHz01 选择 PLL2_PFD2 --- 396MHz10 选择 PLL2_PFD0 --- 352MHz11 选择 PLL2_PFD2/2 --- 396/2MHz第二步由寄存器 CCM_CBCDR的PERIPH_CLK_SEL来选择IPG_PODF(9 - 8)IPG时钟分频00 一分频01 二分频10 三分频11 四分频AHB_PODFAHB 时钟分频0001分频001 2分频010 3分频------396 / 3 132MHz011 4分频100 5分频101 6分频110 7分频111 8分频PERIPH_CLK_SEL0 PLL2 (pll2_main_clk)1 derive clock from periph_clk2_clk clock source第三步设置3分频即可也是使用寄存器 CCM_CBCDR2.3.2 配置PERCLK_CLK_ROOT与IPG_CLK_ROOT注意这里要使用寄存器CBCDR[IPG_PODF]来设置二分频132/266才能得到想要的频率寄存器CCM_CSCMR1PERCLK_PODF(低5位)000000 divide by 1000001 divide by 2000010 divide by 3000011 divide by 4000100 divide by 5000101 divide by 6000110 divide by 7111111 divide by 64PERCLK_CLK_SEL(bit 6)0 :选择 ipg clk1 :选择 osc clk2.3.3 示例代码/配置三个根时钟 /AHB_CLK_ROOT t CCM-CBCMR; t ~(3 18); t | (1 18); /选择PFD2 CCM-CBCMR t; t CCM-CBCDR; t ~(1 25); /选择PLL2 t ~((7 10) | (3 8)); /三分频输出 t | (2 10); t | (1 8); /配置IPG_CLK_ROOT 132/2 66MHz CCM-CBCDR t; /PERCLK_CLK_ROOT t CCM-CSCMR1; t ~(1 6); /选择 IPG_CLK_ROOT配置PERCLK_CLK_ROOT IPG_CLK_ROOT t ~(0x3F 0); /选择一分频PERCLK_CLK_ROOT IPG_CLK_ROOT 66MHz CCM-CSCMR1 t;三. IMX6ULL配置与使能时钟完整代码示例代码#includeMCIMX6Y2.h #includeclock.h //打开所有时钟门 void enable_clocks(void) { CCM-CCGR0 0xFFFFFFFF; CCM-CCGR1 0xFFFFFFFF; CCM-CCGR2 0xFFFFFFFF; CCM-CCGR3 0xFFFFFFFF; CCM-CCGR4 0xFFFFFFFF; CCM-CCGR5 0xFFFFFFFF; CCM-CCGR6 0xFFFFFFFF; } //初始化时钟 void clock_init(void) { unsigned int t; //配置 ARM 时钟 CCM-CCSR ~(1 8); //选择 step_clk osc_clk 24MHz CCM-CCSR | (1 2); //选择 pll1_sw_clk step_clk 24MHz t CCM_ANALOG-PLL_ARM; t ~(3 14); //选择24MHz做为时钟源 t | (1 13); //使能时钟 t ~(0x7F 0); //先将低七位清零 t | (88 0); //DIV_SELECT 88 CCM_ANALOG-PLL_ARM t; CCM-CACRR | (1 0); //设置PLL1输出二分频 CCM-CCSR ~(1 2); //选择 pll1_sw_clk pll1_main_clk //配置 PLL2 的四路PFDPFD0 PFD1 PFD2 PFD3 t CCM_ANALOG-PFD_528; //配置PLL2的四路PFD输出指定频率时钟并且使能时钟 t ~((0x3F 0) | (0x3F 8) | (0x3F 16) | (0x3F 24)); t ~((1 7) | (1 15) | (1 23) | (1 31)); //启用分数分频器 t | ((27 0) | (16 8) | (24 16) | (32 24)); CCM_ANALOG-PFD_528 t; //配置 PLL3 的四路PFDPFD0 PFD1 PFD2 PFD3 t CCM_ANALOG-PFD_480; //配置PLL3的四路PFD输出指定频率时钟并且使能时钟 t ~((0x3F 0) | (0x3F 8) | (0x3F 16) | (0x3F 24)); t ~((1 7) | (1 15) | (1 23) | (1 31)); //启用分数分频器 t | ((12 0) | (16 8) | (17 16) | (19 24)); CCM_ANALOG-PFD_480 t; //配置三个根时钟 //AHB_CLK_ROOT t CCM-CBCMR; t ~(3 18); t | (1 18); //选择PFD2 CCM-CBCMR t; t CCM-CBCDR; t ~(1 25); //选择PLL2 t ~((7 10) | (3 8)); //三分频输出 t | (2 10); t | (1 8); //配置IPG_CLK_ROOT 132/2 66MHz CCM-CBCDR t; //PERCLK_CLK_ROOT t CCM-CSCMR1; t ~(1 6); //选择 IPG_CLK_ROOT配置PERCLK_CLK_ROOT IPG_CLK_ROOT t ~(0x3F 0); //选择一分频PERCLK_CLK_ROOT IPG_CLK_ROOT 66MHz CCM-CSCMR1 t; //使能时钟 enable_clocks(); }