2440的时钟初始化
一、时钟概览
下面图很好地总结了上面的图
时钟源:为了减少外界环境对开发板电磁干扰,降低制作成本,通常开发板的外部晶振时钟频率都很低,2440开发板由12MHz的晶振来提供时钟源,要想让CPU运行在更高的频率就要通过时钟控制逻辑单元PLL(锁相环)来提高主频。
S3C2440里有两个PLL:MPLL和UPLL,MPLL用来产生FCLK,HCLK,PCLK的高频工作时钟,UPLL用来为USB提供工作频率。
其中FCLK主要为ARM920T内核提供工作频率
HCLK主要为S3C2440 AHB总线(Advanced High performance Bus)上挂接硬件提供工作频率,AHB总线主要挂接有内存,NAND,LCD控制器等硬件
PCLK主要为APB总线提供工作频率,由图2-46所示,APB总线主要挂接UART串口,Watchdog等硬件控制器。
二、寄存器设置
1.设置时钟源
在硬件上,已经将这两个管脚接地,即选择晶振输入,开启两个PLL
2.LockTime PLL锁定时间由LOCKTIME寄存器设置
不做详细赘述,直接使用默认值即可
3.设置分频系数
CLKDIVN = 0x05; // FCLK:HCLK:PCLK=1:4:8
4.设置MPLL得到400MHZ的频率
* 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV
* 有如下计算公式:
* S3C2440: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
* 其中: m = MDIV + 8, p = PDIV + 2, s = SDIV
* 对于本开发板,Fin = 12MHz
#define S3C2440_MPLL_400MHZ ((92<<12)|(1<<4)|(1<<0))
MPLLCON = S3C2440_MPLL_400MHZ;
5、其他
如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode”
三、实验代码
1.Makefile
all:
arm-linux-gcc -c -o start.o start.S
arm-linux-gcc -c -o led.o led.c
arm-linux-gcc -c -o init.o init.c
arm-linux-ld -Ttext 0 start.o led.o init.o -o led_on.elf
arm-linux-objcopy -O binary -S led_on.elf led_on.bin
clean:
rm *.bin *.o *.elf
2.start.S
.global _start
_start:
//关闭看门狗
ldr r0, =0
ldr r1, =0x53000000
str r0, [r1]
ldr sp, =4096
bl clock_init
bl led_blink
b .
3.init.c
/*
* init.c: 进行一些初始化
*/
#include "s3c24xx.h"
void clock_init(void);
#define S3C2440_MPLL_400MHZ ((92<<12)|(1<<4)|(1<<0))
/*
* 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV
* 有如下计算公式:
* S3C2440: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
* 其中: m = MDIV + 8, p = PDIV + 2, s = SDIV
* 对于本开发板,Fin = 12MHz
* 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:4:8,
* FCLK=400MHz,HCLK=100MHz,PCLK=50MHz
*/
void clock_init(void)
{
LOCKTIME = 0xFFFFFFFF; // 使用默认值即可
CLKDIVN = 0x05; // FCLK:HCLK:PCLK=1:4:8
/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
__asm__(
"mrc p15, 0, r1, c1, c0, 0\n" /* 读出控制寄存器 */
"orr r1, r1, #0xc0000000\n" /* 设置为“asynchronous bus mode” */ //R1_nF:OR:R1_iA
"mcr p15, 0, r1, c1, c0, 0\n" /* 写入控制寄存器 */
);
MPLLCON = S3C2440_MPLL_400MHZ; /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
}
4.led.c
#define GPFCON 0x56000050
#define GPFDAT 0x56000054
void delay(void);
// 该函数要实现led闪烁效果
void led_blink(void)
{
// led初始化
unsigned int *p = (unsigned int *)GPFCON;
unsigned int *p1 = (unsigned int *)GPFDAT;
*p = 0x1500;
while (1)
{
// led亮
*p1 = ((0<<4) | (0<<5) | (0<<6));
// 延时
delay();
// led灭
*p1 = ((1<<4) | (1<<5) | (1<<6));
// 延时
delay();
}
}
void delay(void)
{
unsigned int i = 200000;
while (i--);
}
5.s3c24xx.h
/* WOTCH DOG register */
#define WTCON (*(volatile unsigned long *)0x53000000)
/* SDRAM regisers */
#define MEM_CTL_BASE 0x48000000
#define SDRAM_BASE 0x30000000
/* NAND Flash registers */
#define NFCONF (*(volatile unsigned int *)0x4e000000)
#define NFCMD (*(volatile unsigned char *)0x4e000004)
#define NFADDR (*(volatile unsigned char *)0x4e000008)
#define NFDATA (*(volatile unsigned char *)0x4e00000c)
#define NFSTAT (*(volatile unsigned char *)0x4e000010)
/*GPIO registers*/
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054)
#define GPFUP (*(volatile unsigned long *)0x56000058)
#define GPGCON (*(volatile unsigned long *)0x56000060)
#define GPGDAT (*(volatile unsigned long *)0x56000064)
#define GPGUP (*(volatile unsigned long *)0x56000068)
#define GPHCON (*(volatile unsigned long *)0x56000070)
#define GPHDAT (*(volatile unsigned long *)0x56000074)
#define GPHUP (*(volatile unsigned long *)0x56000078)
/*UART registers*/
#define ULCON0 (*(volatile unsigned long *)0x50000000)
#define UCON0 (*(volatile unsigned long *)0x50000004)
#define UFCON0 (*(volatile unsigned long *)0x50000008)
#define UMCON0 (*(volatile unsigned long *)0x5000000c)
#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
#define UTXH0 (*(volatile unsigned char *)0x50000020)
#define URXH0 (*(volatile unsigned char *)0x50000024)
#define UBRDIV0 (*(volatile unsigned long *)0x50000028)
/*interrupt registes*/
#define SRCPND (*(volatile unsigned long *)0x4A000000)
#define INTMOD (*(volatile unsigned long *)0x4A000004)
#define INTMSK (*(volatile unsigned long *)0x4A000008)
#define PRIORITY (*(volatile unsigned long *)0x4A00000c)
#define INTPND (*(volatile unsigned long *)0x4A000010)
#define INTOFFSET (*(volatile unsigned long *)0x4A000014)
#define SUBSRCPND (*(volatile unsigned long *)0x4A000018)
#define INTSUBMSK (*(volatile unsigned long *)0x4A00001c)
/*external interrupt registers*/
#define EINTMASK (*(volatile unsigned long *)0x560000a4)
#define EINTPEND (*(volatile unsigned long *)0x560000a8)
/*clock registers*/
#define LOCKTIME (*(volatile unsigned long *)0x4c000000)
#define MPLLCON (*(volatile unsigned long *)0x4c000004)
#define UPLLCON (*(volatile unsigned long *)0x4c000008)
#define CLKCON (*(volatile unsigned long *)0x4c00000c)
#define CLKSLOW (*(volatile unsigned long *)0x4c000010)
#define CLKDIVN (*(volatile unsigned long *)0x4c000014)
/*PWM & Timer registers*/
#define TCFG0 (*(volatile unsigned long *)0x51000000)
#define TCFG1 (*(volatile unsigned long *)0x51000004)
#define TCON (*(volatile unsigned long *)0x51000008)
#define TCNTB0 (*(volatile unsigned long *)0x5100000c)
#define TCMPB0 (*(volatile unsigned long *)0x51000010)
#define TCNTO0 (*(volatile unsigned long *)0x51000014)
#define GSTATUS1 (*(volatile unsigned long *)0x560000B0)
结果分析:
将bin文件烧写进开发板,可以看到LED的闪烁速度比没有进行时钟初始化的时候快了好多。
参考链接:
https://blog.csdn.net/mr_raptor/article/details/6555734
http://wiki.100ask.org/%E7%AC%AC010%E8%AF%BE_%E6%8E%8C%E6%8F%A1ARM%E8%8A%AF%E7%89%87%E6%97%B6%E9%92%9F%E4%BD%93%E7%B3%BB
韦老师代码