(五)arm裸机开发---主频和时钟配置

本节主要涉及imx6ull的时钟配置,包括arm内核时钟配置,外设时钟配置,以及imx6ull的时钟树设置。主要参考的是imx6ull的Reference(《IMX6ULL 参考手册》)。

一、时钟树

      imxull的时钟来源于俩部分,一部分是实时时钟,32.768MHZ,用于提供RTC的时钟。另一部分是24MHZ的晶振,用于提供内核以及其他外设的时钟。我们的时钟树就是从24M时钟经过倍频,分频得来的,共有7路PLL。
      具体的时钟树就不放上来了,截图实在是看不清楚。其实就是通过设置一些寄存器,设置多路选择器和分频器,输出指定的频率。

1.配置主时钟

      我们将 I.MX6ULL 的主频设置为 528MHz。我们如果要设置2分屏的话,PLL1必须设置为1056M的输出。 ARM_PLL 是由CCM_ANALOG_PLL_ARM[DIV_SELECT]设置的,计算公式是PLL output frequency = Fref * DIV_SEL/2。所以 经过计算,CCM_ANALOG_PLL_ARM[DIV_SELECT]=88。2分屏的设置为CCM_CACRR[ARM_PODF]=0x2
在这里插入图片描述
      我们在设置主频的时侯需要先将主频设置为备用模式(必须得有一个主频,单片机才可以工作,即使是设置寄存器)。
在这里插入图片描述
从上图中可以看到先要设置CCSR[step_sel]=0,然后设置CCSR[pll1_sw_clk_sel]=1
所以综上所述;
1.CCSR[step_sel]=0; //备用时钟设置
2.CCSR[pll1_sw_clk_sel]=1; //切换备用时钟
3.CCM_ANALOG_PLL_ARM[DIV_SELECT]=88; //设置主频
4.CCM_CACRR[ARM_PODF]=0x1; //设置2分频
5.CCSR[pll1_sw_clk_sel]=0; //切换回主时钟

2.配置其他PLL和PFD

以下是我们要设置的PLL和PFD:
在这里插入图片描述
PLL2_PFD0的计算公式为528*18/PFD0_FRAC
CCM_ANALOG_PFD_528[PFD0_FRAC] = 0x1B; //PFD0=352M
CCM_ANALOG_PFD_528[PFD1_FRAC] = 0x10; //PFD1=594M
CCM_ANALOG_PFD_528[PFD2_FRAC] = 0x18; //PFD2=396M
CCM_ANALOG_PFD_528[PFD3_FRAC] = 0x20; //PFD3=297M

PLL2_PFD0的计算公式为480*18/PFD3_FRAC
CCM_ANALOG_PFD_480[PFD0_FRAC] = 0xC; //PFD0=720M
CCM_ANALOG_PFD_480[PFD1_FRAC] = 0x10; //PFD1=540M
CCM_ANALOG_PFD_480[PFD2_FRAC] = 0x11; //PFD2=508.2M
CCM_ANALOG_PFD_480[PFD3_FRAC] = 0x13; //PFD3=454.7M

3. AHB、 IPG 和 PERCLK 根时钟设置

设置完主频和其他PLL PFD之后我们还需要设置AHB_CLK_ROOT,IPG_CLK_ROOT,PERCLK_CLK_ROOT。AHB_CLK_ROOT 最高可以设置 132MHz,IPG_CLK_ROOT和PERCLK_CLK_ROOT最高可以设置66MHz。

#AHB_CLK_ROOT设置
CBCMR[PRE_PERIPH_CLK_SEL] = 01 //选择396M
CBCDR[PERIPH_CLK_SEL] =0 //需要握手信号
CBCDR[AHB_PODF]=010 //3分频,需要握手信号

#IPG_CLK_ROOT设置
CBCDR[IPG_PODF]=01 //设置2分频

#PERCLK_CLK_ROOT设置
CSCMR1[PERCLK_CLK_SEL] = 0 //多路选择
CSCMR1[PERCLK_PODF] = 000000 //1分频

寄存器 CCM_CDHIPR判断握手信号是否完成,1 握手没有完成,0握手完成。
在修改 arm_podf 和 ahb_podf 的时候需要先关闭其时钟输出,等修改完成以后再打开

二、编写程序

#include "bsp_clk.h"

//使能时钟
int enable_clock(void){
    CCM->CCGR0 = 0xffffffff;
    CCM->CCGR1 = 0xffffffff;
    CCM->CCGR2 = 0xffffffff;
    CCM->CCGR3 = 0xffffffff;
    CCM->CCGR4 = 0xffffffff;
    CCM->CCGR5 = 0xffffffff;
    CCM->CCGR6 = 0xffffffff;

    return 0;
}

void init_imx6u_clock(void){
    /*1.配置主时钟*/
    if(((CCM->CCSR>>2) & 0x1) == 0){//判断现在是否使用的是主时钟
        CCM->CCSR &= ~(1<<8);       //设置备用时钟
        CCM->CCSR |= 1<<2;          //切换到备用时钟
    }
    //设置主频
    CCM_ANALOG->PLL_ARM &= ~(0x7f);             //0-6位清零
    CCM_ANALOG->PLL_ARM |= (1<<13) | (88);       //0-6位设置为88,13位为使能位
    //设置2分频
    CCM->CACRR = 0x1;
    //切换回主时钟
    CCM->CCSR &= ~(1<<2);
   
    /*2.配置其他PLL和PFD*/
    /*PPL2*/
    unsigned int reg = CCM_ANALOG->PFD_528;
    reg &= ~(0x3f3f3f3f);   //PFD每个Byte的0-5位清零
    reg |= 0x1b << 0;       //PFD0=352M
    reg |= 0x10 << 8;       //PFD1=594M
    reg |= 0x18 << 16;      //PFD2=396M
    reg |= 0x20 << 24;      //PFD3=297M
    CCM_ANALOG->PFD_528 = reg;

    /*PPL3*/
    reg = CCM_ANALOG->PFD_480;
    reg &= ~(0x3f3f3f3f);   //PFD每个Byte的0-5位清零
    reg |= 0xC  << 0;       //PFD0=720M
    reg |= 0x10 << 8;       //PFD1=540M
    reg |= 0x11 << 16;      //PFD2=508.2M
    reg |= 0x13 << 24;      //PFD3=454.7M
    CCM_ANALOG->PFD_480 = reg;

    /*3. AHB、 IPG 和 PERCLK 根时钟设置*/
#if 0
    /*AHB_CLK_ROOT设置为132M*/
    CCM->CBCMR &= (~(3 << 18)) | (1 << 18);     //选择396M

    CCM->CBCDR &= ~(1 << 25);
    while(CCM->CDHIPR & (1 << 5));              //等待握手完成

    CCM->CBCDR &= (~(7 << 10)) | (2 << 10);     //设置3分频
    while(CCM->CDHIPR & (1 << 1));              //等待握手完成 
#endif

    /*IPG_CLK_ROOT设置为66M*/
    CCM->CBCDR &= (~(3 << 8)) | (1 << 8);       //设置2分频

    /*PERCLK_CLK_ROOT设置为66M*/
    CCM->CSCMR1 &= ~(1<<6);         //多路选择
    CCM->CSCMR1 &= ~(0x7);         //1分频 不是3F?
}

总结:I.MX6ULL的时钟系统还是很复杂的,本节我们也只是讲解了如何进行主频、PLL、 PFD 和一些总线时钟的设置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值