1、芯片结构
查看芯片手册,把上图分成三部分:
上部分是与CPU密切相关,工作于FCLOCK
中部分是AHB总线(H是high的意思,高速总线),工作于HCLOCK
下部分是APB总线(P是perpheral,外设总线),工作与PCLOCK
根据手册P34可知工作频率:
Operating Frequency
• Fclk Up to 400MHz
• Hclk Up to 136MHz
• Pclk Up to 68MHz
S3C2440的时钟源是12M的晶振,那么是怎么得到这么高HZ?
是通过PLL(锁相环)达到这么高频率的。
2、 ARM芯片时钟体系——PLL(锁相环)怎么转换高频率?
手册第七章P238找到上图,我们分析下图片的内容
我们可以知道芯片的是时钟源有两个:
12MHZ晶振、EXTCLK引脚输入的时钟
通过选择器来选择时钟源:
打开手册所搜下OM[3:2] (P237),查看下如何配置引脚来选择时钟源的:
我们可以知道,有两个PLL:MPLL(Main PLL)、UPLL(USB PLL)
MPLL是生产时钟给CPU用的的,UPL是生产时钟给USB用的。
我们查看下开发板电路图,OM1 OM2 OM3 都是接地,所以开发板是OM0,Main Clock和USB Clock都是由晶振提供时钟源:
根据分析Clock generator block diagram,我们可以知道:
晶振通过MPLL,产生高频率FCLK,然后提供给CPU使用;通过HDIVN分频(控制P M S的数值进行分频)给HCLK,通过PDIVN分频(控制P M S的数值进行分频)产生给HCLK、PCLK,再传给下面的各个设备,如下图所示。
怎么编程:控制MPLL HDIV PDIV?肯定是需要设置一些寄存器的
我们先了解下 PLL运行过程:
3、上电复位时序分析
P241
一开始上电,复位引脚拉低,等到电源稳定后,复位芯片拉高,可以查看下原理图复位芯片:n表示输出低电平
4、编写程序设置运行时钟
(1)配置寄存器
假设:
FCLK = 400MHZ
HCLK = 100MHZ
PCLK = 50MHZ
1)MPLLCON寄存器
公式:P255
Mpll = (2 * m * Fin) / (p * 2s)
m = (MDIV + 8), p = (PDIV + 2), s = SDIV
m = 92+8 = 100
p = 1+2 = 3
s = 1
Mpll = (2 * 100 * 12)/ (3 * 21) = 400M
MDIV引脚为 92<<12
PDIV引脚为 1<<4
SDIV引脚为 1<<0
因此 MPLLCON = (92<<12) | (1<<4) | (1<<0)
2)设置CLKDIVN寄存器的HDIVN和PDIVN引脚
因此CLKDIVN = 0101 = 0x5
3)注意事项
P244
HDIVN 引脚不为0, 则需要将CPU的快速总线模式改成异步总线模式,否则CPU将在HCLK的频率下工作
mrc 把协处理器的值写入寄存器
mcr 把寄存器的值写入协处理器
r --> register
c --> co-process 协处理器
#R1_nF:OR:R1_iA --> #0xc0000000
怎么得出#0xc0000000?参考下面这个网页:
https://blog.csdn.net/fengsheng301/article/details/25918963
(2)编写程序
为什么我们编写程序是在汇编文件里而不是c文件呢?
因为设计的协处理命令是用汇编代码写的
.text
.global _start
_start:
/* 关闭看门狗 */
ldr r0, =0x53000000
ldr r1, =0
str r1, [r0]
/* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
/* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
/* 虽然是默认就是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
一旦设置PLL, 就会锁定lock time直到PLL输出稳定,然后CPU工作于新的频率FCLK。
运行效果:CPU运行很快,LED的闪烁效果比之前快得多。