心脏作为处理器最重要的东西,没有心脏,那么一切将无从谈起。
1、晶振
玩过单片机对这个名词肯定不陌生,所有的MCU都是需要晶振来提供工作时钟的。ARM也不例外。s3c2440外接12MHZ晶振,这个因设备而异。一般在板子上有注明。这一章绝非仅仅谈晶振,而是要搞明白,soc利用晶振产生了哪些时钟,供芯片使用。
2、ARM时钟体系
还是从芯片手册里面找。有点复杂哈,哈哈哈!
没事,从根源找起,这些时钟体系,都是由晶振倍频而来,再分配给各种外设。
OSC就是晶振,它经过一个多路选择器,再经过MPLL倍频,得到FCLK,再分频得到HCLK和PCLK,FCLK给芯片用,HCLK给高速设备用,PCLK给普通外设用。
Ⅰ、化繁为简
上面的时钟图太复杂了,不够简明。这样就清楚多了
Ⅱ、疑问重重
带着问题学习,效果总是最好的。上面提到FCLK、HCLK、PCLK,它们的工作频率是多少,又是怎样设置的。要搞清楚这两点,只能从芯片手册入手了。
在芯片介绍时说明了芯片的工作频率。
倍频参数一般需要找到与它相关的寄存器,如何设置
找到MPLL的寄存器,下面还有描述,如果输入是12MHZ,输出为400MHZ时,MDIV设置为0x5c,PDIV设置为1,SDIV设置为1,?,这就好办了嘛
再往下找,发现了这个寄存器,它就是设置HCLK,PCLK频率的
似乎已经知道怎样设置了,再找找看,有没有什么需要注意的,手册有个注意点,如果CPU不设置为异步模式,即使设置了上诉的寄存器,也只能使用HCLK频率
翻看手册,其他就关于模式的设置之类的,还有一个基本的框图,这对于以后编程有很大的帮助,特别是内存操作时。
还差一点,我怎么知道我的板子时钟源就是晶振呢,这里这么多选择
打开原理图,?
前面叙述的orr r0,r0,#R1_nF:OR:R1_iA应该设置为多少,最后一个问题也解决了,开始编程吧,
参考手册“ARM920T(Rev 1)Technical Reference Manual”,有如下内容:
Ⅲ、编程
先设置为400MHZ
ldr r0, =0x4C000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1, [r0]
配置HCLK、PCLK
/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8 */
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0]
完整代码
.text
.global _start
_start:
/* 关闭看门狗 */
ldr r0, =0x53000000
ldr r1, =0
str r1, [r0]
/* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
/* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
ldr r0, =0x4C000000
ldr r1, =0xFFFFFFFF
str r1, [r0]
/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8 */
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0]
/* 设置CPU工作于异步模式 */
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
/* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0)
* m = MDIV+8 = 92+8=100
* p = PDIV+2 = 1+2 = 3
* s = SDIV = 1
* FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
*/
ldr r0, =0x4C000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1, [r0]
/* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
* 然后CPU工作于新的频率FCLK
*/
/* 设置内存: sp 栈 */
/* 分辨是nor/nand启动
* 写0到0地址, 再读出来
* 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
* 否则就是nor启动
*/
mov r1, #0
ldr r0, [r1] /* 读出原来的值备份 */
str r1, [r1] /* 0->[0] */
ldr r2, [r1] /* r2=[0] */
cmp r1, r2 /* r1==r2? 如果相等表示是NAND启动 */
ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
moveq sp, #4096 /* nand启动 */
streq r0, [r1] /* 恢复原来的值 */
bl main
halt:
b halt