ARM时钟体系(ARM9)
首先要明确一点,在编写带有时序性质的程序时,如果没有思路可以先了解其工作时的时序图,这一点是非常重要的。一个时序图能够清楚的描述其运行的整个过程,弄懂时序图会对编程思路有着明显的提升。
本次学习使用的开发板为:JZ2440
ARM版本为:AMR9
一、时钟框架概述
1.框架结构
在讲解如何通过程序改变芯片的运行时钟频率之前,先搞清楚ARM9时钟框架,如下图所示为S3C2440芯片手册上关于时钟框架的框架图。
通过观察上述的框架图可以发现,整个SOC被划分成了三部分,可以总结为:CPU部分、AHB总线设备部分、APB总线设备部分。而且AHB总线设备一般包括LCD、Camera、Nand Flash等,APB总线设备一般包括UART、IIC、SPI、GPIO等。三部分所使用到的时钟频率是不相同的,因此需要给特定的部分设置特定的频率。
2.时序图分析
(1)首先可以看到当CPU一开始上电时,系统并没有立刻进行复位操作,而是过了一段时间之后[t]之后才开始复位操作,这样做的目的是因为当系统刚上电时,电压不稳定,因此需要延时一会等待电压稳定后再进行复位操作。
(2)系统复位操作之后OM[3:2]引脚的电平变化就会被读入,从而会确定系统选择的晶振源以及PLL的状态。
(3)CPU复位操作后,晶振源也开始工作,产生时钟信号,但此时的振荡信号也不太稳定,因此需要延时一段时间等晶振输出稳定的振荡信号。 (4)之后就会进行时钟信号的锁存,会有一个锁存时间,在这个锁存时间里时钟信号不会发生。
(5)在锁存时间结束后,CPU会在新的时钟频率下运行。
二、编程实现
1.时钟信号分配情况框图
2.编程步骤
(1)在原理图中查看OM[3:2]这两个引脚处于那种状态,同时确定晶振的频率。
(2)设置LOCK tiME,如果不想设置,也可以使用默认值。
(3)设置MPLLCON、UPLLCON这两个寄存器,这两个寄存器决定的是MPLL和UPLL。MPLL实际上就是FCLK,UPLL实际上是USB_CLK。
(4)设置CLKDINVN,该寄存器主要是控制HCLK、PCLK的大小。
注意事项:(1)在设置MPLLCON时芯片手册上会提示,如果想要设置MPLLCON首先要设置UPLLCON
(2)若HDIVN的值不为0,则需要执行以下代码:
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
对于上述三行的详细解释会在下一专题详细进行分析。
3.编程实例
/****************************************
*****************************************/
.text
.global _start
_start:
#define GPFCON 0x56000050
#define GPFDAT 0x56000054
#define UPLLCON 0x4C000008
#define MPLLCON 0x4C000004
#define CLKDIVN 0x4C000014
#define GPF_as_output_port 0x1500
ldr r0, = GPFCON
ldr r1, = GPF_as_output_port
str r1, [r0]
//设置时钟//
//第一步:设置时钟源,通过原理图可以发现,OM[3:2]为接地引脚,因此选择的是外接的12MHZ的晶振。
//LOCKTIME设置为默认值。
//第二步:设置MPLLCON和UPLLCON寄存器
ldr r4, =MPLLCON
ldr r5, =UPLLCON
//UPLL = 48mhz
ldr r3, =((56<<12) | (2<<4) | (2<<0))
str r3, [r5]
//MPLL = 400mhz
ldr r3, =((92<<12) | (1<<4) | (1<<0))
str r3, [r4]
//第三步设置CLKDIVN寄存器
ldr r4, =CLKDIVN
ldr r3, =0x5
str r3, [r4]
//设置为异步模式
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000
mcr p15,0,r0,c1,c0,0
led_flash:
bl led1_on
bl delay
bl led_off
bl delay
bl led2_on
bl delay
bl led_off
bl delay
bl led3_on
bl delay
bl led_off
bl delay
b led_flash
led1_on:
ldr r2, =0xef
ldr r3, = GPFDAT
str r2, [r3]
mov pc, lr
led2_on:
ldr r2, =0xdf
ldr r3, = GPFDAT
str r2, [r3]
mov pc, lr
led3_on:
ldr r2, = 0xbf
ldr r3, = GPFDAT
str r2, [r3]
mov pc, lr
led_off:
ldr r2, = 0xff
ldr r3, = GPFDAT
str r2, [r3]
mov pc, lr
delay:
mov r0, #0x40000 @注意这里一定不能写在下面的0循环内,否则将变成死循环!!这是经常犯错的地方!!
delay_loop:
sub r0, r0, #1
mov r2, #0
cmp r0, r2
bne delay_loop
mov pc, lr //返回被调用的地方
原作者:pengfei_M
|