系列文章目录
一、IMX6LL裸机点亮一颗LED
二、移植IMX6ULL_SDK点亮LED
三、IMX6ULL BSP工程管理
四、IMX6ULL按键输入
前言
本章学习IMX6U时钟和主频配置
一、工作频率
我们没有配置过时钟和主频,默认情况下IMX6UL内部的boot rom 会将工作频率设置为396Mhz,但I.MX6U标准的工作频率为528Mhz
二、系统时钟来源
其中32.768Khz是RTC时钟源
24Mhz是内核和其他外设的时钟源
三、7路PLL时钟源
不同外设时钟源不同,NXP将这些外设分为7组,这7组时钟源都来自24Mhz的倍频或分频。
1、ARM_PLL(PLL1):提供ARM内核使用
2、528_PLL(PLL2):System PLL 固定22倍频,不可编程 PLL=2422 = 528Mhz 分出4路PFD PLL2_PDF0-PLL2_PDF3
3、USB1_PLL(PLL3):用于USBPHY 固定20倍频 PLL=2420 = 480Mhz 分出4路PFD PLL3_PDF0-PLL3_PDF3
4、USB2_PLL(PLL7):用于USBPHY2 固定20倍频 PLL=2420 = 480Mhz
5、ENET_PLL(PLL6):用于生成网络时钟 固定20+5/6倍频 PLL = 24(20+5/6)=500Mhz
6、VIDEO_PLL(PLL5):用于显示相关的外设 PLL倍频可调整 输出范围650Mhz~1300Mhz 还可分频 1/2/4/8/16
7、AUDIO_PLL(PLL4):用于音频相关外设 PLL倍频可调整 输出范围650Mhz~1300Mhz 还可分频 1/2/4
四、时钟树简介
图中一共分为三部分
1、CLOCK SWITCHER:时钟切换器 7路PLL 8路PFD
2、CLOCK ROOT GENERATOR:时钟根发生器 给外设选择合适的时钟源
3、SYSTEM CLOCKS:系统时钟 外设时钟
五、内核时钟配置
1、我们先将I.MX6U主频设置为528Mhz
从图中可以看到,内核时钟由PLL1提供,通过CACRR的ARM_PODF位设置分频
查找手册,PLL1时钟频率,通过设置CCM_ANALOG_PLL_ARM的DIV_SELECT位,用24Mhz倍频得到
例:我想让PLL1输出1056Mhz 那么根据图中公式 1056 = 24 * DIV_SEL/2 DIV_SEL=88 DIV_SELECT位设置为88
图中pll_sw_clk就是PLL1最终输出的频率,CCSR:pll1_sw_clk_sel位为选择器,选择PLL1时钟源为pll1_main_clk还是step_clk,ps:当我们需要修改PLL1频率时,需要先切换到step_clk,修改完成后,在切换回pll1_main_clk才能生效。
六、PDF时钟设置
主频设置完成还需要设置其他PLL和PFD时钟,这里使用NXP官方推荐值
这里先设置PLL2的4路PFD,查找手册。
图中可以看出,PLL2和PLL3的4路PFD是通过设置CCM_ANALOG_PFD_480n和CCM_ANALOG_PFD_528n这两个寄存器的
我们现在设置PLL2_PFD0这一路的频率
PFD0_FRAC:分频数 范围12~35 假如我们要设置这一路频率为352Mhz,根据上面公式,352=528*18/PFD0_FRAC , PFD0_FRAC= 27 ,这个位就要设置为27,那么这一路频率就为352Mhz
PFD0_STABLE:此位为只读位,可以通过读取此位判断PLL2_PFD0是否稳定
PFD0_CLKGATE: PLL2_PFD0 输出使能位,为 1 的时候关闭 PLL2_PFD0 的输出,为 0 的
时候使能输出。
PLL3_PFD4路时钟配置类似,这里不再总结
七、AHB、IPG、PERCLK根时钟设置
配置范围如下
可以将这三个根时钟配置为最大,具体步骤不在总结,跟上面类似,参考参考手册中的时钟树,配置寄存器即可。
八、代码
void imx6u_clkinit(void)
{
unsigned int reg = 0;
// ARM
if ((((CCM->CCSR) >> 2) & 0x1 ) == 0)
{
/* code */
CCM->CCSR &= ~(1 << 8); //配置step_clk为24Mhz
CCM->CCSR |= (1 << 2); //配置pll1_sw_clk时钟源为step_clk
}
CCM_ANALOG->PLL_ARM = (1 << 13) | ((88 << 0) & 0x7F); //使能时钟输出 并 配置PLL1为1056Mhz 1056 = 24*div/2
CCM->CCSR &=~(1 << 2); //时钟切换回pll_main_clk
CCM->CACRR = 1;
//PLL2
reg = CCM_ANALOG->PFD_528;
reg &=~(0x3F3F3F3F);
reg |= 32 << 24;
reg |= 24 << 16;
reg |= 16 << 8;
reg |= 27 << 0;
CCM_ANALOG->PFD_528 = reg;
//PLL3
reg = CCM_ANALOG->PFD_480;
reg &=~(0x3F3F3F3F);
reg |= 19 << 24;
reg |= 17 << 16;
reg |= 16 << 8;
reg |= 12 << 0;
CCM_ANALOG->PFD_480 = reg;
//AHB
CCM->CBCMR &=~ (3 << 18);
CCM->CBCMR |= (1 << 18);
CCM->CBCDR &=~(1 << 25);
while (CCM->CDHIPR & (1 << 5)); //等握手完成
//IPG
CCM->CBCDR &=~ (3 << 8);
CCM->CBCDR |= (1 << 8);
//PERCLK
CCM->CSCMR1 &=~ (1 << 6);
CCM->CSCMR1 |= (7 << 0);
}