ARM(IMX6U)裸机主频和时钟

参考:Linux之ARM(IMX6U)裸机主频和时钟配置
作者:一只青木呀
发布时间: 2020-08-28 10:39:17
网址:https://blog.csdn.net/weixin_45309916/article/details/108237599

目录

  • 1、I.MX6U 时钟系统详解
    • 系统时钟来源(两个晶振)
    • 7路PLL时钟源(倍频而来)
    • 7路PLL的具体作用
    • 时钟树简介
  • 2、系统主频的配置(内核时钟设置)
    • 步骤①:设置分频系数
    • 步骤②:设置PLL1频率
    • 步骤③:暂时切换时钟源
      • 修改I.MX6U主频的步骤总结
  • 3、两个PLL对应的PFD时钟配置
    • 设置PLL2的4路PFD 频率
    • 设置PLL3的4路PFD频率
  • 4、其他外设的时钟配置(AHB、IPG和PERCLK 根时钟)
  • 5、实验程序编写(内核时钟主频为528MHz)
    • bsp_clk.c
    • bsp_clk.h
    • main.c
  • 6、编译下载验证

I.MX6U 系列标准的工作频率为 528MHz,有些型号甚至可以工作到 696MHz,但是 默认的工作频率为396MHz,这就造成了浪费了,本次 我们来配置主频时钟使其工作在528MHz,以及其他的外设时钟源都工作在NXP推荐的工作频率。

1、I.MX6U 时钟系统详解

I.MX6U 的系统主频为 528MHz,有些型号可以跑到 696MHz,但是默认情况下内部 boot rom 会将 I.MX6U 的主频设置为 396MHz。我们在使用 I.MX6U的时候肯定是要发挥它的最大性能,那么主频肯定要设置到 528MHz(其它型号可以设置更高,比如 696MHz),其它的外设时钟也要设置到 NXP 推荐的值。可参考NXP官方参考手册。

系统时钟来源(两个晶振)

打开 I.MX6U-ALPHA 开发板原理图,开发板时钟原理图如图:
在这里插入图片描述
在这里插入图片描述
I.MX6U-ALPHA 开发板的系统时钟来源于两部分: 32.768KHz 和24MHz 的晶振

  • 32.768KHz 晶振是 I.MX6U 的 RTC (实时时钟,不参与整个系统)时钟源

  • 24MHz 晶振是 I.MX6U 内核和其它外设的时钟源,看原理图是接在了6ull的T16、T17这两个IO上。

7路PLL时钟源(倍频而来)

I.MX6U 的外设有很多,不同的外设时钟源不同, NXP 将这些外设的时钟源进行了分组,一共有 7 组,这 7 组时钟源都是从 24MHz 晶振 PLL(倍频) 而来的,因此也叫做 7 组 PLL,这 7 组 PLL结构如图 :
在这里插入图片描述

在这里插入图片描述

7路PLL的具体作用

PLL作用
ARM_PLL(PLL1)此路 PLL 是供ARM 内核(主频)使用的, ARM 内核时钟就是由此 PLL生成的,此 PLL 通过编程的方式最高可倍频到 1.3GHz。
528_PLL(PLL2)此路 PLL 也叫做 System_PLL,此路 PLL 是固定的 22 倍频,不可编程修改。因此,此路 PLL 时钟=24MHz * 22 = 528MHz,这也是为什么此 PLL 叫做 528_PLL 的原因。此 PLL 分出了 4 路 PFD,分别为: PLL2_PFD0~PLL2_PFD3,这 4 路 PFD 和 528_PLL共同作为其它很多外设的根时钟源。通常 528_PLL 和这 4 路 PFD 是 I.MX6U 内部系统总线的时钟源,比如内处理逻辑单元、 DDR 接口、 NAND/NOR 接口等等。
USB1_PLL(PLL3)此路 PLL 主要用于 USBPHY,此PLL 也有四路 PFD,为:PLL3_PFD0~PLL3_PFD3, USB1_PLL 是固定的 20 倍频,因此 USB1_PLL=24MHz *20=480MHz。USB1_PLL虽然主要用于USB1PHY,但是其和四路PFD同样也可以作为其他外设的根时钟源。
USB2_PLL(PLL7,没有写错!就是 PLL7,虽然序号标为 4,但是实际是 PLL7)看名字就知道此路PLL是给USB2PHY使用的。同样的,此路PLL固定为20倍频,因此也是480MHz。
ENET_PLL(PLL6)此路 PLL 固定为 20+5/6 倍频,因此 ENET_PLL=24MHz * (20+5/6)= 500MHz。此路 PLL 用于生成网络所需的时钟,可以在此 PLL 的基础上生成 25/50/100/125MHz的网络时钟。
VIDEO_PLL(PLL5)此路 PLL 用于视频显示相关的外设,比如 LCD,此路 PLL 的倍频可以调整, PLL 的输出范围在 650MHz~1300MHz。此路 PLL 在最终输出的时候还可以进行分频,可选 1/2/4/8/16 分频。
AUDIO_PLL(PLL4)此路 PLL 用于音频相关的外设,此路 PLL 的倍频可以调整, PLL的输出范围同样也是 650MHz~1300MHz,此路 PLL 在最终输出的时候也可以进行分频,可选1/2/4 分频

时钟树简介

I.MX6U 的所有外设时钟源都是从这 7 路 PLL 和有些 PLL 的PFD 而来的,这些外设究竟是如何选择 PLL 或者 PFD 的?这个就要借助《IMX6ULL 参考手册》里面的时钟树了,在“Chapter 18 Clock Controller Module (CCM)”的 18.3 小节给出了 I.MX6U详细的时钟树图,如图:

在这里插入图片描述
在图中一共有三部分: CLOCK_SWITCHER、 CLOCK ROOT GENERATOR 和SYSTEM CLOCKS。其中左边的 CLOCK_SWITCHER就是那 7 路 PLL 和8 路 PFD,右边的 SYSTEM CLOCKS就是芯片外设中间的 CLOCK ROOT GENERATOR是最复杂的!这一部分就像“月老”一样, 给左边的CLOCK_SWITCHER和右边的SYSTEM CLOCKS进行牵线搭桥。外设时钟源是有多路可以选择的, CLOCK ROOT GENERATOR 就负责从 7 路PLL 和 8 路 PFD 中选择合适的时钟源给外设使用。

具体操作肯定是设置相应的寄存器,我们以ESAI 这个外设为例, ESAI 的时钟图如图:
在这里插入图片描述
在图中我们分为了 3 部分,这三部分如下:

①、此部分是时钟源选择器, ESAI 有 4 个可选的时钟源: PLL4、 PLL5、 PLL3_PFD2 和pll3_sw_clk 。 具 体 选 择 哪 一 路 作 为 ESAI 的 时 钟 源 是 由 寄 存 器 CCM->CSCMR2 的ESAI_CLK_SEL 位来决定的,用户可以自由配置,配置如图:
在这里插入图片描述

②、此部分是 ESAI 时钟的前级分频,分频值由寄存器 CCM_CS1CDR 的 ESAI_CLK_PRED来确定的,可设置 1~8 分频,假如现在 PLL4=650MHz,我们选择 PLL4 作为 ESAI 时钟,前级分频选择 2 分频,那么此时的时钟就是 650/2=325MHz。

③、此部分又是一个分频器,对②中输出的时钟进一步分频,分频值由寄存器CCM_CS1CDR 的 ESAI_CLK_PODF 来决定,可设置 1~8 分频。假如我们设置为 8 分频的话,经过此分频器以后的时钟就是 325/8=40.625MHz。因此最终进入到 ESAI 外设的时钟就是40.625MHz。

2、系统主频的配置(内核时钟设置)

I.MX6U 的时钟系统前面已经分析的差不多了,现在就可以开始设置相应的时钟频率了。先从主频开始,我们将 I.MX6U 的主频设置为 528MHz,根据时钟树可以看到ARM 内核时钟如图所示:
在这里插入图片描述
图中各部分详解如下:

①、内核时钟源来自于 PLL1,假如此时 PLL1 为 996MHz。
②、通过寄存器 CCM_CACRR 的 ARM_PODF 位对 PLL1 进行分频,可选择 1/2/4/8 分频,假如我们选择 2 分频,那么经过分频以后的时钟频率是 996/2=498MHz。
③、大家不要被此处的 2 分频给骗了,此处没有进行 2 分频(我就被这个 2 分频骗了好久,主频一直配置不正确!)。
④、经过第②步 2 分频以后的 498MHz 就是 ARM 的内核时钟,也就是 I.MX6U 的主频。

步骤①:设置分频系数

经过上面几步的分析可知,假如我们要设置内核主频为 528MHz,那么 PLL1 可以设置为1056MHz寄存器 CCM_CACRR 的 ARM_PODF 位设置为 2 分频即可。同理,如果要将主频设置为 696MHz,那么 PLL1 就可以设置为 696MHz, CCM_CACRR 的 ARM_PODF 设置为 1 分频即可(如果选2分频就超过PLL1的最大值了,手册上讲到PLL的范围如下所示)。
在这里插入图片描述

CCM_CACRR 寄存器结构如图所示:
在这里插入图片描述
寄存器 CCM_CACRR 只有 ARM_PODF 位,可以设置为 0~ 7,分别对应 1~8 分频。如果要设置为2分频的话CCM_CACCR就要设置为1。

步骤②:设置PLL1频率

PLL1 的频率可以通过寄存器CCM_ANALOG_PLL_ARMn 来设置,此寄存器结构如图所示:
在这里插入图片描述
在这里插入图片描述
在寄存器 CCM_ANALOG_PLL_ARMn 中重要的位如下:

功能
ENABLE时钟输出使能位,此位设置为 1 使能 PLL1 输出,如果设置为 0 的话就关闭 PLL1输出。
DIV_SELECT此位设置 PLL1 的输出频率,可设置范围为: 54~108, PLL1 CLK = Fin *div_seclec/2.0(手册上给的)), Fin=24MHz(晶振)。如果 PLL1 要输出 1056MHz 的话, div_select 就要设置为 88。

步骤③:暂时切换时钟源

在修改 PLL1 时钟频率的时候我们需要先将内核时钟源改为其他的时钟源(临时的时钟,类似给一个临时的心脏先用着), PLL1 可选择的时钟源如图所示:
在这里插入图片描述
①、 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,此寄存器结构如图所示:
在这里插入图片描述
寄存器 CCM_CCSR 我们只用到了 STEP_SEL、 PLL1_SW_CLK_SEL 这两个位,一个是用来选择 step_clk 时钟源的,一个是用来选择 pll1_sw_clk 时钟源的。

修改I.MX6U主频的步骤总结

到这里,修改 I.MX6U 主频的步骤就很清晰了,修改步骤如下:

①、 设置寄存器 CCSR 的 STEP_SEL 位,设置 step_clk 的时钟源为 24M 的晶振。
②、设置寄存器 CCSR 的 PLL1_SW_CLK_SEL 位,设置 pll1_sw_clk 的时钟源为step_clk=24MHz,通过这一步我们就将 I.MX6U的主频先设置为 24MHz,直接来自于外部的24M 晶振(临时的时钟先用着)。
③、设置寄存器 CCM_ANALOG_PLL_ARMn,将pll1_main_clk(PLL1)设置为 1056MHz。
④、设置寄存器 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。
【注意】:第⑤步骤要先于第④步进行,也就是先设置好分频系数,防止一上来接入1056MHZ出问题,因为系统主频最大就是528MHz!
课堂笔记:
在这里插入图片描述

3、两个PLL对应的PFD时钟配置

设置好主频以后我们还需要设置好其他的 PLL 和 PFD 时钟,PLL1 已经设置了,PLL2、 PLL3 和 PLL7 固定为 528MHz、 480MHz 和 480MHz, PLL4~PLL6 (音视频、LCD相关)都是针对特殊外设的,用到的时候再设置。

因此,接下来重点就是设置 PLL2 和 PLL3 的各自 4 路 PFD, NXP 推荐的这 8 路 PFD 频率如表所示:

PFDNXP推荐频率值
PLL2_PFD0352MHz
PLL2_PFD1594MHz
PLL2_PFD2400MHz(实际为 396MHz)
PLL2_PFD3297MHz
PLL3_PFD0720MHz
PLL3_PFD1540MHz
PLL3_PFD2508.2MHz
PLL3_PFD3454.7MHz

设置PLL2的4路PFD 频率

用到寄存器是:CCM_ANALOG_PFD_528n,寄存器结构如图所示:
在这里插入图片描述
从图可以看出,寄存器 CCM_ANALOG_PFD_528n 其实分为四组,分别对应PFD0~PFD3,每组 8 个 bit,我们就以 PFD0 为例,看一下如何设置 PLL2_PFD0 的频率。 PFD0对应的寄存器位如下:

寄存器位描述
PFD0_FRACPLL2_PFD0 的分频数, PLL2_PFD0 的计算公式为 528 * 18 / PFD0_FRAC,此为 可 设 置 的 范 围 为 12~35 。 如 果 PLL2_PFD0 的 频 率 要 设 置 为 352MHz 的 话PFD0_FRAC=528*18/352=27
PFD0_STABLE此位为只读位,可以通过读取此位判断 PLL2_PFD0 是否稳定。
PFD0_CLKGATEPLL2_PFD0 输出使能位,为 1 的时候关闭 PLL2_PFD0 的输出,为 0 的时候使能输出。

如果我们要设置 PLL2_PFD0 的频率为 352MHz 的话就需要设置 PFD0_FRAC 为 27,PFD0_CLKGATE 为 0 。 PLL2_PFD1~PLL2_PFD3 设 置 类 似 , 频 率 计 算 公 式 都 是528*18/PFDX_FRAC(X=1~3) , 因 此 PLL2_PFD1=594MHz 的 话 , PFD1_FRAC=16 ;PLL2_PFD2=400MHz 的话 PFD2_FRAC 不能整除,因此取最近的整数值,即 PFD2_FRAC=24,这样 PLL2_PFD2 实际为 396MHz; PLL2_PFD3=297MHz 的话, PFD3_FRAC=32。

设置PLL3的4路PFD频率

使用到的寄存器是CCM_ANALOG_PFD_480n,此寄存器结构如图所示:
在这里插入图片描述
从图可以看出,寄存器 CCM_ANALOG_PFD_480n 和 CCM_ANALOG_PFD_528n的结构是一模一样的,只是一个是 PLL2 的,一个是 PLL3 的。寄存器位的含义也是一样的,只是 频 率 计 算 公 式 不 同 , 比 如 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。

课堂笔记: 在这里插入图片描述

4、其他外设的时钟配置(AHB、IPG和PERCLK 根时钟)

在这里插入图片描述
7 路 PLL 和 8 路 PFD 设置完成以后最后还需要设置AHB_CLK_ROOT、IPG_CLK_ROOT和PERCLK_CLK_ROOT的时钟,因为它们控制了大量的外设。由上图分析可知,IPG_CLK_ROOT和PERCLK_CLK_ROOT都要用到AHB_CLK_ROOT,所以首先需要初始化AHB_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 。

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。图 16.1.2中虽然写的是默认 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 分频。

在上面的设置中用到了三个寄存器: CCM_CBCDR、 CCM_CBCMR 和 CCM_CSCMR1,我们依次来看一下这些寄存器, CCM_CBCDR 寄存器结构如图所示:
在这里插入图片描述
寄存器 CCM_CBCDR 各个位的含义如下:

含义
PERIPH_CLK2_PODFperiph2 时钟分频,可设置 0~7,分别对应 1~8 分频。
PERIPH2_CLK_SEL选择 peripheral2 的主时钟,如果为 0 的话选择 PLL2,如果为 1 的话选择 periph2_clk2_clk。修改此位会引起一次与 MMDC 的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定位表示。
PERIPH_CLK_SELperipheral 主时钟选择,如果为 0 的话选择 PLL2,如果为 1 的话选择 periph_clk2_clock。修改此位会引起一次与 MMDC 的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定位表示。
AXI_PODFaxi 时钟分频,可设置 0~7,分别对应 1~8 分频。
AHB_PODFahb 时钟分频,可设置 0~7,分别对应 1~8 分频。修改此位会引起一次与MMDC 的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定位表示。
IPG_PODFipg 时钟分频,可设置 0~3,分别对应 1~4 分频。
AXI_ALT_CLK_SELaxi_alt 时钟选择,为 0 的话选择 PLL2_PFD2,如果为 1 的话选择PLL3_PFD1。
AXI_CLK_SELaxi 时钟源选择,为 0 的话选择 periph_clk,为 1 的话选择 axi_alt 时钟。
FABRIC_MMDC_PODFfabric/mmdc 时钟分频设置,可设置 0~7,分别对应 1~8 分频。
PERIPH2_CLK2_PODFperiph2_clk2 的时钟分频,可设置 0~7,分别对应 1~8 分频。

接下来看一下寄存器 CCM_CBCMR,寄存器结构如下图所示:
在这里插入图片描述寄存器 CCM_CBCMR 各个位的含义如下:

含义
LCDIF1_PODFlcdif1 的时钟分频,可设置 0~7,分别对应 1~8 分频。
PRE_PERIPH2_CLK_SELpre_periph2 时钟源选择, 00 选择 PLL2, 01 选择 PLL2_PFD2,10 选择 PLL2_PFD0, 11 选择 PLL4。
PERIPH2_CLK2_SELperiph2_clk2 时钟源选择为 0 的时候选择 pll3_sw_clk,为 1 的时候选择 OSC。
PRE_PERIPH_CLK_SELpre_periph 时钟源选择, 00 选择 PLL2, 01 选择 PLL2_PFD2, 10 选择 PLL2_PFD0, 11 选择 PLL2_PFD2/2。
PERIPH_CLK2_SELperipheral_clk2 时钟源选择, 00 选择 pll3_sw_clk, 01 选择 osc_clk,10 选择 pll2_bypass_clk。

最后看一下寄存器 CCM_CSCMR1,寄存器结构如下图所示:
在这里插入图片描述

此寄存器主要用于外设时钟源的选择,比如 QSPI1、 ACLK、 GPMI、 BCH 等外设,我们重点看一下下面两个位:

描述
PERCLK_CK_SELperclk 时钟源选择,为 0 的话选择 ipg clk,为 1 的话选择 osc clk。
PERCLK_PODFperclk 的时钟分频,可设置 0~7,分别对应 1~8 分频。

在修改如下时钟选择器或者分频器的时候会引起与 MMDC 的握手发生:
①、 mmdc_podf
②、 periph_clk_sel
③、 periph2_clk_sel
④、 arm_podf
⑤、 ahb_podf

发生握手信号以后需要等待握手完成,寄存器 CCM_CDHIPR 中保存着握手信号是否完成,如果相应的位为 1 的话就表示握手没有完成,如果为 0 的话就表示握手完成,很简单,这里就不详细的列举寄存器 CCM_CDHIPR 中的各个位了。

另外在修改 arm_podf 和 ahb_podf 的时候需要先关闭其时钟输出,等修改完成以后再打开,否则的话可能会出现在修改完成以后没有时钟输出的问题。本教程需要修改寄存器CCM_CBCDR 的 AHB_PODF 位来设置 AHB_ROOT_CLK 的时钟,所以在修改之前必须先关闭AHB_ROOT_CLK 的输出。但是笔者没有找到相应的寄存器,因此目前没法关闭,那也就没法设置 AHB_PODF 了。不过 AHB_PODF 内部 boot rom 设置为了 3 分频,如果 pre_periph_clk 的时钟源选择 PLL2_PFD2 的话, AHB_ROOT_CLK 也是 396MHz/3=132MHz。

课堂笔记:
在这里插入图片描述

在这里插入图片描述

5、实验程序编写(内核时钟主频为528MHz)

我们在上一次实验的基础上(ARM(MX6U)裸机按键输入实验(GPIO的输出与输入))进行修改.

bsp_clk.c

#include "bsp_clk.h"/*使能所有外设时钟*/
void clk_enable(void)
{CCM->CCGR0 =0xFFFFFFFF;CCM->CCGR1 =0xFFFFFFFF;CCM->CCGR2 =0xFFFFFFFF;CCM->CCGR3 =0xFFFFFFFF;CCM->CCGR4 =0xFFFFFFFF;CCM->CCGR5 =0xFFFFFFFF;CCM->CCGR6 =0xFFFFFFFF;}
/** @description : 初始化系统时钟 528Mhz,并且设置 PLL2 和 PLL3 各个* PFD 时钟,所有的时钟频率均按照 I.MX6U 官方手册推荐的值.* @param : 无* @return : 无*/
void imx6u_clkinit(void)
{/* 1、初始化 ARM 内核时钟(主频)为 528MHz *//* 1.1、判断当前内部bootroom使用哪个时钟源启动的,正常情况下是由 pll1_sw_clk 驱动的,而* pll1_sw_clk 有两个来源: pll1_main_clk 和 step_clk, 如果要* 让 I.MX6ULL 跑到 528M, 那必须选择 pll1_main_clk 作为 pll1 的时钟* 源。 如果我们要修改 pll1_main_clk 时钟的话就必须先将 pll1_sw_clk 从* pll1_main_clk 切换到 step_clk,当修改完以后再将 pll1_sw_clk 切换* 回 pll1_main_cl, step_clk 等于 24MHz。*/unsigned int reg = 0;if((((CCM->CCSR)>>2) & 0x1) ==0)//内部bootroom使用的时钟是否是pll1_main_clk{CCM->CCSR &= ~(1 << 8); /* 配置 step_clk 时钟源为 24MHz OSC */CCM->CCSR |= (1 << 2);  /* 配置 pll1_sw_clk 时钟源为 step_clk 24MHz */}/* 1.2、设置 pll1_main_clk 为 1056MHz,也就是 528*2=1056MHZ,* 因为 pll1_sw_clk 进 ARM 内核的时候会被二分频!* 配置 CCM_ANALOG->PLL_ARM 寄存器* bit13: 1 使能时钟输出* bit[6:0]: 88, 由公式: Fout = Fin * div_select / 2.0,* 1056=24*div_select/2.0, 得出: div_select=88。*///                     13位使能   div_select bit0~bit6设置为88CCM_ANALOG->PLL_ARM = (1 << 13) | ((88 << 0) & 0X7F);CCM->CCSR &= ~(1 << 2);   /* 将 pll_sw_clk 时钟切换回 pll1_main_clk */CCM->CACRR = 1;  // 设置2分频  ARM 内核时钟为 pll1_sw_clk/2=1056/2=528Mhz  视频里这一步放到前面,分频好了再切换/* 2、设置 PLL2(SYS PLL)4路 PFD */reg = CCM_ANALOG->PFD_528;reg &=  ~(0x3f3f3f3f);      /* 清除原来的设置 用16进制计算器计算就行*/reg |= (32<<24);            /* PLL2_PFD3=528*18/32=297Mhz */reg |= (24<<16);            /* PLL2_PFD2=528*18/24=396Mhz */reg |= (16<<8);             /* PLL2_PFD1=528*18/16=594Mhz */reg |= (27<<0);             /* PLL2_PFD0=528*18/27=352Mhz */CCM_ANALOG->PFD_528 = reg;  /* 设置 PLL2_PFD0~3 *//* 3、设置 PLL3(USB1)4路 PFD */reg =0;                         /* 清零reg */reg = CCM_ANALOG->PFD_480;      /* 清除原来的设置 */reg &= ~(0x3f3f3f3f);           reg |=  (19<<24);               /* PLL3_PFD3=480*18/19=454.74Mhz */reg |=  (17<<16);               /* PLL3_PFD2=480*18/17=508.24Mhz */reg |=  (16<<8);                /* PLL3_PFD1=480*18/16=540Mhz */reg |=  (12<<0);                /* PLL3_PFD0=480*18/12=720Mhz */CCM_ANALOG->PFD_480 = reg;      /* 设置 PLL3_PFD0~3 *//* 4、设置 AHB 时钟为最大值  132Mhz */CCM->CBCMR &= ~(3<<18);         /* 清除设置*/CCM->CBCMR |= (1<<18);          /* pre_periph_clk=PLL2_PFD2=396MHz  后面3分频正好就是132MHz*/     CCM->CBCDR &= ~(1<<25);         /* periph_clk=pre_periph_clk=396MHz */while(CCM->CDHIPR & (1 << 5));  /* 等待握手完成 (手册上要求的步骤)*//* 修改 AHB_PODF 位的时候需要先禁止 AHB_CLK_ROOT 的输出,但是* 我没有找到关闭 AHB_CLK_ROOT 输出的的寄存器,所以就没法设置。* 下面设置 AHB_PODF 的代码仅供学习参考不能直接拿来使用!!* 内部 boot rom 将 AHB_PODF 设置为了 3 分频,即使我们不设置 AHB_PODF,* AHB_ROOT_CLK 也依旧等于 396/3=132Mhz。*/
#if 0/* 要先关闭 AHB_ROOT_CLK 输出,否则时钟设置会出错 */CCM->CBCDR &= ~(7 << 10);       /* CBCDR 的 AHB_PODF 清零 */CCM->CBCDR |= (2 << 10);        /* AHB_PODF 3 分频, AHB_CLK_ROOT=132MHz */while(CCM->CDHIPR & (1 << 5));  /* 等待握手完成 */
#endif/* 5、设置 IPG_CLK_ROOT成最大值  66Mhz */CCM->CBCDR &= ~(3<<8);       /* CBCDR 的 IPG_PODF 清零 */CCM->CBCDR |= (1<<8);        /* IPG_PODF 2 分频, IPG_CLK_ROOT=66MHz *//* 6、设置 PERCLK_CLK_ROOT 时钟 */CCM->CSCMR1 &= ~(1<<6);         /* PERCLK_CLK_ROOT 时钟源为 IPG */CCM->CSCMR1 &= ~(0x3f << 0);      /* 1分频 */}

bsp_clk.c 中一共有两个函数: clk_enable 和 imx6u_clkinit

  • clk_enable 就是使能 I.MX6U 的所有外设时钟
  • 函数 imx6u_clkinit 先设置系统主频为 528MHz,然后根据我们分析的 I.MX6U 时钟系统来设置 8 路 PFD,最后设置 AHB、 IPG 和 PERCLK 的时钟频率。

bsp_clk.h

#ifndef __BSP_CLK_H
#define __BSP_CLK_H#include "imx6ul.h"void clk_enable(void);//使能外设时钟
void imx6u_clkinit(void);//初始化时钟#endif // !__BSP_CLK_H

在 bsp_clk.h 文件中添加函数 imx6u_clkinit 的声明

main.c

修改 main.c 文件,在 main 函数里面调用 imx6u_clkinit 来初始化时钟,代码如下:


#include "main.h"int main() 
{int i=0;int keyvalue=0;   unsigned char led_status= OFF;unsigned char beep_status= OFF;imx6u_clkinit(); /* 初始化系统时钟 */   clk_enable();  //使能外设时钟led_init(); //初始化LEDinit_beep();//初始化蜂鸣器key_init(); //初始化keywhile(1){keyvalue = key_get_value();if(keyvalue){switch (keyvalue){case KEY_VALUE:beep_status=!beep_status;beep_switch(beep_status);break;default:break;}}i++;if(i == 50){i=0;led_status=!led_status;led_switch(LED0,led_status);}delay(10);}return 0;
}

6、编译下载验证

具体所有代码在GitHub:裸机主频时钟配置

使用 Make 命令编译代码,编译成功以后使用软件 imxdownload 将编译完成的 clk.bin 文件下载到 SD 卡中,命令如下:

chmod 777 imxdownload 				//给予 imxdownload 可执行权限,一次即可
./imxdownload clk.bin /dev/sdd 		//烧写到 SD 卡中

烧写成功以后将 SD 卡插到开发板的 SD 卡槽中,然后复位开发板。本试验效果其实和试验“7_key”一样,但是 LED 灯的闪烁频率相比试验“7_key”要快一点。因为试验“7_key”的主频是 396MHz,而本试验的主频被配置成了 528MHz,因此代码执行速度会变快,所以延时函数的运行就会加快。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265442.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关联矩阵古林法的matlab代码,[转载][原创]灰色关联分析及Matlab程序实现

灰色系统理论由我国著名学者邓聚龙教授于1982提出。灰色关联分析是灰色系统理论的一个分支&#xff0c;应用灰色关联分析方法对受多种因素影响的事物和现象从整体观念出发进行综合评价是一个被广为接受的方法。一、灰色关联分析法的建模过程灰色关联分析法的基本思想是根据各比…

C语言排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)

参考&#xff1a;C语言五大排序&#xff08;桶排序&#xff0c;冒泡排序&#xff0c;选择排序&#xff0c;插入排序&#xff0c;快速排序&#xff09;动态演示 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-09-09 20:18:43 网址&#xff1a;https://blog.csdn.net/we…

FIFO分枝_限界算法

问题&#xff1a; 检索4-皇后问题的状态空间树如下图的基本过程。&#xff08;4-皇后问题解空间的树结构&#xff0c;结点按深度优先检索编号&#xff09; 如果按序扩展这些结点&#xff0c;则下一个E-结点就是结点2。扩展结点2后生成结点3&#xff0c;8和13。利用限界函数(同行…

智能家居APP使用指南

参考&#xff1a;智能家居APP使用指南 作者&#xff1a;图触靓 发布时间&#xff1a; 2021-04-14 14:11:40 网址&#xff1a;https://blog.csdn.net/bhbhhyg/article/details/115694774 目录一、如何修改IP&#xff0c;端口号&#xff0c;以及发送的指令二、如何增加或者删除一…

python zlib字符串压缩

2019独角兽企业重金招聘Python工程师标准>>> 在做网络程序时,可以对字符串进行压缩来节省带宽 项目中用到 {"compress": <压缩标记>, "result":[[设备类型.设备ID, 设备名称, 单位ID, 设备功能], ...]} 只做了简单的压缩解压缩,也没crc3…

linux做一个客户端与WemosD1作为服务器的无线通信(局域网通信)

参考&#xff1a;linux做一个客户端与WemosD1作为服务器的无线通信&#xff08;局域网通信&#xff09; 作者&#xff1a;枕上 发布时间&#xff1a;2021-07-19 23:33:44 网址&#xff1a;https://blog.csdn.net/jinchi_boke/article/details/118916896?utm_sourceapp&app…

C语言学习书籍推荐《C语言程序设计 现代方法(第2版)》下载

下载地址&#xff1a;点我 C语言仍然是计算机领域的通用语言之一&#xff0c;但现在的C语言已经和当初的时候大不相同了。本书主要的一个目的就是通过一种“现代方法”来介绍C语言&#xff0c;书中强调标准C&#xff0c;强调软件工程&#xff0c;不再强调“手工优化”。这一版中…

wemosD1_WIFI模块 与 arduino

参考&#xff1a;wemosD1_WIFI模块 与 arduino 作者&#xff1a;枕上 发布时间&#xff1a;2021-07-19 21:49:55 网址&#xff1a;https://blog.csdn.net/jinchi_boke/article/details/118915142 目录作为设备接入wifi&#xff08;STA模式&#xff09;架设Wemos为ftp服务器ardu…

本机在合成图片经常提示内存不足

转载于:https://www.cnblogs.com/niyl/p/9988614.html

tp5 php7 报500,记一次TP单元测试报500错误的问题

记一次TP单元测试报500错误的问题一直听说好的单元测试能提高代码质量&#xff0c;昨天终于在下定决心弄懂单元测试&#xff0c;但第一步就把我干趴下了&#xff0c;我的问题在下面开始都没有什么问题&#xff0c;tp5单元测试的手册就那一点&#xff0c;通过看云上一位仁兄写的…

H3C配置

H3C交换机配置 1.查看设备版本,确定是否需要升级 <H3C>dis version 2.vlan及接口配置 注&#xff1a;正式配置前可以查看下现有的VLAN。命令如下 <H3C>dis vlan <H3C>sys                          //进入系统视图模式 [H3C]vlan …

创建自己的共用js库

直至昨晚为止&#xff0c;学习了一个多月的MVC与jQuery&#xff0c;从所做的练习中&#xff0c;发觉jQuery的代码也有跟C#语言一样可以重构&#xff0c;多页面有相同使用的方法函数&#xff0c;均可以放置于一个单独立的js文件或是自定义的js库中。在使用时&#xff0c;引用此库…

视频专辑:JAVA语言入门视频教程

为什么80%的码农都做不了架构师&#xff1f;>>> 专辑&#xff1a;JAVA语言入门视频教程 简介:该视频专辑是java的入门教程&#xff0c;适合初学者学习java&#xff0c;讲的也非常容易懂&#xff0c;希望能给想学习java的朋友一些帮助。 1 JAVASE 01 简介 2013-10…

视频专辑:Servlet视频教程

为什么80%的码农都做不了架构师&#xff1f;>>> 专辑&#xff1a;Servlet视频教程 简介:郭宏志 Servlet视频教程 1 郭宏志 Servlet 01 WEB工程结构 2013-10-26 00:32 | 播放(9) | 评论(0) | 时长:28:39 2 郭宏志 Servlet 02 Servlet简介 2013-10-26 00:31 …

基于wemos D1的无线遥控灯(433m无线模块)

参考&#xff1a;基于wemos D1的无线遥控灯(433m无线模块) 作者&#xff1a;一只小阿大:) 发布时间&#xff1a; 2021-04-16 09:25:53 网址&#xff1a;https://blog.csdn.net/qq_44610809/article/details/115747714 项目软硬件平台及开发环境 1.硬件平台 开发板&#xff1a…

Linux实战教学笔记37:企业级Nginx Web服务优化实战(上)

一&#xff0c;Nginx基本安全优化 1.1 调整参数隐藏Nginx软件版本号信息 一般来说&#xff0c;软件的漏洞都和版本有关&#xff0c;这个很像汽车的缺陷&#xff0c;同一批次的要有问题就都有问题&#xff0c;别的批次可能就都是好的。因此&#xff0c;我们应尽量隐藏或消除Web服…

探索云计算、大数据的特色化应用之路

云计算与大数据是当前最热门的两个话题&#xff0c;除了技术上的相关性以外&#xff0c;两者现在都面临同一个问题&#xff0c;就是如何更快更好地落地&#xff0c;也就是将云计算、大数据所代表的新技术、新业务模式与行业用户的实际需求紧密结合起来&#xff0c;驱动企业业务…

树莓派摄像头使用Motion监测人物动作

更多干货推荐可以去牛客网看看&#xff0c;他们现在的IT题库内容很丰富&#xff0c;属于国内做的很好的了&#xff0c;而且是课程刷题面经求职讨论区分享&#xff0c;一站式求职学习网站&#xff0c;最最最重要的里面的资源全部免费&#xff01;&#xff01;&#xff01;点击进…

ARM(IMX6U)ARM Cortex-A7中断系统(GPIO按键中断驱动蜂鸣器)

参考&#xff1a;Linux之ARM Cortex-A7 中断系统详解 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-09-16 16:07:22 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108290225 目录1、中断是什么2、回顾STM32中断系统2.1、中断向量表(对应的…

测试——设计思维之获取反馈

获取用户反馈 为什么要测试&#xff1f; 尽早的从用户&#xff0c;干系人&#xff0c;专家那边获得反馈&#xff0c;能够迭代改善通过测试能够知道我们的主意设想的强项和弱势早失败如何测试&#xff1f; 让原型自己说话不要为自己的想法狡辩&#xff0c;原型是给用户&#xff…