上篇讲了配置时钟的原理,今天就结合源码具体分析一下。在U-Boot的源码中,系统时钟的初始化是放在板文件夹下的(board/Samsung/mytiny4412)的clock_init_zthtiny4412.S文件中的system_clock_init函数中。我们的Tiny4412是拷贝的smdk4212来的,所以,大家可以先参看smdk4212的clock_init_smdk4212.S文件中的system_clock_init函数来分析,完了再修改适合自己板子的程序。
对于芯片手册中每一个模块的学习,在了解前面的基本原理后,关键的寄存器的操作,可以先浏览一下这个模块的所有寄存器的简介,对各个寄存器的作用做到心中有数,这样,可以大体知道,需要配置哪些寄存器,不至于被下面一大堆的寄存器给弄懵了,系统时钟的寄存器介绍在第776开始的第7.9节REGISTERDESCRIPTION 。
我这里直接参照了FriendlyARM所提供的U-BOOT源码,基本上是复制了其tiny4412目录下的时钟设置代码,说明一下,我是学习为目录,所以很多代码都是从现有可以运行的程序那里复制来的,换句话说,我现在基本是在注释代码吧,下面顺着函数来分析:
一、输入源和分频比
设置时钟模块的时钟输入源和分频比,包括CPU,DMC,TOP,LEFTBUS,RIGHTBUS等。
1、CPU MUX /DIV的时钟源和分频比
由于要设置的模块寄存器比较多,这里我他仅仅分析一下如何设置 CPU MUX /DIV的时钟源和分频比,其设置过程是怎么样的。
开如之前,修改代码开头:
#ifdef CONFIG_EXYNOS4412
#include"smdk4412_val.h"à#include "zthtiny4412_val.h"
#else
#include"smdk4212_val.h"à#include "zthtiny4212_val.h"
#endif
再来看这个图3-1
图4-1、时钟源选择图
以及其设置寄存器如下表4-1截图所示:
表4-1、CLK_SRC_CPU寄存器设置
为了用24M的外部时钟进行分频,需设置MUX_APLL_SEL(MUXAPLL)为0,那么MUX_CORE_SEL也需设置成0,选择MOUTAPLL.其它的两位,按代码以前的设置为0,分别将MUX_MPLL_USER_SEL_C设置选择FINPLL.而MUX_HPM_SEL选择MOUTAPLL。所以此寄存器的设置值为0。设置完成后需要等待一定时间,让其设置成功,代码的实现方式是也可以与寄存器CLK_MUX_STAT_CPU的值相比较。如下表4-2所示为CLK_MUX_STAT_CPU状态值说明。
表4-2、CLK_MUX_STAT_CPU状态值说明
结合上表的设置值,设置完成后,MUX_MPLL_USER_SEL_C设置选择FINPLL那么26:24位的值应为001,而MUX_HPM_SEL选择MOUTAPLL,那么26:24位的值也应为001,同理,可分析出其他位的值,那么,此寄存器的值应为0x0111_0001下面来看看代码具体写法:
system_clock_init:
push {lr}@将链接寄存器压栈
ldr r0,=ELFIN_CLOCK_BASE @ELFIN_CLOCK_BASE=0x1003_0000 ,时钟寄存器的基地址
@CMU_CPU MUX / DIV
ldr r1,=0x0
ldr r2,=CLK_SRC_CPU_OFFSET@ CLK_SRC_CPU寄存器的偏移地址
str r1,[r0, r2]@ CLK_SRC_CPU寄存器的设置为0
ldr r2, =CLK_MUX_STAT_CPU_OFFSET@CLK_MUX_STAT_CPU寄存器的偏移地址
ldr r3, =0x01110001@需要比较的CLK_MUX_STAT_CPU设置值,即我们上面分析的值。
bl wait_mux_state @跳转到wait_mux_state等待寄存器值设置成功
wait_mux_state:
ldr r1, [r0, r2]@读取CLK_MUX_STAT_CPU寄存器的值
cmp r1, r3@ 将CLK_MUX_STAT_CPU寄存器的值和0x01110001进行比较
bne wait_mux_state@不等就再来一次
mov pc, lr@等了就返回。
@也可以用以下的方法来等待一定的时间
@/* wait ?us */
@ mov r1, #0x10000
@1: subs r1, r1, #1
@ bne 1b
好了,至此我们分析了如何设置 CPUMUX /DIV的时钟源选择的代码,但其分频比且没有进行设置,其实设置分频比的代码在后面设置完成LOCKOUT时间后才进行的,至于为什么这么安排我也不清楚,我们顺着代码分析就行,那这段代码还是在后面进行说明。
下面的代码是接着设置DMC,TOP,LEFTBUS,RIGHTBUS等寄存器,这里不做过多分析,以后我会给出详细源码,寄存器的值,针对我们板子是要进行必要修改的,重要的地方我还是会说明,如何查看手册就不做过多说明,接着说。
2、CMU_DMC MUX / DIV设置
这一段代码仅仅设置了其分频值,而其MUX值且没有设置,利用芯片启动的时的默认设置值,大家可以查看手册细细分析。这里参照tiny4412的Uboot进行了其DIV值设置。为什么取用这个值,我一时也还没有弄清楚,这里先留个问号,稍后再做说明。
@ CMU_DMC MUX / DIV add by zth
@CLK_DIV_DMC1_VAL --Tiny4412_val.h
@defined(CONFIG_CLK_BUS_DMC_100_200)->CLK_DIV_DMC1_VAL=0X00113113
@CLK_DIV_DMC1_VAL=0X00111113
ldr r1,=CLK_DIV_DMC0_VAL
ldr r2,=CLK_DIV_DMC0_OFFSET
str r1,[r0, r2]
ldr r1,=CLK_DIV_DMC1_VAL @CLK_DIV_DMC1_VAL=0x07071713
ldr r2,=CLK_DIV_DMC1_OFFSET
str r1,[r0, r2]
3、CMU_TOP MUX / DIV设置
CMU_TOP的MUX寄存器是CLK_SRC_TOP0和CLK_SRC_TOP1,他们的设置值分别由原值0X0变为0X00000110和0x01111000,分别利用比较其相应的状态寄存器CLK_MUX_STAT_TOP和CLK_MUX_STAT_TOP1的方法来确定值是否设置成功,当然也可以用等待一段时间的方法。
最后设置CLK_DIV_TOP寄存器,其值为0x01215474
@CMU_TOP MUX / DIV
@CLK_SRC_TOP0_VAL= 0x00000110
ldr r1,=CLK_SRC_TOP0_VAL
ldr r2,=CLK_SRC_TOP0_OFFSET
str r1,[r0, r2]
ldr r2, =CLK_MUX_STAT_TOP_OFFSET
@ldr r3, =0x11111111
ldr r3, =CLK_MUX_STAT_TOP_VAL @0x11111221
bl wait_mux_state
@CLK_SRC_TOP1_VAL= 0x01111000
ldr r1,=CLK_SRC_TOP1_VAL
ldr r2,=CLK_SRC_TOP1_OFFSET
str r1,[r0, r2]
ldr r2, =CLK_MUX_STAT_TOP1_OFFSET
@ldr r3, =0x01111110
ldr r3, =CLK_MUX_STAT_TOP1_VAL @0x02222110
bl wait_mux_state
@/* wait ?us */
@ mov r1, #0x10000
@1: subs r1, r1, #1
@ bne 1b
ldr r1,=CLK_DIV_TOP_VAL @0x01215474
ldr r2, =CLK_DIV_TOP_OFFSET
str r1,[r0, r2]
4、CMU_LEFTBUS MUX / DIV设置
CMU_LEFTBUSCMU的寄器设置和上述过程一样,这里不做过多说明,这里仅给出代码
ldr r1,=CLK_SRC_LEFTBUS_VAL
ldr r2,=CLK_SRC_LEFTBUS_OFFSET
str r1,[r0, r2]
ldr r2, =CLK_MUX_STAT_LEFTBUS_OFFSET
@ldr r3, =0x00000021
ldr r3, =CLK_MUX_STAT_LEFTBUS_VAL@0x00000021
bl wait_mux_state
ldr r1,=CLK_DIV_LEFRBUS_VAL
ldr r2,=CLK_DIV_LEFTBUS_OFFSET
str r1,[r0, r2]
5、CMU_RIGHTBUS MUX / DIV设置
CMU_LEFTBUS CMU的寄器设置和上述过程一样,这里不做过多说明,这里仅给出代码.
@ CMU_RIGHTBUS MUX / DIV
ldr r1,=CLK_SRC_RIGHTBUS_VAL
ldr r2,=CLK_SRC_RIGHTBUS_OFFSET
str r1,[r0, r2]
ldr r2, =CLK_MUX_STAT_RIGHTBUS_OFFSET
@ldr r3, =0x00000021
ldr r3, =CLK_MUX_STAT_RIGHTBUS_VAL @0x00000021
bl wait_mux_state
ldr r1,=CLK_DIV_RIGHTBUS_VAL
ldr r2,=CLK_DIV_RIGHTBUS_OFFSET
str r1,[r0, r2]
二、设置APLL/MPLL/EPLL/EPLL锁相环锁频时间
翻看手册,P371页,找到PLLCONTROL REGISTERS。
• (APLL_LOCK, R/W, Address =0x1004_0000)
• (MPLL_LOCK, R/W, Address =0x1004_0000)
• (EPLL_LOCK, R/W, Address =0x1003_0000)
• (VPLL_LOCK, R/W, Address =0xE010_0020)
表4-3、PLL寄存器锁定时间
这里出现了一个问题,APLL/MPLL/EPLL/VPLL的锁相环的时间是不一样的,而像S5PC100,频率为667MHz,他的A/M/E/HPLL的锁相环时间均是300us,这个时间一定要查芯片手册,如下截图的表3-4所示每一个寄存器的设置值,里面有完整的说明:
表4-4、xPLL_LOCK寄存器说明
参看上述说明,用如下宏定义先说明设置值
#if defined(CONFIG_CLK_ARM_800_APLL_800)
#define APLL_PDIV 0x3
#if defined(CONFIG_CLK_BUS_DMC_165_330)
#define MPLL_PDIV 0x5
#elifdefined(CONFIG_CLK_BUS_DMC_200_400)
#define MPLL_PDIV 0x3
#elif defined(CONFIG_CLK_BUS_DMC_220_440)
#define MPLL_PDIV 0x3
#endif
#define EPLL_PDIV 0x2
#define VPLL_PDIV 0x3
/* APLL_LOCK */
#define APLL_LOCK_VAL (APLL_PDIV * 270)/* 810*/
/* MPLL_LOCK */
#define MPLL_LOCK_VAL (MPLL_PDIV * 270)
/* EPLL_LOCK */
#define EPLL_LOCK_VAL (EPLL_PDIV * 3000)
/* VPLL_LOCK */
#define VPLL_LOCK_VAL (VPLL_PDIV * 3000)
接着进行设置,设置方法代码如下,代码的书写方式很明了,这里就不做过多说明。
@ Set PLL locktime
ldr r1,=APLL_LOCK_VAL
ldr r2,=APLL_LOCK_OFFSET
str r1,[r0, r2]
ldr r1,=MPLL_LOCK_VAL
ldr r2,=MPLL_LOCK_OFFSET
str r1,[r0, r2]
ldr r1,=EPLL_LOCK_VAL
ldr r2,=EPLL_LOCK_OFFSET
str r1,[r0, r2]
ldr r1,=VPLL_LOCK_VAL
ldr r2,=VPLL_LOCK_OFFSET
str r1,[r0, r2]
在这段代码后才是设置MCU_CPU的分频比的代码。设置值可以查看
P585 页7.9.1.136CLK_DIV_CPU0和7.9.1.137 CLK_DIV_CPU1页的寄存器列表。
由于zthtiny4412_val.h中可以设置其值,这里修改设置的值如下所示,这两个值的设置得以照APLL后的频来决定。不能随便设置,APLL设置好后,即可以知道APLL频率,此后根据CLK_DIV_CPU0和CLK_DIV_CPU1的说明来计算出所需的值进行设置即可,zthtiny4412_val.h中有设置好几类时钟频率的值,如APLL为800MHZ,1000MHZ时的值不一样。
@Set MCU_CPU Ratio
ldr r1,=CLK_DIV_CPU0_VAL
ldr r2,=CLK_DIV_CPU0_OFFSET
str r1,[r0, r2]
ldr r1,=CLK_DIV_CPU1_VAL
ldr r2,=CLK_DIV_CPU1_OFFSET
str r1,[r0, r2]
三、下面的代码就是开始倍频
1、倍频APLL
这个倍频值需根据需求参考手册来时行设置。这里有不同频进行设置,每一个设置值不做过多说明,仅仅说明一下参考位置,设置值P,M,S可以设置寄存器APLL_CON0,如下图所示,其中,其上电初始化后,如果外部的时钟晶振是24MHZ的话,那么其频率为800MHZ。但需要注意的是设置的输出频率范围在21.9MHZ到1400MHZ
上一篇:第三章、Tiny4412 U-BOOT移植三 时钟设置
下一篇:第五章、Tiny4412 U-BOOT移植五 Nand Flash原理
推荐阅读最新更新时间:2024-11-03 08:50
设计资源 培训 开发板 精华推荐
- 使用 ON Semiconductor 的 CS3972 的参考设计
- DC675A-A,演示电路采用 LT1568CGN,4 阶窄带通滤波器
- 555电路 1810300305
- 使用 Infineon Technologies AG 的 IRU3137 的参考设计
- LT3761EMSE-1 升压 LED 驱动器的典型应用电路,具有输出短路保护和外部驱动 PWM
- LTC3547EDDB 演示板,双单片同步。降压转换器
- SG117 1.5A 三端可调电压调节器用于温度补偿铅酸电池充电器的典型应用
- 扩展电路
- 使用 Analog Devices 的 LTC4302-1 的参考设计
- 使用 NovTech, Inc 的 NOVSOMCV6FSX2-SL-31E-F-C 的参考设计