I.MX6ULL裸机开发之时钟篇

在嵌入式开发中,时钟配置是至关重要的一部分。它影响整个系统的运行速度、定时和能耗等多个方面。

作为一位合格的嵌入式开发工程师,总不能连内核、外设、总线各自的频率都不清晰吧?


配置内核时钟

配置时钟最简单直接的方式就是看图了,下图的ARM就表示内核的时钟,它是由PLL1经过分频就得到,即改变PLL1频率和分频系数即可配置内核时钟

《IMX6ULL参考手册》——CCM Clock Tree

在这里插入图片描述


  • 要改变PLL1频率需要先将内核使用的时钟源切换成其他时钟源,比如24MHz晶振

  • 如下图可知,可以通过CCSR寄存器配置

    CCM->CCSR &= ~(1 << 8);				// 配置step_clk时钟源为24MH OSC
    CCM->CCSR |= (1 << 2);				// 配置pll1_sw_clk时钟源为step_clk
    

《IMX6ULL参考手册》——Figure 18-4
在这里插入图片描述
在这里插入图片描述



然后开始配置PLL1频率,这里Fin = 24MHz,将DIV_SELECT配置成66,及PLL1.Fout = 24*66/2MHz = 792MHz

CCM_ANALOG->PLL_ARM = (1 << 13) | (66UL << 0);

并配置CACRR[ARM_PODF]将分频系数设置为1

CCM->CACRR = 0;

在这里插入图片描述
在这里插入图片描述

最后将时钟源切换回PLL1,这时内核的时钟就是792MHz

CCM->CCSR &= ~(1 << 2);	



配置其余PLL时钟

PPL2-5都是固定频率,PLL4-5用于音视频,这里不做讨论,仅分配PPL2-3的各个PFD

时钟频率
PLL2528MHz
PLL3480MHz
PLL4650MHz
PLL5650MHz
	// 设置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

	// 设置PLL3(USB1)各个PFD
	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

配置总线时钟

Clock RootDefault Frequency (MHz)Maximum Frequency (MHz)
AXI_CLK_ROOT12264
AHB_CLK_ROOT6132
PERCLK_CLK_ROOT366
IPG_CLK_ROOT366

在这里插入图片描述
由上图可知:

  • AXI总线时钟由CBCDR寄存器的axi_alt_clk_selaxi_clk_selaxi_podf控制

  • AHB总线时钟由CBCMR[pre_periph_clk_sel]CBCDR寄存器的periph_clk_selahb_podf控制

  • IPG总线(APB)由AHB分配而来,分配系数由CBCDR[IPG_PODF]控制,默认2分频

  • PERCLK_CLK_ROOT由IPG_CLK_ROOT分配而来,由CSCMR1[PERCLK_CLK_SEL]CSCMR1[PERCLK_PODF]

设置AXI时钟(198MHz)

	reg = CCM->CBCDR;
	reg &= ~(1 << 7);				// sel PLL2 PFD2 = 396MHz 
	reg |= 1 << 6;			    // AXI_SEL = 1   alt clk
	reg &= ~(0x7 << 16);
	reg |= 1 << 16;					// AXI_PODF divide by 2 = 198MHz
	CCM->CBCDR = reg;
	while(CCM->CDHIPR);			// 等待握手完成 

设置AHB时钟(132MHz)

	reg = CCM->CBCMR;
	reg &= ~(3 << 18);
	reg |= (1 << 18);				// pre_periph_clk = PLL2_PFD2 = 396MHz
	CCM->CBCMR = reg;
	reg = CCM->CBCDR;
	reg &= ~(1 << 25);			// periph_clk = pre_periph_clk = 396MHz 
	reg &= ~(0x7 << 10);
	reg |= 2 << 10;					// AHB_PODF divide by 3 = 132MHz
	CCM->CBCDR = reg;
	while(CCM->CDHIPR);			// 等待握手完成 

设置IPG时钟(66MHz)

	reg = CCM->CBCDR;
	reg &= ~(3 << 8); 			// CBCDR的IPG_PODF清零
	reg |= 1 << 8;	  			// IPG_PODF divide by 2 = 66MHz
	CCM->CBCDR = reg;

设置PERCLK_CLK_ROOT时钟(66MHz)

	reg = CCM->CSCMR1;
	reg &= ~(1 << 6); 			// PERCLK_CLK_ROOT时钟源为IPG
	reg &= ~(7 << 0); 			// PERCLK_PODF位清零,即1分频
	CCM->CSCMR1 = reg;
  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值