历史上的今天
返回首页

历史上的今天

今天是:2024年12月09日(星期一)

正在发生

2021年12月09日 | 第四章、TIny4412 U-BOOT移植四 配置时钟频率源码分析

2021-12-09 来源:eefocus

上篇讲了配置时钟的原理,今天就结合源码具体分析一下。在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

推荐阅读

史海拾趣

Autonics公司的发展小趣事

上世纪60、70年代,韩国经济蓬勃发展,工业自动化需求迅速增长,但传感器与控制仪表的国内市场仍是一片空白。Autonics的创始人看到了这个巨大的市场机会,于1977年创立了Autonics公司。公司初创时期,面临着资金短缺、技术落后等诸多挑战,但创始人凭借着对技术的执着追求和对市场的敏锐洞察,带领公司逐步走上正轨。

Herotek Inc公司的发展小趣事

随着半导体技术的飞速发展,Henkel公司紧跟行业趋势,不断研发适用于半导体封装的高性能粘合剂。其研发的粘合剂产品不仅满足了半导体封装过程中对于高精度、高可靠性的要求,还显著提升了封装效率。例如,Henkel的某些粘合剂产品能够在极端温度条件下保持稳定的性能,确保半导体器件在各种工作环境中都能正常运行。这一技术突破为Henkel在半导体封装市场赢得了广泛的认可。

APC (APC by Schneider Electric)公司的发展小趣事

APC的产品和服务在全球范围内赢得了广泛认可。其InfraStruXure产品线因其集成式的电力、制冷、机架、管理和服务实现了一种开放、具有适应性且集成化的解决方案,赢得了近20个奖项。此外,APC还因其卓越的产品和业务表现,在多个年份赢得了全球100多个奖项。这些奖项不仅证明了APC在电子行业中的领先地位,也反映了其对于创新和质量的不懈追求。

Anderson Electronics Inc公司的发展小趣事

随着公司规模的扩大和产品线的丰富,Anderson Electronics Inc公司开始积极拓展市场。公司通过与各大电子产品零售商建立合作关系,将产品销往全国各地。同时,公司还加大了品牌宣传力度,通过广告、展会等多种渠道提升品牌知名度和影响力。在市场拓展的过程中,公司始终坚持质量第一的原则,以优质的产品和服务赢得了客户的信赖和支持。

苏州锋驰(Feng)公司的发展小趣事
稳流器通常通过将多余电压转化为热量来维持恒定的电流输出,因此存在一定的能量消耗。
胜利(VICTOR)公司的发展小趣事

随着产品的不断升级和市场的扩大,胜利公司开始将目光投向国际市场。1980年代,VICTOR品牌成功进入欧美市场,凭借优质的产品和合理的价格,迅速赢得了消费者的认可。公司还积极参加国际赛事,通过赞助等方式提升品牌知名度。

问答坊 | AI 解惑

液晶为什么不显示

公司让我搞一个项目,没有办法,必需学单片机子,我刚刚学习单片机,想用1621驱动一个段式液晶,找了很多程序资料,也写了四天了,可就是不显示,请高手指点一下!看是我哪里出了问题,谢谢了!字段式的,用在计数上; //1621引线:CS:PD4  ...…

查看全部问答>

100414Digital Motor Control Software Library (spru485a

100414Digital Motor Control Software Library (spru485a…

查看全部问答>

求助,想不通快要崩溃了

新手求教。(芯片ep9315,环境:wince5.0) 我的主程序里有三个线程在跑:线程1做好了,是串口指令的收发;线程2,3还没写好,一直在死循环,准备用于ad数据的采集和储存。 平时串口的收发正常,当我创建一个全局变量a(其他亦如此)时,会出现串 ...…

查看全部问答>

流明学习笔记之七控制IO网络例程成功

这两天看下例程的网络部分哈   试了好久没成功,原因在我家电脑是UHB,那种集线器地,所以不能直接配DHCP,而开发板例是自动测动态IP地,于是我想了个熊招效果不错,不敢独享拿出分享   我由于网线和两台电脑都集中在集线器上,而集 ...…

查看全部问答>

uip-telnet控制LED/PWM

最近考试太忙了,好久没来更新了,今天有点时间,学习了uip协议,看了下官方给的范例HTTP网页访问,论坛里也有位大哥写了个TCP发送的流程。我看了下uip带了范例,有个telnet的范例,比较有意思。拿来修改下实现对开发板的一些控制,有点像lwip-io范 ...…

查看全部问答>

头文件问题

我已经在源文件里面写了#include\\"main.h\\" ,而且已经建立了\\"main.h\\",为什么在工程文件列表中没有显示main.h啊?是什么原因阿?…

查看全部问答>

关于以.afx后缀名的文件是什么

关于以.afx后缀名的文件是什么文件,ADS 1.2和keil 3能够生成以afx为后缀的文件吗?.afx的文件可以通过串口或者jtag口烧写到LPC1758的flash中运行吗?望高手能够赐教,万分感谢!!!…

查看全部问答>

下面的VHDL中时钟clk是变量,不是输入量,结果出现错误?为什么啊?怎么编啊?

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. --library U ...…

查看全部问答>

明天TI杯正式开始,亲们准备好了吗?

明天TI杯正式开始,我准备裸赛了。。。。…

查看全部问答>

【无线节点】PCB板

先传一个,剩下的再检查下后马上上传…

查看全部问答>