//这是整理的汇编代码,我们一步步分析一下。
// 时钟控制器基地址
#define ELFIN_CLOCK_POWER_BASE 0xE0100000
//我们使用的基地址的原因是所有时钟寄存器的地址都是在这个基地址上偏移得到的。
//下面就是各个寄存器的的偏移地址了
// 下面是时钟相关的寄存器相对时钟控制器基地址的偏移值,里面有锁相环锁定周期寄存器,
//锁相环控制寄存器,时钟源控制寄存器,时钟源开关,时钟分频器寄存器。
#define APLL_LOCK_OFFSET 0x00
#define MPLL_LOCK_OFFSET 0x08
#define APLL_CON0_OFFSET 0x100
#define APLL_CON1_OFFSET 0x104
#define MPLL_CON_OFFSET 0x108
#define CLK_SRC0_OFFSET 0x200
#define CLK_SRC1_OFFSET 0x204
#define CLK_SRC2_OFFSET 0x208
#define CLK_SRC3_OFFSET 0x20c
#define CLK_SRC4_OFFSET 0x210
#define CLK_SRC5_OFFSET 0x214
#define CLK_SRC6_OFFSET 0x218
#define CLK_SRC_MASK0_OFFSET 0x280
#define CLK_SRC_MASK1_OFFSET 0x284
#define CLK_DIV0_OFFSET 0x300
#define CLK_DIV1_OFFSET 0x304
#define CLK_DIV2_OFFSET 0x308
#define CLK_DIV3_OFFSET 0x30c
#define CLK_DIV4_OFFSET 0x310
#define CLK_DIV5_OFFSET 0x314
#define CLK_DIV6_OFFSET 0x318
#define CLK_DIV7_OFFSET 0x31c
#define CLK_DIV0_MASK 0x7fffffff
// 这些MDIV、PDIV、SDIV的各个配置值都是查数据手册中典型时钟配置值的推荐配置得来的。
// 这些配置值是三星推荐的,因此工作最稳定。我们只需要知道它们是怎么得来的就好,毕竟
// 直接用人家配置的值最稳定。
#define APLL_MDIV 0x7d // 125
#define APLL_PDIV 0x3
#define APLL_SDIV 0x1
#define MPLL_MDIV 0x29b // 667
#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)
.global clock_init
clock_init:
ldr r0, =ELFIN_CLOCK_POWER_BASE
// 1 设置各种时钟开关,暂时绕过PLL,直接使用24MHz的频率作为主频
ldr r1, =0x0
// CLK_SRC选择时钟源0,CLOCK SRC寄存器主要是设置MUX开关的
str r1, [r0, #CLK_SRC0_OFFSET]
// 2 设置锁定时间,使用默认值即可
// 设置PLL后,时钟从Fin提升到目标频率时,需要一定的时间,即锁定时间
ldr r1, =0x0000FFFF
str r1, [r0, #APLL_LOCK_OFFSET]
str r1, [r0, #MPLL_LOCK_OFFSET]
// 3 设置分频,设置从PLL里出来的时钟如何分频得到最高时钟。
ldr r1, [r0, #CLK_DIV0_OFFSET] //清除bit[0~31]
ldr r2, =CLK_DIV0_MASK //0x7fffffff
bic r1, r1, r2 //把r1中的这些位清零(说实话我咋觉得这两步是废话呢,晕蛋了,有谁给我解释一下)
ldr r2, =0x14131440 //
//这些位的作用就是各个分频,对照示意图和表格就能知道,这里不赘述了
orr r1, r1, r2 //把r1中的这些位,置1,于是 CLK_DIV0_OFFSET就是0x14131440了(上两步难道真是废话?!)
str r1, [r0, #CLK_DIV0_OFFSET]
// 4 设置PLL的倍频系数
// FOUT = MDIV*FIN/(PDIV*2^(SDIV-1))=0x7d*24/(0x3*2^(1-1))=1000 MHz
//上面这玩意是一个计算频率的公式
ldr r1, =APLL_VAL
str r1, [r0, #APLL_CON0_OFFSET]
// FOUT = MDIV*FIN/(PDIV*2^SDIV)=0x29b*24/(0xc*2^1)= 667 MHz
ldr r1, =MPLL_VAL
str r1, [r0, #MPLL_CON_OFFSET]
//我们只设置了APLL和MPLL,因为在基础设置中只关系到这两个锁相环。
// 5 设置各种时钟开关,启动PLL,时钟初始化完毕
ldr r1, [r0, #CLK_SRC0_OFFSET]
ldr r2, =0x10001111
orr r1, r1, r2
str r1, [r0, #CLK_SRC0_OFFSET]
mov pc, lr //跳转回主程序
//粗略的设置我们的各种寄存器已经完成了
//总共只使用了五个寄存器,至于以后每个特殊功能寄存器需要的时钟我们再以后学习的时候再各个设置。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。