zoukankan      html  css  js  c++  java
  • [smart210] 通过PLL设置各时钟频率的方法以及代码注释

    平台:smart210(tiny210v2)

    CPU:S5PV210

    目标:

    设置APLL (提供MSYS domain 与DSYS domain 下各时钟的来源,最高1Ghz)

    设置MPLL(提供MSYS domain 与DSYS domain 下各时钟的来源,最高2Ghz)

    设置EPLL(Audio相关时钟)

    设置VPLL(Video相关时钟,54Mhz)

    知识储备:

    1.   MSYS主要为CPU,DRAM控制器,3D,IRAM,IROM,中断控制器等提供时钟

          DSYS主要为显示相关部件FIMC,FIMD,JPEG,Multimedia IPs提供时钟

          PSYS为外设I2S,SPI,I2C,UART等提供时钟

    2.  官方文档有时钟domain的【时钟继承图】(自造词。。)

           从图上我们能发现,MSYS domain包含有ARMCLK、HCLK_MSYS、PCLK_MSYS、HCLK_IMEM、SCLK_DMC0 这几个时钟信号,追本溯源,这些时钟信号主要都源于APLL或者MPLL经过各种分频倍频环节得到的,而其他的CLOCK domain下的子时钟也如此,换句话说,只要先把外置时钟源FIN=24Mhz转换成我们需要的APLL,MPLL这两个主要的PLL时钟,其余大部分的时钟我们就能轻松设置了。

    3    官方还给出了直观的各子时钟的设置来源与推荐值:

    4   同样的,官方P364给出了从FIN到设置最终子时钟的整个流程:

    ①打开APLL:APLL_CON0[31]=1;这里能看到bit31是使能控制端

    ②等待PLL锁定

    ③在锁定时钟稳定后,令APLL输出:CLK_SRC0[0]=1;这里能看到bit0(APLL_SEL)控制MUX_APLL的时钟输出,同时bit16(MUX_MSYS_SEL)控制了MUX_MSYS的输出

    ④改变分频值,设置PMS,其实就是PDIV,MDIV,SDIV的值,相关寄存器仍是APLL_CON0,参考步骤①的附图,而设置的PMS有什么用呢?我们最终要得到的是APLL的时钟,这个时钟通过FIN与PMS三个分频系数计算得到,使用的是下面这条公式  FOUT=MDIV*FIN/(PDIV*2^(SDIV-1))  。下面附图给出了公式以及PMS的取值范围:

    ⑤设置各CLOCK domain下的子时钟的分频比,从而确定了最终的MSYS domain、PSYS domain与DSYS domain各子时钟的频率,相关寄存器CLK_DIV0、CLK_DIV1、CLK_DIV2,这里贴出主要的CLK_DIV0

    5.好了,现在整理一下那5个步骤,其实顺序可以打乱,只要设置得当就行,这5个步骤中,有几个关键点要注意的:

    ①初始输入频率FIN为24Mhz,通过设置APLL_CON来控制PLL使能,以及设置PMS的值,设置完这些,我们基本上得到了APLL的FOUT,一般都是先想好需要多快的FOUT,再去设置PMS的值的。

    ②获取到FOUT APLL之后,通过设置CLK_SRC0的相关位把FOUT APLL作为MUX APLL的输出(从最上面那个【时钟继承图】上可以看出MUX APLL可以选择FIN或者FOUT APLL作为输出,输出的时钟名为SCLK_APLL  )同时,我们还要通过设置CLK_SRC0的相关位如MUX_MSYS_SEL(【时钟继承图】上的又一个多路复用器)将SCLK_APLL作为该MUX的输出,输出的时钟名为MOUT_MSYS

    ③最后就是通过设置CLK_DIV0来设置各子时钟的分频比了,可以发现,只要有了MOUT_MSYS,MSYS domain里面的子时钟都能通过设置这个寄存器而得到!

    6.下面再不厌其烦地给出直观的讲解图

    终于到了代码阶段了,有了上面的知识储备,程序的事也是手到擒来是吧!

    1.首先start.s关好看门狗,设置堆栈后,进入clock_init

    .global _start
    _start:
        ldr    r0, =0xE2700000            
        mov    r1, #0
        str    r1, [r0]
        ldr    sp, =0x40000000                        
        bl clock_init                        
        bl main                            
    halt:
        b halt

    2.clock.c中,有写好的clock_init函数

    // 时钟相关寄存器
    #define APLL_LOCK             ( *((volatile unsigned long *)0xE0100000) )        
    #define MPLL_LOCK             ( *((volatile unsigned long *)0xE0100008) )
    
    #define APLL_CON0             ( *((volatile unsigned long *)0xE0100100) )
    #define APLL_CON1             ( *((volatile unsigned long *)0xE0100104) )
    #define MPLL_CON             ( *((volatile unsigned long *)0xE0100108) )
    
    #define CLK_SRC0             ( *((volatile unsigned long *)0xE0100200) )
    #define CLK_SRC1             ( *((volatile unsigned long *)0xE0100204) )
    #define CLK_SRC2             ( *((volatile unsigned long *)0xE0100208) )
    #define CLK_SRC3             ( *((volatile unsigned long *)0xE010020c) )
    #define CLK_SRC4             ( *((volatile unsigned long *)0xE0100210) )
    #define CLK_SRC5             ( *((volatile unsigned long *)0xE0100214) )
    #define CLK_SRC6             ( *((volatile unsigned long *)0xE0100218) )
    #define CLK_SRC_MASK0         ( *((volatile unsigned long *)0xE0100280) )
    #define CLK_SRC_MASK1         ( *((volatile unsigned long *)0xE0100284) )
    
    #define CLK_DIV0             ( *((volatile unsigned long *)0xE0100300) )
    #define CLK_DIV1             ( *((volatile unsigned long *)0xE0100304) )
    #define CLK_DIV2             ( *((volatile unsigned long *)0xE0100308) )
    #define CLK_DIV3             ( *((volatile unsigned long *)0xE010030c) )
    #define CLK_DIV4             ( *((volatile unsigned long *)0xE0100310) )
    #define CLK_DIV5             ( *((volatile unsigned long *)0xE0100314) )
    #define CLK_DIV6             ( *((volatile unsigned long *)0xE0100318) )
    #define CLK_DIV7             ( *((volatile unsigned long *)0xE010031c) )
    
    #define CLK_DIV0_MASK        0x7fffffff
    
    #define APLL_MDIV           0x7d
    #define APLL_PDIV           0x3
    #define APLL_SDIV               0x1
    #define MPLL_MDIV            0x29b
    #define MPLL_PDIV            0xc
    #define MPLL_SDIV            0x1
    
    #define set_pll(mdiv, pdiv, sdiv)    (1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
    #define APLL_VAL        set_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV)
    #define MPLL_VAL        set_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV)
    
    //#define PLL_OFF        //屏蔽此句才能顺利启用PLL设置
    
    void clock_init()
    {
        // 1 设置各种时钟开关,暂时不使用PLL
        CLK_SRC0 = 0x0;    //根据手册显示,0代表使用FINPLL即默认外置时钟源(此时FIN=24Mhz)
        //CLK_SRC0寄存器中控制位:[0]->APLL_SEL,[4]->MPLL_SEL,[8]->EPLL_SEL,[12]->VPLL_SEL
    #ifndef PLL_OFF
    
        // 2 设置锁定时间,使用默认值即可
        // 设置PLL后,时钟从Fin提升到目标频率时,需要一定的时间,即锁定时间             
        APLL_LOCK = 0x0000FFFF;              
        MPLL_LOCK = 0x0000FFFF;
                            
        // 3 设置分频
        CLK_DIV0 = 0x14131440;
    
    
    
    
        //以APLL为例,这里CLK_DIV0设置了APLL_RATIO的值为0,则根据公式 ARMCLK=MOUT_MSYS/(APLL_RATIO + 1)=MOUT_MSYS
    
        // 4 设置PLL
        //解析为APLL_CON0=APLL_VAL=(1<<31|0x7d<<16|0x3<<8|0x1)意思就是APLL_CON0寄存器[31]位使能,允许PLL控制
        //[25:16]位为MDIV(倍频因子)值,[13:8]为PDIV(分频因子)值,[2:0]为SDIV值,FOUT计算公式如下
        // FOUT= MDIV * FIN / (PDIV*2^(SDIV-1)) = 0x7d*24/(0x3*2^(1-1))=1000 MHz
        //上式采用MDIV=0x7d(125),PDIV=0x3(3),SDIV=0x1(1)
        APLL_CON0 = APLL_VAL;
        // FOUT = MDIV*FIN/(PDIV*2^SDIV)=0x29b*24/(0xc*2^1)= 667 MHz
        MPLL_CON  = MPLL_VAL;
                        
        // 5 设置各种时钟开关,使用PLL
        CLK_SRC0 = 0x10001111;
    #endif
    }
  • 相关阅读:
    【DFS】XIII Open Championship of Y.Kupala Grodno SU Grodno, Saturday, April 29, 2017 Problem D. Divisibility Game
    【二分】【三分】【计算几何】XIII Open Championship of Y.Kupala Grodno SU Grodno, Saturday, April 29, 2017 Problem L. Lines and Polygon
    【线段树】XIII Open Championship of Y.Kupala Grodno SU Grodno, Saturday, April 29, 2017 Problem J. Jedi Training
    【贪心】【后缀自动机】XIII Open Championship of Y.Kupala Grodno SU Grodno, Saturday, April 29, 2017 Problem E. Enter the Word
    【转载】随机生成k个范围为1-n的随机数,其中有多少个不同的随机数?
    【推导】【贪心】XVII Open Cup named after E.V. Pankratiev Stage 4: Grand Prix of SPb, Sunday, Octorber 9, 2016 Problem H. Path or Coloring
    【枚举】XVII Open Cup named after E.V. Pankratiev Stage 4: Grand Prix of SPb, Sunday, Octorber 9, 2016 Problem D. Cutting Potatoes
    【找规律】【递归】XVII Open Cup named after E.V. Pankratiev Stage 4: Grand Prix of SPb, Sunday, Octorber 9, 2016 Problem F. Doubling
    【贪心】Codeforces Round #436 (Div. 2) D. Make a Permutation!
    【计算几何】【圆反演】计蒜客17314 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 G. Finding the Radius for an Inserted Circle
  • 原文地址:https://www.cnblogs.com/tinyfeather/p/3260471.html
Copyright © 2011-2022 走看看