S3C2440 初始化时钟

一、S3C2440 时钟

1、时钟树

  • 从s3c2440的技术手册的时钟树可以了解到,它的时钟分四大块FCLK,HCLK,PCLK,UCLKFCLK主要用于CPU的运行时钟,HCLK主要用于内存控制器,中断控制器等一些高速设备的时钟,PCLK主要用于GPIO控制器,I2C控制器等一些较低速设备的时钟,UCLK主要给USB控制器提供时钟的。时钟树如下图:

2、S3C2440支持的时钟速率

  • 1、S3C2440的最高速率:FCLK最高支持400MHz,HCLK最高支持136MHzPCLK最高支持68MHz
  • 2、在本实验将 FCLK设置为400MHz,HCLK设置为100MHz,PCLK设置为50MHz

二、设置时钟

1、时钟源的选择

  • 1、s3c2440的时钟源,可以从晶振里来也可以从外部时钟来。来源于哪里可以由OM2OM3管脚设置。
  • 2、由于我的板子接了12MHz的晶振,所以将晶振设置为输入的时钟源;OM2OM3都设置为0。

2、锁相环设置(MPLLCON寄存器)

  • MPLLCON寄存器:

  • MPLL 时钟的计算公式:

  • S3C2440技术手册提供了配置值,直接使用它的配置值,这里就不自己计算了。

3、配置HCLK和PCKL分频(CLKDIVN寄存器)

4、设置锁存存时间(LOCKTIME)

  • 由于配置锁相环的时候需要等待它输出稳定的时钟,等待的这段时间由LOCKTIME配置

  • LOCKTIME 寄存器使用默认的值0xFFFFFFFF即可

5、设置异步模式

  • S3C2440技术手册有说明,如果FCLK的时钟频率不等于HCLK的频率时需要配置成异步模式,否则CPU使用HCLK作为运行的时钟频率。设置的方法手册上也有,需要通过设置它的协处理器。

  • 对于#R1_nF:OR:R1_iA这个立即数是什么,在S3C2440手册上没有给出。一般这些跟CPU核相关的设置,我们可以去看它的CPU核的技术文档(S3C2440的CPU核是arm920t)。在arm920t技术文档找到了nFiA。如下图:

三、程序编写

1、汇编程序(Startup.S)

  • 因为要设置p15协处理器,所以初始化时钟用汇编语言来写。

.text                     /*定义代码段*/
.global _start            /*标号_start是GNU连接器用来指定第一个要执行所必须的(只能出现在一个模块),.global将_start声明为全局可见*/

_start:
    
    /* 关看门狗 */
    ldr r1,=0x53000000
    mov r0,#0x00000000
    str r0,[r1]
    
    /* 设置栈 */
	/* 自动分辨是nor flash 启动还是nand flash启动 */
	/* 先将一个数写道0地址,然后读出来判断跟写入的值是否一样;跟写入的一样则是nand flash启动,跟写入的值不一样则是nor flash 启动 */
	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+0x1000 /* 先假设是nor启动,0x40000000 + 4k处 */
	moveq sp, #0x1000  /* nand启动, 将栈设置在4k处 */
	streq r0, [r1]   /* 恢复原来的值 */
	
	
	
#if 1
    /* 初始化时钟 */
    
    /* 设置锁存时间 LOCKTIME=0xffffffff */
    ldr r1,=0x4C000000
    ldr r0,=0xffffffff
    str r0,[r1]
    /* 设置HDIVN,PDIVN分频系数,让FCLK:HCLK:PCLK=1:4:8 */
    ldr r1,=0x4C000014
    mov r0,#0x00000005
    str r0,[r1]
    /* 设置Mpll锁相环 MDV=0x5c,PDIV=1,SDIV=1 */
    ldr r1,=0x4C000004
    ldr r0,=((0x5c<<12)|(1<<4)|(1<<0))
    str r0, [r1]
    /* 设置锁相环时钟源,使能锁相环 */
    ldr r1,=0x4C000010
    mov r0,#0x00000004
    str r0,[r1]
    /* 设置时钟为异步模式 */
    mrc p15,0,r0,c1,c0,0
    orr r0,r0,#0xc0000000
    mcr p15,0,r0,c1,c0,0
#endif
    b main
loop:
    b loop

2、主程序(main.c)

  • main函数里面主要做了led灯闪烁的事情
/* 定义GPFCON 寄存器 */

#define  GPFCON    *((volatile unsigned long*)0x56000050)

/* 定义GPFDAT 寄存器 */
#define  GPFDAT    *((volatile unsigned long*)0x56000054)


void delay(int tim){
	while(tim--);
}


int main(){
	/* 清零 */
	GPFCON &= ~(0x03 << 8);
	/* 设置为output */
	GPFCON |= (0x01<<8);
	
	while(1){
		/* 将 GPF4 输出低电平 */
		GPFDAT &= ~(1<<4);
		delay(0x10000);
		/* 将 GPF4 输出高电平 */
		GPFDAT |= (1<<4);
		delay(0x10000);
	}
	return 0;
}


3、Makefile

all:
	arm-linux-gcc -c Startup.S -o Startup.o
	arm-linux-gcc -c main.c -o main.o
	arm-linux-ld -Ttext 0 Startup.o main.o -o Led.elf
	arm-linux-objcopy -O binary -S Led.elf Led.bin
	arm-linux-objdump -D Led.elf > led.dis
clean:
	rm *.o *.elf *.bin *.dis

四、实验现象

通过初始化时钟后和不初始化时钟的led灯闪烁的快慢成都不一样。通过现象可以看到初始化时钟后led灯闪烁的更快,也就是说CPU的运行频率更快了。

posted @ 2020-11-02 00:34  古澜  阅读(403)  评论(0编辑  收藏  举报