s5pv210 时钟配置
clock.c
// 时钟控制器基地址
#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 // 这些M、P、S的配置值都是查数据手册中典型时钟配置值的推荐配置得来的。 #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) //重要寄存器 #define REG_CLK_SRC0 (ELFIN_CLOCK_POWER_BASE + CLK_SRC0_OFFSET) #define REG_APLL_LOCK (ELFIN_CLOCK_POWER_BASE + APLL_LOCK_OFFSET) #define REG_MPLL_LOCK (ELFIN_CLOCK_POWER_BASE + MPLL_LOCK_OFFSET) #define REG_CLK_DIV0 (ELFIN_CLOCK_POWER_BASE + CLK_DIV0_OFFSET) #define REG_APLL_CON0 (ELFIN_CLOCK_POWER_BASE + APLL_CON0_OFFSET) #define REG_MPLL_CON (ELFIN_CLOCK_POWER_BASE + MPLL_CON_OFFSET) #define rREG_CLK_SRC0 (*(volatile unsigned int *)REG_CLK_SRC0) #define rREG_APLL_LOCK (*(volatile unsigned int *)REG_APLL_LOCK) #define rREG_MPLL_LOCK (*(volatile unsigned int *)REG_MPLL_LOCK) #define rREG_CLK_DIV0 (*(volatile unsigned int *)REG_CLK_DIV0) #define rREG_APLL_CON0 (*(volatile unsigned int *)REG_APLL_CON0) #define rREG_MPLL_CON (*(volatile unsigned int *)REG_MPLL_CON) void clock_init(void) { // 1 设置各种时钟开关,暂时不使用PLL rREG_CLK_SRC0 = 0x0; // 2 设置锁定时间,使用默认值即可 // 设置PLL后,时钟从Fin提升到目标频率时,需要一定的时间,即锁定时间 rREG_APLL_LOCK = 0x0000ffff; rREG_MPLL_LOCK = 0x0000ffff; // 3 设置分频 // 清bit[0~31] rREG_CLK_DIV0 = 0x14131440; // 4 设置PLL // FOUT = MDIV*FIN/(PDIV*2^(SDIV-1))=0x7d*24/(0x3*2^(1-1))=1000 MHz rREG_APLL_CON0 = APLL_VAL; // FOUT = MDIV*FIN/(PDIV*2^SDIV)=0x29b*24/(0xc*2^1)= 667 MHz rREG_MPLL_CON = MPLL_VAL; // 5 设置各种时钟开关,使用PLL rREG_CLK_SRC0 = 0x10001111; }
重要的寄存器有 :
xPLL_CON:主要用来打开/关闭PLL电路,设置PLL的倍频参数,查看PLL锁定状态等 即 倍频到多少
CLK_DIVn:各模块的分频器参数配置 即 分频到多少
CLK_SRC:是用来设置时钟来源的,对应时钟框图中的MUX开关 即 走哪一路
xPLL_LOCK:主要控制PLL锁定周期
CLK_SRC_MASK:决定MUX开关n选1后是否能继续通过。
start.S
#define WTCON 0xE2700000 #define SVC_STACK 0xd0037d80 .global _start _start: // 第1步:关看门狗 ldr r0, =WTCON ldr r1, =0x0 str r1, [r0] // 第2步:初始化时钟 bl clock_init // 第3步:设置SVC栈 ldr sp, =SVC_STACK // 第4步:开/关icache mrc p15,0,r0,c1,c0,0; // 读出cp15的c1到r0中 //bic r0, r0, #(1<<12) // bit12 置0 关icache orr r0, r0, #(1<<12) // bit12 置1 开icache mcr p15,0,r0,c1,c0,0; bl led_blink b .