上篇中已经详细分析了6410时钟系统的结构,现在就介绍下几个与时钟设置相关的寄存器。
1.APLL_LOCK、MPLL_LOCK、EPLL_LOCK
这三个寄存器的低十六位分别表示APLL、MPLL、EPLL这三个锁相环"锁相"所需的时间(周期数),当锁相环的输入或设置改变后,只有经历这么多个周期数后,才让锁相环有输出,这里一般保留默认值(同时也是允许的最大值)0xffff,这个数大可以保证锁相环始终能有稳定的输出。
2.APLL_CON、MPLL_CON、EPLL_CON0、EPLL_CON1
这几个寄存器包含了三个PLL的配置信息。这里只介绍APLL_CON和MPLL_CON。
APLL_CON/MPLL_CON寄存器中重要的几个位域:[31]ENABLE、[25:16]MDIV、[13:8]PDIV、[2:0]SDIV。其中ENABLE位控制相应锁相环的使能,另外三个位域负责产生输出时钟。
锁相环输出时钟=晶振时钟*MDIV/(PDIV*(2^SDIV))。
其他的注意事项和说明在上图中已标出。
3.CLK_DIV0、CLK_DIV1、CLK_DIV2
这些都是为外设进行分频的寄存器。对于设置内核时钟和AHB、APB的总线时钟来说,我们只需要了解CLK_DIV0的几个位域即可。
这四个位域的作用在上篇中已经介绍过了,这里不再赘述。
4.CLK_SRC
这个寄存器是为各个时钟选择源。我们只用它的低两位来为MOUT(MPLL)和MOUT(APLL)来选择源。当对应位为0时,表示选择FIN作为源,相当于没有用到相应的PLL;当对应位为1时,表示选择FOUT作为源,PLL就起到了作用。
(忘了MOUT(MPLL)和MOUT(APLL)分别指什么??参考上篇中的Figure3.5或Figure3.4,这两个都用小红框圈着,找找看)
5.OTHERS
这个寄存器我们只需要用到下面几个位域:
SYNCMODE(此处有过改动,原来写的是SYNCMUXSEL,见第一条评论)就是选择同步模式还是异步模式的。其他两个位域在三星提供的User Manaul里并没有过多的说明,我现在还不是特别清楚他们的作用。我是分析了Uboot1.1.6中的代码后才知道几个位的用法。下面是Uboot1.1.6中board\samsung\smdk6410目录下的lowlevel_init.S文件中与OTHERS寄存器的这些位相关的设置部分:
(下面的注释是笔者自己加进去的,Uboot源码中并没有)
#ifdef CONFIG_SYNC_MODE ldr r1, [r0, #OTHERS_OFFSET] mov r2, #0x40 orr r1, r1, r2 str r1, [r0, #OTHERS_OFFSET] ;向SYNCMUXSEL位写1
nop nop nop nop nop ;等待几个时钟 ldr r2, =0x80 orr r1, r1, r2 str r1, [r0, #OTHERS_OFFSET] ;向SYNCMODE为写1 check_syncack: ldr r1, [r0, #OTHERS_OFFSET] ldr r2, =0xf00 and r1, r1, r2 cmp r1, #0xf00 bne check_syncack ;然后等待SYNCACK位域变成1111(即0xf)
;------------上面是同步模式下的操作方式,下面是异步模式下的操作方式。----------------------------
#else /* ASYNC Mode */ nop nop nop nop nop ldr r1, [r0, #OTHERS_OFFSET] bic r1, r1, #0xC0 orr r1, r1, #0x40 str r1, [r0, #OTHERS_OFFSET] ;先将SYNCMODE位清零
wait_for_async: ldr r1, [r0, #OTHERS_OFFSET] and r1, r1, #0xf00 cmp r1, #0x0 bne wait_for_async ;等待SYNCACK位域变为0
ldr r1, [r0, #OTHERS_OFFSET] bic r1, r1, #0x40 str r1, [r0, #OTHERS_OFFSET] ;将SYNCMUXSEL位清零
我们编程的时候也按着这个顺序来即可。(路过的大神如果哪位知道哪里有关于这几个位的详细说明请一定要留上一言,为以后可能经过这里的新手们提供点帮助)
时钟这块重要的寄存器就是这几个。下篇中直接贴出C源码供路过的菜鸟们参考。