7.IXM6U系统时钟
7.IXM6U系统时钟
1.32.768Kzh的晶振供给RTC使用
2.在6U的T16和T17这两个IO上接了24Mhz的晶振。
1.七路PLL
24Mhz的晶振频率被PLL(倍频)后成七路
PLL1: ARM PLL -供给ARM内核(可进行配置)
PLL2: 固定22倍频 2422 = 528 Mhz,又叫528PLL,此路PLL分出了4路PLL,PFD
PLL3(USB_PLL): 主要用于USBPHY,又叫480PLL。固定20倍 2420 = 480Mhz,也分出四路PLL3_PFD0~PLL_PFD3
PLL4:AudioPLL ,主供音频
PLL5:Video PLL ,主供视频外设,如RGB LED 接口,和图像处理有关外设
PLL6: ENET PLL 主供网络外设
PLL7(USB2_PLL) 480MHz,无PFD
一般主要使用PLL1、2、3、4、5及其分路

2.时钟树,
在STM32学习的时候,也有时钟树
这个时钟树更加复杂
时钟源经过倍频/分频后给到各个外设
不同的外设可以通过多路选择器可以选择不同的时钟源

三、初始化
常用的外设需要初始化相应的时钟
PLL1
PLL2 以及4路PLL
PLL3 以及4路PLL
PLL4
Table 18-4. System Clock Frequency Values
表中有各个外设的时钟频率参考值
四、配置系统主频


若要将ARM配置为528Mhz ①PLL设置为1056Mhz /2 (分频) 得到528Mhz
若要将ARM配置为696Mhz ② PLL设置为696Mhz /1 (分频) 得到696Mhz 无法通过 /2 (分频) 得到
PLL1取值范围:650 MHz —— 1.3 GHz.
CCM Arm Clock Root Register (CCM_CACRR) 寄存器说明:
可以设置不同分频 1- 8分频

000 divide by 1
001 divide by 2 ✔
010 divide by 3
011 divide by 4
100 divide by 5
101 divide by 6
110 divide by 7
111 divide by 8
设置步骤
目标设置ARM主频为 528Mhz
18.5.1.5.1 Clock Switcher PLL1的设置:

PLL1的输出可以有PLL1_mian_clk选择996Mhz
还有备用时钟源step_clk,来源有①osc_clk②secondeary_clk,备用时钟源用osc_clk即可。改变一路时钟时需要零时切换到另外一路备用时钟源,以提供工作频率
步骤①:前面说到方案:PLL设置为1056Mhz /2 (分频) 得到528Mhz /2 (分频)可以通过CCM_CACRR寄存器的arm-podf = 1实现
②设置PLL1 = 1056Mhz 通过CCSR寄存器的ppl1_sw_clk_sel选择时钟源,在修改系统时钟的时候需要给6ULL一个临时的时钟,也就是step_clk
③step_clk也有两路来源osc_clk以及sencondary_clk,可以通过CCSR的step_sel(位)进行选择,一般通过0选择osc_clk(24Mhz)来
④时钟切换之后就可以修改PLL1的值
⑤修改PLL1的值是通过CCM_ANALOG_PLL_ARM[DIV_SELECT] 进行修改的
This PLL synthesizes a low jitter clock from a 24 MHz reference clock. The clock output frequency for this PLL ranges from 650 MHz to 1.3 GHz. The output frequency is selected by a 7-bit register field CCM_ANALOG_PLL_ARM[DIV_SELECT]
修改公式为:
PLL output frequency = Fref(输入固定24MHz) * DIV_SEL/2 Fref 为我们需要设置的arm时钟频率 528Mhz
1056 = 24* DIV_SEL /2 -> 得到DIV_SEL = 88
还要bit13设置为使能时钟输出
⑥切换为PLL1_main_clk

void imx6u_clkInit(void){//初始化为528Mhzif(((CCM->CCSR>>2) & 0x01 ) == 0) { //判断是否选择了main_clkCCM->CCSR &=~ (1<<8); //设置step_clk为osc_clk时钟源24MhzCCM->CCSR |= (1<<2) ; //设置系统时钟为备用的step_clk(24Mhz)}CCM_ANALOG->PLL_ARM = (1<<13)| ((88<<0) & 0x7F); //(1<<13):使能时钟输出,0x7F作用是只修改七位有效DIV_SELECT是0-6位,限制数据宽度。58为10进制数,与十六进制按位与时,转化成二进制数。有效仍为58 -》 0011 1010//分频系数CCM->CACRR |= 0x1 ; //二分频//切换时钟源CCM->CCSR &=~ (1<<2); //切换到ppl1_main_clk
}
PPL1 的 输入为:24* DIV_SEL /2 当DIV_SEL为88时,输出1056Mhz的ppl1_main_clk
接着经过分频之后(2分频)得到 了528Mhz的arm时钟频率,就会影响如Delay这种延时函数、以及所有代码的执行效率。
对各PLL时钟的配置
PLL2和PLL3
PLL2固定为528Mhz PLL3固定为480Mhz
但需要对PLL2、PLL3分出的各四路PFD时钟进行配置
①初始化PLL2_PFD0-PLL2_PFD3
使用到的寄存器为:
528MHz Clock (PLL2) Phase Fractional Divider ControlRegister (CCM_ANALOG_PFD_528n)
寄存器CCM_ANALOG_PFD_528用于设置4路PFD的时钟, 每8位中前6位3F进行配置一路的PFD
如第0-5位用于设置PLL2_PFD0的时钟频率 其他2位保留
8-15位中的8-13用于设置PLL2_PFD1的时钟频率 其他2位保留
16-23位的16-21用于设置PLL2_PFD2的时钟频率 其他2位保留
24-32位的24-20用于设置PLL2_PFD3的时钟频率 其他2位保留
This field controls the fractional divide value. The resulting frequency shall be 528*18/PFD0_FRAC where PFD0_FRAC is in the range 12-35
PFD0 = 528*18/PFD0_FRAC PFD0_FRAC为 寄存器设置的zhi
要将PPL2_PFD0设为352Mhz 则设置 PFD0_FRAC 的值(12-35)为27 -> 528 * 18 /27 = 352M
基本思路:
1.读取原寄存器的值,只对需要修改的数据进行修改,其他位保持不变
2.读取后对需要修改的位进行清零(&=~)操作
3.对对应位进行修改(|=)置位
4.写入寄存器(=)

下面设置8路PFD位NXP推荐频率
②初始化PLL3_PFD0 - PLL3_PFD3
480MHz Clock (PLL3) Phase Fractional Divider ControlRegister (CCM_ANALOG_PFD_480n)

result FRAC = 480*18/PFD0_FRAC PFD0_FRAC为寄存器的值
volatile unsigned int reg;reg = CCM_ANALOG->PFD_528;reg &=~ (0x3F3F3F3F); //即00111111前两位不清零,保持默认reg |= (32<<24); //PFD3 297Mhzreg |= (24<<16); //PFD2 396Mhzreg |= (16<<8); //PFD1 594Mhzreg |= (27<<0); //PFD0 352MhzCCM_ANALOG->PFD_528 = reg;reg = 0;reg = CCM_ANALOG->PFD_480;reg &=~ (0x3F3F3F3F); //即00111111前两位不清零,保持默认reg |= (19<<24); //PFD3 454.7Mhzreg |= (17<<16); //PFD2 508.2Mhzreg |= (16<<8); //PFD1 540Mhzreg |= (12<<0); //PFD0 720MhzCCM_ANALOG->PFD_480 = reg;
③其他外设时钟源配置
主要是 PERCLK_CLK_ROOT、IPG_CLK_ROOT、AHB_CLK_ROOT


均设置为最大的时钟源 132 Mhz 66 Mhz 66 Mhz
后面AHB_CLK_ROOT再往后是PERCLK_CLK_ROOT、IPG_CLK_ROOT的时钟源信号
①初始化AHB_CLK_ROOT推荐(6-132Mhz)
设置为132Mhz,时钟来源为PLL2_PFD2的396Mhz的时钟信号

需要配置几个多路选择器CBCDR[PERIPH_CLK_SEL]、CBCMR[PERIPH_CLK2_SEL]
具体如下18章节的框图所示

1.需要设置CBCMR[PRE_PERIPH_CLK_SEL]选择PLL2_PFD2
2.设置CBCDR[PERIPH_CLK_SEL]位为0
3.来自PLL2_PFD2的396Mhz的时钟信号需要经过分频器 396 / 3 = 132 Mhz的频率,即CBCDR[AHB_PODF]为3分频给到AHB_CLK_ROOT
4.经过分频后的132Mhz的频率 经过CBCDR[IPG_PODF] 设置为2分频 132/2 = 66 Mhz的频率给到IPG_CLK_ROOT
CBCMR[PERIPH_CLK_SEL]: 配置为11从PLL2_PFD2的不分频的路线过来
PLL2_PFD2前面设置了369Mhz
CBCMR寄存器:

CBCDR寄存器:

CCM->CBCMR &=~(3<<18); //将18-19位清零CCM->CBCMR |= (1<<18); //将18-19位设置为1CCM->CBCDR &=~(1<<25); //清零//CCM->CBCDR |= (0<<25);CCM->CBCDR &=~ (7 << 10); //将10-12位清零CCM->CBCDR |= (2 << 10); //将10-12置为010 三分频
对寄存器的操作最好是先读出,再对变量进行操作,直接操作寄存器可能会导致寄存器慢状态无法对后面的赋值进行及时相应
将思路换成下面: 每次寄存器读出来,对临时变量reg进行修改,多次修改也不会导致寄存器忙的状态,切写入也只是写入一次
reg = CCM->CBCMR;reg &=~ (3<<18);reg |= (1<<18);CCM->CBCMR = reg;while (CCM->CDHIPR & (1<<5));reg = CCM->CBCDR;reg &=~0x2001C00;reg |= (3<<10);CCM->CBCDR = reg;while (CCM->CDHIPR & (1<<1));
避免了短时间内对同一个寄存器进行写入操作,导致不生效或其他原因。
不使用临时变量,则需要根据note来编写:写入|等待握手|写入|等待握手
②初始化IPG_CLK_ROOT,设置为66Mhz
CCM->CBCDR &= ~(3 << 8); /* CBCDR的IPG_PODF清零 */CCM->CBCDR |= 1 << 8; /* IPG_PODF 2分频,IPG_CLK_ROOT=66MHz */
③PERCLK_CLK_ROOT

可以看到PERCLK_CLK_ROOT前面有一个多路选择器和一个预分频器
多路选择器在CSCMR1的PERCLK_PODF位前面的一个位,即PERCLK_CLK_SEL位用于选择时钟源该位置0
PERCLK_PODF位置为全0 1分频

/* 6、设置PERCLK_CLK_ROOT时钟 */CCM->CSCMR1 &= ~(1 << 6); /* PERCLK_CLK_ROOT时钟源为IPG */CCM->CSCMR1 &= ~(0x3f << 0); /* PERCLK_PODF位清零,即1分频 */
相关源码:https://gitee.com/yulindd/imx6ull-assembly-experiment
本节我们学习了如何配置imx6ull的时钟树部分,也知道了整个板子的脉络,神经系统。
