完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
ARM裸机开发:主频与时钟
本章了解一下 IMX 的系统时钟主频配置原理 一、时钟系统 1.1 外部时钟电路 开发板时钟电路 IMX 的时钟电路和 STM32 没有多大区别,一个 24M 的晶振作为系统内核和外设的时钟电路,另外一个 32.768K 的晶振电路作为系统 RTC 时钟电路 1.2 7路PLL时钟源 NXP 将外设的时钟源进行了分组, 一共有 7 组,这 7 组时钟源都是从 24MHz 晶振 PLL 而来的,因此也叫做 7 组 PLL时钟源,7组时钟源结构如下: 图上7路 PLL 功能如下: [tr]PLL功能[/tr]
先看一张时钟树劝退图: 我们在里面可以看到两部分内容:左边的 CLOCK SWITCHER (PLL 时钟源)和右边的 CLOCK ROOT GENERATOR (时钟生成树)、SYSTEM CLOCKS (外设时钟);左边部分就是上面分析的 PLL 时钟源,CLOCK ROOT GENERATOR 则是对时钟源进行进一步处理,分频到合适的值给外设时钟使用,其中主要的部分就是 CLOCK ROOT GENERATOR 这部分电路,这部分电路主要用到以下几个逻辑电路:
我们通过配置时钟选择器和分频器,使PLL时钟源和外设时钟关联起来,达到可以正常使用的功能 二、时钟配置 时钟配置主要分为三个部分的时钟配置:
先看一下时钟源到内核时钟的时钟路线: 其中 PLL1 经过分频器1和2后输出到ARM内核时钟上,但注意,其中灰色的那个分频器并没有作用,所以只要配置第一个就行,如我们要是需要498M的主频,只需要将时钟源配置为996M,然后配置分频器为2分频,这样出来的就是498M的主频时钟,所以我们主频时钟配置需要配置两个寄存器
该寄存器以及 ARM_PODF 位与分频的对应关系如下: ARM_PODF 位,可以设置为 0~7,分别对应 1~8 分频,要设置 2分频就是给 001就行 2.1.2 CCM_ANALOG_PLL_ARMn 寄存器 **ENABLE :**用于使能时钟输出 DIV_SELECT: 此位设置 PLL1 的输出频率,可设置范围为:54~108,PLL1 CLK = Fin * div_seclec/2.0,因为Fin=24MHz,所以如果 PLL1 要输出 1056MHz 的话,div_select 就要设置为 88 注意!我们在配置时钟频率时必须先切换时钟源为其他时钟源,不然会出问题,先看一下内核时钟源有哪些: 看图中我们有 2、3 两个时钟选择器来控制时钟源的选择,其中选择器2是由寄存器 CCM_CCSR 的 PLL1_SW_CLK_SEL 位决定 pll1_sw_clk 是选择 pll1_main_clk 还是 step_clk;选择器3是由寄存器 CCM_CCSR 的 STEP_SEL 位 来决定 step_clk 是选择 osc_clk 还是secondary_clk;CCM_CCSR 寄存器如下: 所以综合上面,修改主频步骤如下:
设置好主频以后我们还需要设置好其他的 PLL 和 PFD 时钟,PLL2、PLL3 和 PLL7 固定为 528MHz、480MHz 和 480MHz,PLL4~PLL6 都是针对特殊外设 的,用到的时候再设置。因此,接下来重点就是设置 PLL2 和 PLL3 的各自 4 路 PFD,NXP 推 荐的这 8 路 PFD 频率如表: 设置 PLL2 的 4 路 PFD 频率,用到寄存器是 CCM_ANALOG_PFD_528n,寄存器结构如下: PFD0_FRAC: PLL2_PFD0 的分频数,PLL2_PFD0 的计算公式为 528 * 18 / PFD0_FRAC,可设置的范围为 12~35 。 如 果 PLL2_PFD0 的频率要设置为 352MHz 的 话 PFD0_FRAC=528*18/352=27。 PFD0_STABLE: 此位为只读位,可以通过读取此位判断 PLL2_PFD0 是否稳定。 PFD0_CLKGATE: PLL2_PFD0 输出使能位,为 1 的时候关闭 PLL2_PFD0 的输出,为 0 的时候使能输出 设置 PLL3_PFD0~PLL3_PFD3 这 4 路 PFD 的频率,使用到的寄存器是 CCM_ANALOG_PFD_480n,此寄存器结构如下: PFD0_FRAC: PLL3_PFD0 的分频数,PLL3_PFD0 的计算公式为 480 * 18 / PFD0_FRAC PFD0_STABLE: 此位为只读位,可以通过读取此位判断 PLL3_PFD0 是否稳定。 PFD0_CLKGATE: PLL3_PFD0 输出使能位,为 1 的时候关闭 PLL3_PFD0 的输出,为 0 的时候使能输出 2.3 AHB、IPG 和 PERCLK 根时钟设置 除了以上两个时钟,IMX还需要设置 AHB_CLK_ROOT 和 IPG_CLK_ROOT 的时钟,I.MX6U 外设根时钟可设置范围如图: 上图给出了大多数时钟的配置方式,下面按上图,将AHB_CLK_ROOT、 IPG_CLK_ROOT 和 PERCLK_CLK_ROOT 分别设置为 132MHz 、 66MHz 、 66MHz;先看一下 AHB_CLK_ROOT 和 IPG_CLK_ROOT 的时钟树: 可以看到,时钟树中的时钟经过路径为:
其时钟源可以来自 OSC(24MHz) 和 IPG_CLK_ROOT 两个时钟源,如果来自 OSC 的话,通过寄存器 CCM_CSCMR1 的 PERCLK_PODF 位来设置分频 以上三个时钟频率的配置主要依靠三个寄存器来配置: CCM_CBCDR 寄存器 其各位功能如下: [tr]寄存器位功能[/tr]
[tr]寄存器位功能[/tr]
重点以下两个位: [tr]寄存器位功能[/tr]
① mmdc_podf ② periph_clk_sel ③ periph2_clk_sel ④ arm_podf ⑤ ahb_podf 在寄存器 CCM_CDHIPR 中保存着握手信号是否完成, 如果相应的位为 1 的话就表示握手没有完成,如果为 0 的话就表示握手完成 修改 arm_podf 和 ahb_podf 的时候需要先关闭其时钟输出,等修改完成以后再打开, 否则的话可能会出现在修改完成以后没有时钟输出的问题三、配置代码 代码工程基于上一届的按键输入继续修改,主要就是修改 bsp_clk 模块内容,此处使用的正点原子的配置代码: #include "bsp_clk.h" #include "fsl_iomuxc.h" #include "MCIMX6Y2.h" void CLK_INIT(void) { //寄存器缓冲位 unsigned int reg = 0; //先切换输入时钟源 if((((CCM->CCSR) >> 2) & 0x1 ) == 0) /* 当前pll1_sw_clk使用的pll1_main_clk*/ { CCM->CCSR &= ~(1 << 8); /* 配置step_clk时钟源为24MH OSC */ CCM->CCSR |= (1 << 2); /* 配置pll1_sw_clk时钟源为step_clk */ } //设置主频,并切换回时钟源 CCM_ANALOG->PLL_ARM = (1 << 13) | ((88 << 0) & 0X7F); /* 配置pll1_main_clk=1056MHz */ CCM->CCSR &= ~(1 << 2); /* 将pll_sw_clk时钟重新切换回pll1_main_clk */ CCM->CACRR = 1; /* ARM内核时钟为pll1_sw_clk/2=1056/2=528Mhz */ /* 2、设置PLL2(SYS PLL)各个PFD */ reg = CCM_ANALOG->PFD_528; reg &= ~(0X3F3F3F3F); /* 清除原来的设置 */ reg |= 32<<24; /* PLL2_PFD3=528*18/32=297Mhz */ reg |= 24<<16; /* PLL2_PFD2=528*18/24=396Mhz(DDR使用的时钟,最大400Mhz) */ 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)各个PFD */ reg = 0; /* 清零 */ 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时钟 最小6Mhz, 最大132Mhz (boot rom自动设置好了可以不用设置)*/ CCM->CBCMR &= ~(3 << 18); /* 清除设置*/ CCM->CBCMR |= (1 << 18); /* pre_periph_clk=PLL2_PFD2=396MHz */ 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 << 1));/* 等待握手完成 */ #endif /* 5、设置IPG_CLK_ROOT最小3Mhz,最大66Mhz (boot rom自动设置好了可以不用设置)*/ 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 &= ~(7 << 0); /* PERCLK_PODF位清零,即1分频 */ } 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; } 代码只修改了 bsp_clk 模块文件的代码,所以 makefile 文件不需要修改直接编译下载:下载通过如下 这里只是修改了默认主频,表现起来的现象只是延时长度不同。 |
|
|
|
只有小组成员才能发言,加入小组>>
3280 浏览 9 评论
2958 浏览 16 评论
3460 浏览 1 评论
9004 浏览 16 评论
4052 浏览 18 评论
1115浏览 3评论
573浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
571浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2303浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1859浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 12:17 , Processed in 1.193615 second(s), Total 81, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号