//这是整理的汇编代码,我们一步步分析一下。


// 时钟控制器基地址

#define ELFIN_CLOCK_POWER_BASE0xE0100000

//我们使用的基地址的原因是所有时钟寄存器的地址都是在这个基地址上偏移得到的。

//下面就是各个寄存器的的偏移地址了


// 下面是时钟相关的寄存器相对时钟控制器基地址的偏移值,里面有锁相环锁定周期寄存器,

//锁相环控制寄存器,时钟源控制寄存器,时钟源开关,时钟分频器寄存器。

#define APLL_LOCK_OFFSET0x00

#define MPLL_LOCK_OFFSET0x08


#define APLL_CON0_OFFSET0x100

#define APLL_CON1_OFFSET0x104

#define MPLL_CON_OFFSET0x108


#define CLK_SRC0_OFFSET0x200

#define CLK_SRC1_OFFSET0x204

#define CLK_SRC2_OFFSET0x208

#define CLK_SRC3_OFFSET0x20c

#define CLK_SRC4_OFFSET0x210

#define CLK_SRC5_OFFSET0x214

#define CLK_SRC6_OFFSET0x218

#define CLK_SRC_MASK0_OFFSET0x280

#define CLK_SRC_MASK1_OFFSET0x284


#define CLK_DIV0_OFFSET0x300

#define CLK_DIV1_OFFSET0x304

#define CLK_DIV2_OFFSET0x308

#define CLK_DIV3_OFFSET0x30c

#define CLK_DIV4_OFFSET0x310

#define CLK_DIV5_OFFSET0x314

#define CLK_DIV6_OFFSET0x318

#define CLK_DIV7_OFFSET0x31c


#define CLK_DIV0_MASK0x7fffffff


// 这些MDIV、PDIV、SDIV的各个配置值都是查数据手册中典型时钟配置值的推荐配置得来的。

// 这些配置值是三星推荐的,因此工作最稳定。我们只需要知道它们是怎么得来的就好,毕竟

// 直接用人家配置的值最稳定。

#define APLL_MDIV 0x7d// 125

#define APLL_PDIV 0x3

#define APLL_SDIV 0x1


#define MPLL_MDIV0x29b// 667

#define MPLL_PDIV0xc

#define MPLL_SDIV0x1


#define set_pll(mdiv, pdiv, sdiv)(1<<31 | mdiv<<16 | pdiv<<8 | sdiv)

#define APLL_VALset_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV)

#define MPLL_VALset_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV)



.global clock_init

clock_init:

ldrr0, =ELFIN_CLOCK_POWER_BASE


// 1 设置各种时钟开关,暂时绕过PLL,直接使用24MHz的频率作为主频

ldrr1, =0x0

// CLK_SRC选择时钟源0,CLOCK SRC寄存器主要是设置MUX开关的

strr1, [r0, #CLK_SRC0_OFFSET]


// 2 设置锁定时间,使用默认值即可

// 设置PLL后,时钟从Fin提升到目标频率时,需要一定的时间,即锁定时间

ldrr1,=0x0000FFFF

strr1,[r0, #APLL_LOCK_OFFSET]

str r1, [r0, #MPLL_LOCK_OFFSET]


// 3 设置分频,设置从PLL里出来的时钟如何分频得到最高时钟。

ldr r1, [r0, #CLK_DIV0_OFFSET] //清除bit[0~31]

ldrr2, =CLK_DIV0_MASK //0x7fffffff

bicr1, r1, r2 //把r1中的这些位清零(说实话我咋觉得这两步是废话呢,晕蛋了,有谁给我解释一下)

ldrr2, =0x14131440 //

//这些位的作用就是各个分频,对照示意图和表格就能知道,这里不赘述了

orrr1, r1, r2 //把r1中的这些位,置1,于是CLK_DIV0_OFFSET就是0x14131440了(上两步难道真是废话?!)

strr1, [r0, #CLK_DIV0_OFFSET]


// 4 设置PLL的倍频系数

// FOUT = MDIV*FIN/(PDIV*2^(SDIV-1))=0x7d*24/(0x3*2^(1-1))=1000 MHz

//上面这玩意是一个计算频率的公式

ldrr1, =APLL_VAL

strr1, [r0, #APLL_CON0_OFFSET]

// FOUT = MDIV*FIN/(PDIV*2^SDIV)=0x29b*24/(0xc*2^1)= 667 MHz

ldrr1, =MPLL_VAL

strr1, [r0, #MPLL_CON_OFFSET]

//我们只设置了APLL和MPLL,因为在基础设置中只关系到这两个锁相环。

// 5 设置各种时钟开关,启动PLL,时钟初始化完毕

ldrr1, [r0, #CLK_SRC0_OFFSET]

ldrr2, =0x10001111

orrr1, r1, r2

strr1, [r0, #CLK_SRC0_OFFSET]


movpc, lr //跳转回主程序

//粗略的设置我们的各种寄存器已经完成了

//总共只使用了五个寄存器,至于以后每个特殊功能寄存器需要的时钟我们再以后学习的时候再各个设置。