本实验对应的例程在光盘资料的:i.MX6UL终结者光盘资料\04_裸机例程源码\7_clk 目录下面,我们在Ubuntu系统下使用命令“mkdir 7_clk”建立“7_clk”文件夹,如图 1所示:
然后使用命令“cd 7_clk”进入7_clk文件。如图 2所示:
然后使用命令“cp -r …/6_key/* ./”将上一章试验中的所有内容拷贝到刚刚新建的“7_clk”里面,如图 3:
然后使用命令“vi drivers/clk/clk.h”修改clk.h文件。如图 5所示:
修改如下内容:
1 #ifndef __BSP_CLK_H
2 #define __BSP_CLK_H
3
4 #include "imx6ul.h"
5
6 /* 函数声明 */
7 void clk_enable(void);
8 void imx6u_clkinit(void);
9
10
11 #endif
gpio.h文件中是两个函数声明。主要是第7行添加void clk_enable和第8行添加 imx6u_clkinit函数声明,部分截图如图 6所示:
添加完成之后,保存并退出文件。
然后使用命令“vi drivers/clk/clk.c”修改clk.c文件。如图 7所示:
添加内容如下:
1 #include "clk.h"
2
3 /*
4 * @description : 使能I.MX6U所有外设时钟
5 * @param : 无
6 * @return : 无
7 */
8 void clk_enable(void)
9 {
10 CCM->CCGR0 = 0XFFFFFFFF;
11 CCM->CCGR1 = 0XFFFFFFFF;
12 CCM->CCGR2 = 0XFFFFFFFF;
13 CCM->CCGR3 = 0XFFFFFFFF;
14 CCM->CCGR4 = 0XFFFFFFFF;
15 CCM->CCGR5 = 0XFFFFFFFF;
16 CCM->CCGR6 = 0XFFFFFFFF;
17 }
18
19 /*
20 * @description : 初始化系统时钟,设置系统时钟为528Mhz,设置PLL2和
21 PLL3各个PFD时钟,所有时钟频率按照I.MX6U官方手册推荐的值.
22 * @param : 无
23 * @return : 无
24 */
25 void imx6u_clkinit(void)
26 {
27 unsigned int reg = 0;
28 /* 1、设置ARM内核时钟为528MHz */
29 /* 1.1、判断当前ARM内核是使用的哪个时钟源启动的,
正常情况下ARM内核是由pll1_sw_clk驱动的,而
30 * pll1_sw_clk有两个来源:pll1_main_clk和tep_clk。
31 * 如果要让ARM内核跑到528M的话必须选择
pll1_main_clk作为pll1的时钟源。
32 * 如果我们要修改pll1_main_clk时钟的话就必须
先将pll1_sw_clk从pll1_main_clk切换到step_clk,
33 * 当修改完pll1_main_clk以后在将pll1_sw_clk
切换回pll1_main_clk。而step_clk的时钟源可以选择
34 * 板子上的24MHz晶振。
35 */
36
37 if((((CCM->CCSR) >> 2) & 0x1 ) == 0) /* 当前pll1_sw_clk使用pll1_main_clk*/
38 {
39 CCM->CCSR &= ~(1 << 8); /* 配置step_clk时钟源为24MH OSC */
40 CCM->CCSR |= (1 << 2); /* 配置pll1_sw_clk时钟源为step_clk */
41 }
42
43 /* 1.2、设置pll1_main_clk为1056MHz,也就是528*2=1056MHZ,
44 * 因为pll1_sw_clk进ARM内核的时候会被二分频!
45 * 配置CCM_ANLOG->PLL_ARM寄存器
46 * bit13: 1 使能时钟输出
47 * bit[6:0]: 88, 由公式:Fout = Fin * div_select / 2.0,
1056=24*div_select/2.0,
48 * 得出:div_select= 88
49 */
50 CCM_ANALOG->PLL_ARM = (1 << 13)
| ((88 << 0) & 0X7F); /* 配置pll1_main_clk=1056MHz */
51 CCM->CCSR &= ~(1 << 2);
52 CCM->CACRR = 1;
53
54 /* 2、设置PLL2(SYS PLL)各个PFD */
55 reg = CCM_ANALOG->PFD_528;
56 reg&=~(0X3F3F3F3F);/*清除原来设置 */
57 reg |= 32<<24; /* PLL2_PFD3=528*18/32=297Mhz */
58 reg |= 24<<16; /*PLL2_PFD2=528*18/24=396Mhz(DDR时钟最大400Mhz) */
59 reg |= 16<<8; /* PLL2_PFD1=528*18/16=594Mhz*/
60 reg |= 27<<0; /* PLL2_PFD0=528*18/27=352Mhz
*/
61 CCM_ANALOG->PFD_528=reg; /* 设置PLL2_PFD0~3*/
62
63 /* 3、设置PLL3(USB1)各个PFD */
64 reg = 0; /* 清零 */
65 reg = CCM_ANALOG->PFD_480;
66 reg &= ~(0X3F3F3F3F); /* 清除原来的设置 */
67 reg |= 19<<24; /* PLL3_PFD3=480*18/19=454.74Mhz */
68 reg |= 17<<16; /* PLL3_PFD2=480*18/17=508.24Mhz*/
69 reg |= 16<<8; /* PLL3_PFD1=480*18/16=540Mhz */
70 reg |= 12<<0; /* PLL3_PFD0=480*18/12=720Mhz */
71 CCM_ANALOG->PFD_480=reg; /* 设置PLL3_PFD0~3 */
72
73 /* 4、设置AHB时钟最小6Mhz,最大132Mhz (boot rom设置好了不用设置)*/
74 CCM->CBCMR &= ~(3 << 18); /* 清除设置*/
75 CCM->CBCMR |= (1 << 18); /* pre_periph_clk=PLL2_PFD2=396MHz */
76 CCM->CBCDR &= ~(1 << 25); /* periph_clk=pre_periph_clk=396MHz */
77 while(CCM->CDHIPR & (1 << 5));/* 等待握手完成 */
78
79 /* 修改AHB_PODF位的时候需要先禁止AHB_CLK_ROOT的输出,但是
80 * 我没有找到关闭AHB_CLK_ROOT输出的的寄存器,所以就没法设置。
81 * 下面设置AHB_PODF的代码仅供学习参考不能直接拿来使用!!
82 * 内部boot rom将AHB_PODF设置为了3分频,即使我们不设置AHB_PODF,
83 * AHB_ROOT_CLK也依旧等于396/3=132Mhz。
84 */
85 #if 0
86 /* 要先关闭AHB_ROOT_CLK输出,否则时钟设置会出错 */
87 CCM->CBCDR &= ~(7 << 10); /* CBCDR的AHB_PODF清零 */
88 CCM->CBCDR |= 2 << 10; /* AHB_PODF 3分频,AHB_CLK_ROOT=132MHz */
89 while(CCM->CDHIPR & (1 << 1));/* 等待握手完成 */
90
91 #endif
92
93 /* 5、设置IPG_CLK_ROOT最小3M最大66M (boot rom设置好了不用设置)*/
94 CCM->CBCDR &= ~(3 << 8); /* CBCDR的IPG_PODF清零 */
95 CCM->CBCDR |= 1 << 8; /* IPG_PODF 2分频IPG_CLK_ROOT=66M */
96
97 /* 6、设置PERCLK_CLK_ROOT时钟 */
98 CCM->CSCMR1 &= ~(1 << 6); /* PERCLK_CLK_ROOT时钟源为IPG */
99 CCM->CSCMR1 &= ~(7 << 0); /* PERCLK_PODF位清零,即1分频 */
100 }
101
文件clk.c 中有两个函数:clk_enable和新添加的imx6u_clkinit。
clk_enable:使能I.MX6U的所有外设时钟。
imx6u_clkinit:先设置系统主频为528MHz,然后设置8路PFD,最后设置AHB、IPG和PERCLK的时钟频率。
然后使用命令“vi main.c”打开main.c。如图 8所示:
然后添加下面的内容:
1 #include "clk.h"
2 #include "delay.h"
3 #include "led.h"
4 #include "beep.h"
5 #include "key.h"
6
7 /*
8 * @description : main函数
9 * @param : 无
10 * @return : 无
11 */
12 int main(void)
13 {
14 int i = 0;
15 int keyvalue = 0;
16 unsigned char led_state = OFF;
17 unsigned char beep_state = OFF;
18
19 imx6u_clkinit(); /* 初始化系统时钟 */
20 clk_enable(); /* 使能所有的时钟 */
21 led_init(); /* 初始化led*/
22 beep_init(); /* 初始化beep*/
23 key_init(); /* 初始化key*/
24
25 while(1)
26 {
27 keyvalue = key_getvalue();
28 if(keyvalue)
29 {
30 switch ((keyvalue))
31 {
32 case KEY0_VALUE:
33 beep_state = !beep_state;
34 beep_switch(beep_state);
35 break;
36 }
37 }
38 i++;
39 if(i==50)
40 {
41 i = 0;
42 led_state = !led_state;
43 led_switch(LED0, led_state);
44 }
45
46 delay(10);
47 }
48
49 return 0;
50 }