上一节对于imx6ul的时钟源以及时钟树我们进行了讲解,使我们对于一个系统的时钟是如何产生的,既然已经对于了时钟的来源与生成有了一定的了解,那么就可以顺着这个思路对于开发板的时钟进行修改,这一节将开始具体的实验分析与操作

        在上一节分析的时钟树上的最上面,对应的PLL1的时钟输出就是设置ARM_CLK_ROOT,也就是ARM内核时钟,为ARM核心提供是时钟信号的根时钟源,我们先分析一下原理,在这里它假设PLL1时钟频率为966MHz,随着时钟路径往前走。
        将对PLL1进行分频,下方对应的寄存器是CCM_CACRR的ARM_PODF,此寄存器具体下方会讲解,这里简单解释为,此寄存器可进行1/2/4/8的分频,如果如图中选择2分频。则是996 / 2 =448MHz,顺着走后面有一个灰色的二分频此处并未进行二分频
        也就是按照图中例子给出的效果来分析,最后ARM内核时钟输出的时钟频率就应该是498MHz,这也对应的就是imx6ul的主频。
        

        博主在查阅了相关资料后,有解释原因,但是确实无法学识浅薄,无法理解,在下方我会放出原因,如果有读者能理解可以自行参考一下,博主这里得知无法分频就好,就不过多解释了
 

        在这里我们得知如果要设置主频,第一步要进行操作的是设置PLL1的时钟频率,那么继续顺着思路,分析一下如何设置PLL1的主频,PLL1的输出主频来源于时钟切换器,那么去找参考手册中的时钟切换器。

        下方就是PLL1时钟切换器对应的功能描述,24MHzOSC这里的OSC通常指的是振荡器,通常指的是一个能够产生24MHz频率的时钟信号振荡器。那么在这里就是前面的能够产生24MHz的振荡器晶振。
        首先从后面开始分析,在末尾PLL1_sw_clk是PLL1输出的最终频率,​图中有一个GLITCHLESS MUX叫做无毛刺多路选择器(Glitchless Clock Multiplexer),是一种特殊设计的多时钟源切换电路,简单来说就是现在时钟源与备用时钟源之间的无缝切换,可以确保CPU在时钟源切换过程中稳定运行。

        在这里为什么会设计到时钟切换呢,这里就需要引入一个概念时钟源与备用时钟源,对于系统时钟源进行修改为了确保系统的稳定性和可靠性,一般就会启动备用的时钟源,因为时钟源的修改可能会暂时影响系统的时钟信号,也就是出于对系统本身的稳定性和可靠性的考虑
        所以可以看到这里的时钟有两条线都可以输出到最末端pll1_sw_clk,第一条是pll1_main_clk,另外一条是step_clk,通过CCM_CCSR的PLL1_SW_CLK_SEL来对PLL1输出频率进行一个选择。对于一般正常情况下而言上面的pll1_sw_clk是主要的输出频率,所以一般也是对它进行调整。那么如前面所讲考虑到系统稳定性等缘故,必须需要一个备用时钟源来提供基本的时钟信号,那么就需要通过控制PLL1_SW_CLK_SEL,选择另外一条线step_clk,在配置完成pll1_main_clk便可以将其切换回来


        博主使用的imx6ul开发板的系统最高主频为528MHz,我们要发挥板子的最高性能也就是将他主频设置为这么多,因为如上图分析需要需要一个分频,我们翻阅与一下参考手册对于它的说明,翻译过来也就是说这个ARM PLL(也就是PLL1)的时钟输出频率范围为650MHz——1.3KMHz,那么我们的最后可以这么计算将PLL1的频率设置到1056MHz,然后通过设置2分频,即是1056 / 2 = 528MHz,就达到了我们想要的效果。所以在这里整个思路就是这么分析的,现在开始讲解寄存器,开始具体方案的实施

        为了节省文章内容,我们将之前点亮LED灯的闪烁实验直接复制到我们这一章节的实验文件下,那么我们还是先创建一个文件夹用来作为本章实验
        然后继续开始分析,首先我们需要先从PLL1开始设置,首要就是先选择从哪一条线上输出时钟频率,我们在手册中找到CCM_CCSR这个寄存器
        这个寄存器的第二位就是PLL1_SW_CLK_SEL,也就是可以选择输出哪条时钟频率的位,选择生成pll1_sw_clk的源,因为需要设置pll1_main_clk,所以这里就需要将时钟切换为step_clk,然后设置切换完成过后,我们还需要对step_clk进行时钟频率的配置,上图的24MHz晶振同样进入了step_clk,再观察这个寄存器可以看到此此寄存器的第九位就是对step_clk的配置,使用的是同一个寄存器,既然思路已经理清楚了,那我们就在代码中体现
        我们在刚开始初始化外设时钟的地方,首先先创建一个函数,用来设置内核时钟的初始化,这里有一个if的判断语句,作用即是先检测一下第二位是否为0,因为第二位为0便是主时钟(pll1_main_clk),设置为1就是备用时钟源,判断作用就在于,可以防止在不需要时重复进行相同的位操作。如果该位已经是1,说明备用时钟源已经被选择,其次就是在之后添加判断条件可以提高代码的可靠性、效率,并防止意外的重复操作或硬件状态的意外变化的一个习惯
        这个代码是怎么达到检测的效果的呢,首先将第三位向右移动两位到第一位,因为要寄存器中的位进行读取,必须要将其中的位移动到第一位来进行读取,在移动完过后,与(&)上一个0x1(0001),进行计算,位与操作 & 只保留 0x1 掩码对应位置上的位的值,其余位置上的位都被清零。例如
        相当于将其余位都清0,将我们刚刚移动到第一位的位进行判断,如果它本身为0那么输出的值便是0,也就是他目前是pll1_main_clk,达成if判断条件。反正如果它自身本身为1就是与上一个1过后还是为1,所以它自身就是step_clk,就不需要进行判断了,所以这个就是后面为什么需要与上一个0x1
        继续这段代码,既然如果我们if条件达成,说明目前目前仍然是主时钟源,那么就需要将他修改成备用时钟源,进入if括号那么首先就需要先对备用时钟源进行配置,在前面CCM_CCSR的第九位就是关于设置备用时钟源step_clk,翻译一下是,0是从OSC_CLK产生时钟频率 为1是从seconddary_clk产生时钟,很明显我们是要将其设置为1,从OSC产生24MHz的频率。
        
        括号中的第一句位运算代表的意思就是,将第8位清零其他位保持不变,计算的过程就不多讲解,然后第二句话也就是将第二位置1,也就是在完成了step_clk的配置过后,我们的下一步就是直接切换成这个备用时钟源,只需要将对应的CCM_CCSR寄存器设置为1便可,我们代码确实也是直接设置为了1,那么我们备用是时钟源的切换就完成了

        将时钟暂时切换为备用时钟源的目的,就是为了来配置PLL1的主时钟,pll1_main_clk,那么接下来自然就是开始配置此时钟,从ARM PLL(PLL1)的介绍中也能得到很多信息
        首要说明的它的输出频率由七位寄存器字段CCM_ANALOG_PLL_ARM[DIV_SELECT]来选择,下面是PLL1输出频率的计算公式,那么首先还是先去找到对应的寄存器
        公式中对应的DIV_SEL就是如图下寄存器中的对应的0到6位,我们要将最终主频设置1056MHz通过公式计算,Fref是外部晶振的24MHz,设DIV_SEL为X,1056 = 24 * X/2 解的X = 88那么也就是我们要将这6位中写入88
 

        在对于0-6位的描述中,可以设置的有效范围位54-108,如果没有设置那么默认最小有效值为54,此7位如果全部写为1可表示的值为127有效范围是这么来的
        在这里我们要对此寄存器完成两个位设置,第一个是13位,有一个Enable也就是使能该时钟,其次就是设置它的具体数值0-6位那么,在思路清晰后开始代码体现
        


        从代码中可以看到对CCM_ANALOG寄存器进行操作,位运算这里不过多讲解了,最后将第13位设置为了1,或上后面的位运算
        后面的位运算完成的操作是将88左移0位,结果是01011000,进行按位与操作,01011000与上01111111,结果就是01011000。其中虽然左移 0 位没有实际改变数值,但它可能是为了保持代码的结构一致性,便于以后修改或与其他需要移位的代码保持统一。用于确保最终的值只保留低 7 位但在更广泛的代码上下文中,它有助于防止错误和保持代码的通用性。这些看似多余但是还是养成对于写代码的良好习惯
        那么最后这两个位运算或上,通过按位或操作,将两个结果合并。这里按位或操作 0x2000 | 0x58 结果是 0x2058。这相当于在合并两个值时,将 0x58 的低 7 位与 0x2000 的第 13 位结合起来,位运算的详细步骤我就不解释了,然后我们的pll1_main_clk也就是PLL1的时钟频率也就配置完成了

        

        按照上面这张图我们已经完成了对PLL1的配置,也就是将其配置为了1056,既然要达到开发板528MHz的最高频率那么就需要进行一次分频,需要2分频,按照图中的提示我们去寻找分频的寄存器CCM_CACRR

        根据手册中寄存器描述,此寄存器可以的0到2位负责控制分频。一共控制1-8倍的分频,那么我们这里需要的是2分频,那么对应的就是001,接下来继续写代码

        因为是001,直接写入1就可以了

        在完成了pll1的pll1_main_clk所有配置过后,我们就可以将之前配置的备用时钟源给切换回来 
将前面控制是时钟源切换的寄存器,重新置为0就可以切换到pll1_main_clk,所以我们直接使用位运算将它置0,位运算还是不做过多的分析了

        关于这个系统时钟就已经全部配置完成了,只需要这么一个简单的函数,现在需要做的就是在头文件中申明一下这个函数,然后再在我们的主函数中初始化一下,就可以了最后记得再修改一下Makefile
        这个在头文件中引用一下

        然后再在主函数中使用初始化

        修改一下Makefile

        最后通过Makefile编译出.bin文件,然后再使用imxdownload文件将.bin文件烧写进去,具体的详细步骤,在之前的烧写程序那么就已经提过了,这里不过多赘述
        这个实验的实验效果是这么体现的,因为之前我们在设置delay延时函数的时候,是按照开发板上的默认主频396MHz,所以我们是按照这个时钟频率计算出来二点延时一秒钟,但是现在由于我们将主频修改到了开发板的极限,528MHz,所以这个delay可能原本是一秒钟的延时,现在就要变得更快一点
        那么使用之前的灯闪烁实验,就可以看出,同样是选择的delay(500),但是修改之后要比修改之前要快一点,这个肉眼观察可能需要一双好视力的眼睛,仔细看还是可以看出来的,那么我们修改imx6ul开发板的主频实验到这里就完成了,感受你的阅读与支持

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部