i.MX6ULL終結者主頻和時鐘配置例程程式設計

一隻流浪小法師發表於2020-09-26

本實驗對應的例程在光碟資料的:i.MX6UL終結者光碟資料\04_裸機例程原始碼\7_clk 目錄下面,我們在Ubuntu系統下使用命令“mkdir 7_clk”建立“7_clk”資料夾,如圖 1所示:
在這裡插入圖片描述

圖 1

然後使用命令“cd 7_clk”進入7_clk檔案。如圖 2所示:
在這裡插入圖片描述

圖 2

然後使用命令“cp -r …/6_key/* ./”將上一章試驗中的所有內容拷貝到剛剛新建的“7_clk”裡面,如圖 3:
在這裡插入圖片描述

圖 3

拷貝完成以後的工程如圖 4所示:
在這裡插入圖片描述

圖 4

然後使用命令“vi drivers/clk/clk.h”修改clk.h檔案。如圖 5所示:
在這裡插入圖片描述

圖 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所示:
在這裡插入圖片描述

圖 6

新增完成之後,儲存並退出檔案。
然後使用命令“vi drivers/clk/clk.c”修改clk.c檔案。如圖 7所示:
在這裡插入圖片描述

圖 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所示:
在這裡插入圖片描述

圖 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 }

我們在main.c裡新增了clk.h標頭檔案,然後主函式中新增初始化及使能clk的函式。在這裡插入圖片描述

相關文章