大部分摘抄自韦老师博客https://blog.csdn.net/thisway_diy/article/details/79389009
S3C2440是System On Chip(SOC),在芯片上不仅仅有CPU还有一堆外设。
至于有哪些外设,可以查看参考手册。在S3C2440参考手册的第一章PRODUCT OVERVIEW里面有个BLOCK DIAGRAM图:
可以把该图分为上中下三块,上面的是与CPU密切相关的,工作于FCLK;中间的一些对性能要求较高的设备,像LCD显示、相机等,在AHB BUS,H即为High,高速之意,工作于HCLK;下面的是一些对性能要求不那么高的低速设备,在APB BUS,P即为Peripheral之意,工作在PCLK。
在参考手册的特性里介绍了S3C2440的工作频率:
CPU工作于FCLK,最大400MHZ.
高速设备工作于HCLK(如LCD控制器,USB Host) 最大136MHZ
慢速设备工作于PCLK(如iic等各种串口,ADC,IO,USBdevice等大部分常见的) ,最大68MHZ.
2440时钟源有两个:晶振或一个引脚输入。有一个选择器控制(选择器也是有两个引脚控制选择哪个方式)
韦板子是12M晶振。作为时钟源产生12MHz的频率,经过SOC的PLL(锁相环)倍频产生Fclk、Hclk、Pclk。
CLKCNTL之后生成FCLK,经过HDIVN和PDIVN分频得到HCLK和PCLK.
FCLK传给CPU,图中ARM920T指的就是cpu!!!!
在该图的左上角,晶振和一个外部时钟接在一个选择器上,这个选择器通过OM[3:2]的值来决定选择哪个时钟源。然后生成的MPLL(Main PLL)和UPLL(USB PLL),MPLL直接提供给FCLK,通过HDIVN分频给HCLK,通过PDIVN分频给PCLK,再传给下面的各个设备。
简图就是:
上电启动,时钟过程分析:
上电时,PLL没被启动。FCLK即等于外部输入的时钟,称为Fin。若要提高系统时钟,需要软件来启动PLL。
芯片上电复位引脚需要一段时间低电平才能置高电平,为了等待电源稳定再执行复位。
这一小段时间由一个专用芯片完成,韦板子用了IMP811T,一上电的时候nRESET引脚是低电平,过一会才是高电平。
1).上电几毫秒后,晶振(OSC)输出稳定,FCLK = Fin(晶振频率),nRESET信号恢复高电平后,CPU开始执行指令
2).在nRESET信号的上升沿,引脚OM[3:2]的电平被内部电路捕获,根据OM[3:2]的值,设置FCLK
3).在程序开头启用MPLL**,设置MPLL的几个寄存器后**,需要等待一段时间(Lock Time),MPLL的输出才能稳定。在这段时间(Lock Time)内,FCLK停振,CPU停止工作。Lock Time的长短有寄存器LOCKTIME设定
4).Lock Time后MPLL输出正常,CPU工作在新的FCLK下。
编程提高运行时钟
(补:貌似,刚上电的时候三个CLK都是12MHZ,代码放在nor,要启动了,这时候nor的时钟信号就是HCLK,12mhz。)
时钟配置代码都在s汇编文件中进行(也就是main之前的那个start中),因为涉及到的协处理器命令是汇编给出的。
怎么编程控制MPLL、HDIV、PDIV,FCLK=400MHz,HCLK=100MHz,PLCK=50MHz?
需要设置MPLLCON的FCLK=400MHz,设置CLKDIVN的HCLK=FCLK/4,PCLK=FCLK/8。
先看2440时钟配置需要的寄存器:
①先配置FCLK=400MHz,另外两个HCLK/PLCK都是从这个基础上得到的。
在手册的PLL VALUE SELECTION TABLE里列出了常见情况PLL的设置,我们输入的是晶振的12MHz,输出需要400MHz,因此根据表格需要设置 MDIV=92(0x5C),PDIV=1,SDIV=1;
/* 设置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就会立马自己做调整了。
②按照寄存器的值从FCLK分频得到HCLK/PLCK
根据计算得到这个寄存器的配置:
/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8 */
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0]
手册244页有注意事项,如果HDIVN不是0,需要设置异步模式,否则即使设置FCLK为400M,也会使用HCLK给CPU工作使用的。
设置CPU工作于异步模式代码如下:
(这几个指令说是不需要看,手册直接给出的)
(arm芯片除了有一个CPU还有很多协处理器,这指令是读写协处理器的,不用深究)
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
完整的start.S:
.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