S5PV210的时钟系统

Posted Lewin~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了S5PV210的时钟系统相关的知识,希望对你有一定的参考价值。

3.0时钟简介

时钟是同步工作系统的工作节拍
例如:

工人按照工作时间上下班
舞者根据音乐节拍做出不同的动作
正步时教官念的121

为什么需要时钟?

SoC内部需要一个同步的时钟系统来协调各个内部外设和CPU的工作

SoC的时钟获得方式:

1.SoC有个引脚用于输入外部时钟源信号,用的很少。
2.外部晶振+内部时钟发生器产生时钟,大部分低频单片机常用。
3.外部晶振+内部时钟发生器+内部PLL产生高频时钟+内部分频器分频得到各种频率的时钟,ARM,stm32使用这些。

为什么外部不直接用高频晶振产生高频信号直接给CPU?

高频晶振易产生传导辐射影响周遭电路,因此SoC外围电路不宜使用高频;
高频率的晶振太贵了。

为什么要内部先高频然后再分频?

主要因为SoC内部各部件所需时钟频率不同,没法统一供应。
因此设计思路是PLL后先得到一个最高的频率(1GHz、1.2GHz)作为主频,然后各外设都有自己的分频器再来分频得到自己想要的频率。

3.1时钟域

210根据 “各设备所需时钟频率的高低和设备的类别” 将整个时钟体系分成三个时钟域,即主系统(MSYS)、显示系统(DSYS)和外围系统(PSYS),如图3-1所示。

•MSYS域包括CortexA8处理器、DRAM内存控制器(DMC0和DMC1)、IRAM和IROM…
•DSYS域都是和视频显示、编解码等有关的模块
•PSYS域和内部各种外设时钟有关,譬如串口、SD接口、I2C等。

3.2时钟声明

210时钟来源:晶振+时钟发生器+PLL+分频电路

S5PV210外部有4个晶振接口,设计板子硬件时可以根据需要来决定在哪里接晶振。接了晶振之后上电相应的模块就能产生振荡,产生原始时钟。原始时钟再经过一系列的筛选开关进入相应的PLL电路生成倍频后的高频时钟。高频时钟再经过分频到达芯片内部各模块上。(有些模块,譬如串口内部还有进一步的分频器进行再次分频使用)

在典型的210应用程序中,

•CortexA8和MSYS时钟域使用APLL(即ARMCLK、HCLK_MSYS和PCLK_MSYS)。
•DSYS和PSYS时钟域(即HCLK_DSYS、HCLK_PSYS、PCLK_DSYS和PCLK_PSYS)和其他外设时钟(即音频IP、SPI等)使用MPLL和EPLL。
•视频时钟使用VPLL。

3.3时钟关系

210时钟域详解
MSYS域:

ARMCLK: 给cpu内核工作的时钟,也就是主频
HCLK_MSYS: MSYS域的高频时钟,给DDR0和DDDR1使用
PCLK_MSYS: MSYS域的低频时钟
HCLK_IMEM:给iROM和iRAM(合称iMEM)使用

DSYS域:

HCLK_DSYS:DSYS域的高频时钟
PCLK_DSYS:DSYS域的低频时钟

PSYS域:

HCLK_PSYS:PSYS域的高频时钟
PCLK_PSYS:PSYS域的低频时钟

总结:

210内部的各个外设都是接在(内部AMBA总线)总线上面的,AMBA总线有1条高频分支叫AHB,有一条低频分支叫APB。上面的各个域都有各自对应的HCLK_XXX和PCLK_XXX,其中HCLK_XXX就是XXX这个域中AHB总线的工作频率;PCLK_XXX就是XXX这个域中APB总线的工作频率。
SoC内部的各个外设其实是挂在总线上工作的,也就是说这个外设的时钟来自于他挂在的总线,譬如串口UART挂在PSYS域下的APB总线上,因此串口的时钟来源是PCLK_PSYS。
我们可以通过记住和分析上面的这些时钟域和总线数值,来确定我们各个外设的具体时钟频率。

高性能的时钟值:

• freq(ARMCLK) = 1000 MHz
• freq(HCLK_MSYS) = 200 MHz
• freq(HCLK_IMEM) = 100 MHz
• freq(PCLK_MSYS) = 100 MHz
• freq(HCLK_DSYS) = 166 MHz
• freq(PCLK_DSYS) = 83 MHz
• freq(HCLK_PSYS) = 133 MHz
• freq(PCLK_PSYS) = 66 MHz
• freq(SCLK_ONENAND) = 133 MHz, 166 MHz

3.4时钟框图分析

(1)时钟框位置:数据手册P361&P362
(2)两张图之间是渐进的关系。第一张图从左到右依次完成了原始时钟生成->PLL倍频得到高频时钟->初次分频得到各总线时钟;第二张图是从各中间时钟(第一张图中某个步骤生成的时钟)到各外设自己使用的时钟(实际就是个别外设自己再额外分频的设置)。
(3)要看懂时钟体系框图,2个符号很重要:一个是MUX开关,另一个是DIV分频器。
(3.1)MUX开关是数据选择器,实际编程时对应某个寄存器的某几位的设置,设置值决定了不同的时钟来源。
(3.2)DIV分频器,是一个硬件设备,可以对频率进行n分频生成低频时钟,实际编程时对应某个寄存器中的某几位的设置,设置值决定了不同的分频系数(譬如左边进来的时钟是80MHz,分频系数设置为8,则分频器右边输出的时钟频率为10MHz)。

3.7寄存器分析

xPLL_LOCK寄存器用于控制PLL的锁定周期
xPLL_CONn寄存器用于打开/关闭PLL电路,设置PLL的倍频参数,查看PLL锁定状态等
CLK_SRCn寄存器用于选择时钟来源,对应时钟框图中的MUX开关。
CLK_DIVn寄存器用于设置时钟分频

210设置高性能时钟值的步骤

目的:(将对应时钟设置成如下数值)

• freq(ARMCLK) = 1000 MHz
• freq(HCLK_MSYS) = 200 MHz
• freq(HCLK_IMEM) = 100 MHz
• freq(PCLK_MSYS) = 100 MHz
• freq(HCLK_DSYS) = 166 MHz
• freq(PCLK_DSYS) = 83 MHz
• freq(HCLK_PSYS) = 133 MHz
• freq(PCLK_PSYS) = 66 MHz
• freq(SCLK_ONENAND) = 133 MHz, 166 MHz

第1步:先将所有MUX开关置0,保证设置完PLL后再设置为1导通倍频过的时钟。
寄存器查看:

这里设置值为0x0

第2步:设置PLL锁定时间。
寄存器查看:
默认值为0x0FFF,保险起见我们设置为0xFFFF。

第3步:设置分频系数,决定由PLL倍频后出来的最高时钟如何分频得到各个分时钟。
寄存器查看:
这里设置值为0x14131440

第4步:设置PLLL的倍频系数(M、P、S)并使能PLL,决定输入端24MHz的原始频率经倍频后能得到多大的时钟频率。
寄存器查看:


数据手册推荐的倍频系数的设置:

第5步:MUX开关置1,经PLL倍频后的时钟开始工作。

这里设置值为0x10001111。

clock.S:

#define	CLOCK_START	0xE0100000
#define	CLOCK_START						0xE0100000

#define CLK_SRC0_OFFSET					0x200
#define APLL_LOCK_OFFSET				0x0
#define MPLL_LOCK_OFFSET				0x8
#define CLK_DIV0_OFFSET					0x300

#define	APLL_CON0_OFFSET 				0x100
#define	APLL_MDIV						0x7d
#define	APLL_PDIV						0x3
#define APLL_SDIV						0x1
#define set_apll(mdiv , pdiv , sdiv)	(1<<31 | mdiv<<16 | pdiv<<8 | sdiv<<0)
#define SET_APLL_DAT					set_apll(APLL_MDIV , APLL_PDIV  , APLL_SDIV)

#define	MPLL_CON0_OFFSET 				0x108
#define	MPLL_MDIV						0x29b
#define	MPLL_PDIV						0xc
#define MPLL_SDIV						0x1
#define set_mpll(mdiv , pdiv , sdiv)	(1<<31 | mdiv<<16 | pdiv<<8 | sdiv<<0)
#define SET_MPLL_DAT					set_mpll(MPLL_MDIV , MPLL_PDIV , MPLL_SDIV)
.global _setclock
_setclock:
	/*所有mux置0*/
	ldr r0, =CLOCK_START
	ldr r1, =0x0
	str r1, [r0, #CLK_SRC0_OFFSET]
	
	/*设置PLL锁定时间*/
	ldr r1, =0xFFFF
	str r1, [r0, #APLL_LOCK_OFFSET]
	str r1, [r0, #MPLL_LOCK_OFFSET]
	
	/*分频*/
	ldr r1, =0x14131440	
	str r1, [r0, #CLK_DIV0_OFFSET]
	
	/*设置PLL倍频,并使能PLL*/
	ldr r1, =SET_APLL_DAT
	str r1, [r0, #APLL_CON0_OFFSET]
	
	ldr r1, =SET_MPLL_DAT
	str r1, [r0, #MPLL_CON0_OFFSET]
	
	/*部分mux置1*/
	ldr r1, [r0, #CLK_SRC0_OFFSET]
	ldr r2, =0x10001111
	orr r1, r1, r2
	str r1, [r0, #CLK_SRC0_OFFSET]
	
	mov pc, lr

clock.c:

#define	CLOCK_START						0xE0100000

#define CLK_SRC0_OFFSET					0x200
#define APLL_LOCK_OFFSET				0x0
#define MPLL_LOCK_OFFSET				0x8
#define CLK_DIV0_OFFSET					0x300
#define	APLL_CON0_OFFSET 				0x100
#define	MPLL_CON0_OFFSET 				0x108

#define rClock_Start					*((volatile unsigned int*)(SET_CLOCK_START))
#define rCLK_SRC0						*((volatile unsigned int*)(SET_CLOCK_START+CLK_SRC0_OFFSET))
#define rAPLL_LOCK						*((volatile unsigned int*)(SET_CLOCK_START+APLL_LOCK_OFFSET))
#define rMPLL_LOCK						*((volatile unsigned int*)(SET_CLOCK_START+MPLL_LOCK_OFFSET))
#define rCLK_DIV0						*((volatile unsigned int*)(SET_CLOCK_START+CLK_DIV0_OFFSET))
#define rAPLL_CON0						*((volatile unsigned int*)(SET_CLOCK_START+APLL_CON0_OFFSET))
#define rMPLL_CON0						*((volatile unsigned int*)(SET_CLOCK_START+MPLL_CON0_OFFSET))

#define	APLL_MDIV						0x7d
#define	APLL_PDIV						0x3
#define APLL_SDIV						0x1
#define set_apll(mdiv , pdiv , sdiv)	(1<<31 | mdiv<<16 | pdiv<<8 | sdiv<<0)
#define SET_APLL_DAT					set_apll(APLL_MDIV , APLL_PDIV  , APLL_SDIV)
#define	MPLL_MDIV						0x29b
#define	MPLL_PDIV						0xc
#define MPLL_SDIV						0x1
#define set_mpll(mdiv , pdiv , sdiv)	(1<<31 | mdiv<<16 | pdiv<<8 | sdiv<<0)
#define SET_MPLL_DAT					set_mpll(MPLL_MDIV , MPLL_PDIV , MPLL_SDIV)

void clock_test(void)

	/*关mux*/
	rCLK_SRC0 = 0;
	
	/*设置PLL锁定时间*/
	rAPLL_LOCK = 0xFFFF;
	rMPLL_LOCK = 0xFFFF;
	
	/*分频*/
	rCLK_DIV0 = 0x14131440;
	
	/*设置PLL倍频,并开PLL*/
	rAPLL_CON0 = SET_APLL_DAT;
	rMPLL_CON0 = SET_MPLL_DAT;
	
	/*开mux*/
	rCLK_SRC0 = 0x10001111;

以上是关于S5PV210的时钟系统的主要内容,如果未能解决你的问题,请参考以下文章

S5PV210的时钟系统

S5PV210的时钟系统

S5pv210 时钟体系分析

9.S5PV210的时钟系统

ARM芯片的时钟系统详解(S5PV210芯片)

s5pv210——初始化时钟