ARM cortex a 之时钟系统3
2016-08-23 15:12
232 查看
//这是整理的汇编代码,我们一步步分析一下。
// 时钟控制器基地址
#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 //跳转回主程序
//粗略的设置我们的各种寄存器已经完成了
//总共只使用了五个寄存器,至于以后每个特殊功能寄存器需要的时钟我们再以后学习的时候再各个设置。
// 时钟控制器基地址
#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 //跳转回主程序
//粗略的设置我们的各种寄存器已经完成了
//总共只使用了五个寄存器,至于以后每个特殊功能寄存器需要的时钟我们再以后学习的时候再各个设置。
相关文章推荐
- ARM cortex a 之时钟系统1
- ARM cortex a 之时钟系统1
- ARM cortex a 之时钟系统3
- STM32F系列ARM Cortex-M3核微控制器基础之系统时钟二
- STM32F系列ARM Cortex-M3核微控制器基础之系统时钟一
- ARM cortex a 之时钟系统1
- STM32F系列ARM Cortex_M3核微控制器基础之系统时钟三
- ARM cortex a 之时钟系统2
- ARM cortex a 之时钟系统2
- ARM Linux系统的时钟机制
- 用DNW工具在ARM-Cortex-A8开发板烧写Linux系统详细讲解
- ARM Linux系统的时钟机制
- 【嵌入式系统】ARM Cortex-A8体系结构
- [时钟管理] arm 时间系统 1
- ARM裸机之系统时钟
- [时钟管理] arm 时间系统 3
- [时钟管理] arm 时间系统 2
- ARM Linux系统的时钟机制
- ARM裸机编程系列----系统时钟与定时器
- ARM学习笔记--系统时钟和定时器