系统时钟 裸板

1、板子上我们的晶振提供的时钟只有12M,但6410号称可以跑5、6百兆,这是怎么回事呢?

显然,从晶振出来的12M时钟 到给CPU提供的时钟中间经过了某个部件的处理。这个部件就叫做PLL。它将12M的时钟提高到五、六百兆,再供给CPU。
我们今天就来设置这个PLL,让它实现这样的功能。

2、怎么设置这个PLL呢?

查看6410手册S3C6410X.pdf,

3、还是从代码来分析吧

1)以下是启动代码 :start.S

.globl _start
_start:
/* 硬件相关的设置 : 把外设的基地址告诉CPU*/
    /* Peri port setup */
    ldr r0, =0x70000000
    orr r0, r0, #0x13
    mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)
    
/* 关看门狗 */
/* 往WTCON(0x7E004000)写0 */	
	ldr r0, =0x7E004000
	mov r1, #0
	str r1, [r0]
	
	/*设置时钟 */
	bl clock_init

	/* 设置栈, 调用C函数 */
	ldr sp, =8*1024
	bl main
halt:
	b halt	
2)下面是点led的测试程序:led.c

void delay()
{
	volatile int i = 0x10000;
	while (i--);
}
int main()
{
	int i = 0;	
	volatile unsigned long *gpmcon = (volatile unsigned long *)0x7F008820;
	volatile unsigned long *gpmdat = (volatile unsigned long *)0x7F008824;
	
	/* gpm0,1,2,3设为输出引脚 */
	*gpmcon = 0x1111;
	
	while (1)
	{
		*gpmdat = i;
		i++;
		if (i == 16)
			i = 0;
		delay();
	}	
	return 0;
}
3)以下是时钟设置的代码:clock.S
.globl clock_init
clock_init:	
	/* 1.设置LOCK_TIME */
	ldr r0, =0x7E00F000  /* APLL_LOCK */
	ldr r1, =0x0000FFFF
	str r1, [r0]
	
	str r1, [r0, #4]	 /* MPLL_LOCK */
	str r1, [r0, #8]	 /* EPLL_LOCK */	
	
#define OTHERS		0x7e00f900
	@ set async mode  /* 当CPU时钟 != HCLK时,要设为异步模式 */
	ldr r0, =OTHERS
	ldr r1, [r0]
	bic r1, r1, #0xc0	/* 1100,0000 */		
	str r1, [r0]
loop1:				/* 等待,直到CPU进入异步模式 */
	ldr r0, =OTHERS
	ldr r1, [r0]
	and r1, r1, #0xf00					
	cmp r1, #0
	bne loop1		
	
	/* SYNC667 */
	/* MISC_CON[19] = 0 */
#define ARM_RATIO    0   /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1)    */
#define HCLKX2_RATIO 1   /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) */
#define HCLK_RATIO   1   /* HCLK = HCLKX2 / (HCLK_RATIO + 1)       */
#define PCLK_RATIO   3   /* PCLK   = HCLKX2 / (PCLK_RATIO + 1)     */
#define MPLL_RATIO   0   /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1)     */
	ldr r0, =0x7E00F020  /* CLK_DIV0 */
	ldr r1, =(ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12)
	str r1, [r0]
	
	/* 2.配置时钟 */
	/* 2.1 配置APLL */
	/* 2.1.1 设置APLL
	 * 2.1.2 MUXAPLL
	 * 2.1.3 SYNC667
	 * 2.1.4 DIVAPLL
	 */
#define APLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
	ldr r0, =0x7E00F00C
	ldr r1, =APLL_CON_VAL
	str r1, [r0]		/* APLL_CON, FOUTAPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz  */
	
	/* 2.2 配置MPLL */
	/* 2.2.1 设置MPLL
	 * 2.2.2 MUXMPLL
	 * 2.2.3 SYNCMUX
	 * 2.2.4 SYNC667
	 * 2.2.5 HCLKX2_RATIO
	 * 2.2.6 PCLK_RATIO
	 */
#define MPLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
	ldr r0, =0x7E00F010
	ldr r1, =MPLL_CON_VAL
	str r1, [r0]		/* MPLL_CON, FOUTMPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz  */
	
	/* 3.选择PLL的输出作为时钟源 */
	ldr r0, =0x7E00F01C
	ldr r1, =0x03
	str r1, [r0]
	
	mov pc, lr
1> 我们要把12M时钟提高到5 6百兆,不可能瞬间完成,需要一个时间差,这个时间差就是LOCK_TIME.            以下是时序图:

LOCK_TIME 就是锁定时间,在这段时间PLL就开始工作,把时钟提高。

2>  APP  MPLL EPLL

这里有3个PLL,分别是给不同的控件提供时钟的,APLL是给CPU用的,MPLL是给HCLK( 一般是我们的内存,DDR ),PCLK(片上外设),EPLL给其它设备用的。

上面是汇编的,以下是其时钟设置C版,功能都一样:

#define APLL_LOCK (*((volatile unsigned long *)0x7E00F000))
#define MPLL_LOCK (*((volatile unsigned long *)0x7E00F004))
#define EPLL_LOCK (*((volatile unsigned long *)0x7E00F008))

#define OTHERS    (*((volatile unsigned long *)0x7e00f900))

#define CLK_DIV0  (*((volatile unsigned long *)0x7E00F020))

#define ARM_RATIO    0   /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1)    */
#define HCLKX2_RATIO 4   /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) = 100MHz */
#define HCLK_RATIO   0   /* HCLK = HCLKX2 / (HCLK_RATIO + 1)   = 100MHz       */
#define PCLK_RATIO   1   /* PCLK   = HCLKX2 / (PCLK_RATIO + 1) = 50MHz    */
#define MPLL_RATIO   0   /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1)     */

#define APLL_CON  (*((volatile unsigned long *)0x7E00F00C))
#define APLL_CON_VAL  ((1<<31) | (250 << 16) | (3 << 8) | (1))

#define MPLL_CON  (*((volatile unsigned long *)0x7E00F010))
#define MPLL_CON_VAL  ((1<<31) | (250 << 16) | (3 << 8) | (1))

#define CLK_SRC  (*((volatile unsigned long *)0x7E00F01C))

void clock_init(void)
{
	APLL_LOCK = 0xffff;
	MPLL_LOCK = 0xffff;
	EPLL_LOCK = 0xffff;

	/* set async mode 当CPU时钟 != HCLK时,要设为异步模式 */
	OTHERS &= ~0xc0;
	while ((OTHERS & 0xf00) != 0);

	CLK_DIV0 = (ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12);
	
	APLL_CON = APLL_CON_VAL;  /* 500MHz */
	MPLL_CON = MPLL_CON_VAL;  /* 500MHz */

	CLK_SRC = 0x03;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值