一、源文件
1.1 程序目的/效果
在改变CPU频率之前,我们首先切换到其它时钟信号(示例中选择晶体振荡电路XTALOSC24M的输出),修改ARM_PLL设置并稳定在新的频率之后,再切换回ARM_PLL的输出时钟信号
在main函数中,我们首先初始化并点亮led灯,设置CPU频率到81MHZ(ARM_PLL输出为648MHZ,分频参数为8),亮灯和灭灯各5次;然后设置CPU频率为648MHZ(ARM_PLL输出为1296MHZ,分频参数为2),之后无限闪灯。我们可通过肉眼观测到led的闪烁频率明显变快。
1.2 文件链接
但是感觉到源文件较为臃肿,掺杂了很多不必要的代码,尽管为以后代码的复用提供了方便,但是不利于本章节的学习。所以接下里我会对各部分内容进行裁剪,以尽量使得最少的代码完成本节的内容。
二、CPU时钟频率切换代码简述
2.1 sel_pll1_sw_clk(0);
作用:将ARM_ROOT时钟切换至OSC
该函数如下
由于是时钟切换,所以我们查阅IMX6ULL芯片手册的18.5.1.5.1节Clock Switcher (648页)
该模块介绍:这个时钟切换器子模块接收PLL输出时钟和PLL旁路时钟
图18-4描述了三个切换器时钟的生成(下面我只截取我们用到的图片,其余详情查看手册)
图中还包含了负责频率变换的频率切换控制子模块
看图我们可以得知使用CCSR寄存器来负责控制切换器子模块,及多路复用器。
Address: 20C_4000h base + Ch offset = 20C_400Ch
第8位step_sel翻译:当更改ARM频率时,选择步进频率
注意:只有在它的输出不被使用时,这个复用器才可以被改变;换句话讲,ARM使用pll1的输出,并且step_clk没有被使用的时候,才可以更改这个复用器。(所以程序中才会先修改这个复用器,再选择使用step_sel)
因此,时钟切换函数思路如下:
需要pll1_sw_clk.设置为0
需要pll1_sw_clk.设置为1,需要step_sel设置为0
2.2 set_pll(ARM_PLL, 54);
作用:设置ARM_PLL: 24*54/2 = 648MHZ, ARM_ROOT: 648/8=81MHZ
函数(部分)截图如下
查阅芯片手册即可理解,该步骤将对锁相环的控制位与倍频参数一块复制给了寄存器
2.3 setup_arm_podf(8);
作用:ARM_ROOT的分频参数设置为8
函数如下:
这部分内容还需要了解下时钟树,查看芯片手册629页。
先看看时钟树的介绍
pll和pfd的默认频率值(MHz)在下面的时钟树图中显示。pll和pfd控制寄存器可以根据使用的SoC的速度等级重新编程,但不应超过该速度等级的最大设置
得知使用寄存器 CACRR的位[ARM_PODF]进行分频,我们现在跳转到这个寄存器
Address: 20C_4000h base + 10h offset = 20C_4010h
该寄存器的0-3位负责ARM根时钟的分频,根据我们的需要设置分频参数为8
2.4 sel_pll1_sw_clk(1);
作用:将ARM_ROOT切换回ARM_PLL,此时CPU工作频率为81MHZ
因为前面三步首先将时钟切换到osc_clk,然后对ARM_PLL进行设置,设置好参数后再将时钟切换回ARM_PLL。
三、CPU切换时钟频率(文字理解)(资料)
理解:首先查看芯片手册,寻找时钟树,查看相应寄存器,了解对应的芯片时钟体系,然后以“先倍频,再分频”的原则对CPU的频率进行更改,具体落实获取有不同,多看芯片手册总会解决。
为验证CPU频率的变化,本例使用忙等待的延时方式,控制LED灯闪烁--随着CPU频率的提升,延时时间变短,LED灯闪烁频率变快。
正常工作时,CPU使用锁相环电路ARM_PLL的输出信号作为时钟源。在改变CPU频率之前,我们首先切换到其它时钟信号(示例中选择晶体振荡电路XTALOSC24M的输出),修改ARM_PLL设置并稳定在新的频率之后,再切换回ARM_PLL的输出时钟信号。这里我们再次引用时钟切换电路(switcher)的部分原理图,如下所示:
改变CPU频率前,pll1_sw_clk时钟路径如图中路径1所示。我们首先将其切换至路径2,待ARM_PLL(PLL1)稳定输出后,再切换回路径1。
怎么控制时钟路径?修改上图中用黄色标出来的寄存器值即可。对应的控制函数为set_pll1_sw_clk(int sel_pll1),当参数sel_pll1值为0时,选择路径1;当参数sel_pll1值非0时,选择路径2。
切换完pll1_sw_clk时钟路径之后,我们就可以重新设置ARM_PLL的输出频率,相应的设置函数set_pll设置指定PLL的倍频参数并等待其输出频率稳定。为了简化函数接口,AUDIO_PLL和VIDEO_PLL的NUM(4)和DENOM(5)参数统一设置为0xF,而且不支持ENET_PLL(6)的设置,感兴趣的同学可以自己添加相关代码。
时钟信号pll1_sw_clk在成为arm_clk_root送往CPU之前,还要在根时钟生成电路(root generator)经过一次分频操作,其分频参数的设置函数为setup_arm_podf,位于文件clkroot.c中,
最后,为了方便比较led的闪烁频率,我们对led的接口函数稍作修改,增加led_toggle函数,led的状态改变一次(从亮到灭或从灭到亮),这里不再展示其代码。
在main函数中,我们首先初始化并点亮led灯,设置CPU频率到81MHZ(ARM_PLL输出为648MHZ,分频参数为8),亮灯和灭灯各5次;然后设置CPU频率为648MHZ(ARM_PLL输出为1296MHZ,分频参数为2),之后无限闪灯。我们可通过肉眼观测到led的闪烁频率明显变快。