开发环境与平台
开发板:粤嵌的GEC210开发板
处理器:s5pv210
处理器内核:Cortex-A8
开发环境:Keil4
时钟
时钟在计算机系统里是非常重要的,各逻辑部件的运行、协同工作都需要时钟。时钟在计算机系统主要是通过脉冲的来实现的,通过脉冲的计数可以形成一个相对时间。
s5pv210的时钟
1、时钟分类
s5pv210的时钟的时钟分成以上三类。
MSYS:包括Cortex A8处理器,DRAM内存控制器(DMCO和DMC1),3D,内部SRAM(IRAM和IROM),INTC和配置接口(SPERI)。Cortex A8仅支持同步模式,因此必须与200MHz AXI总线同步运行。
DSYS:包括显示相关模块,包括FIMC,FIMD,JPEG和多媒体IP(X,L和T块中提到的所有其他IP)
PSYS:用于安全性,I / O外设和低功耗音频播放。
2、时钟框架
下面这个是s5pv210的时钟体系的框架图。
3、时钟来源
32.768KHZ的晶振:给RTC模块提供时钟
24MHZ晶振:有两个,一个给USB提供时钟,一个给三大时钟域提供时钟。
27MHZ:给HDMI提供时钟。
4、时钟信号的关系
HCLK:高速总线时钟,用于高速设备
PCLK:低速总线时钟,用于低速设备
5、逻辑器件的所属的时钟域
可见,常用的GPIO、I2C、SPI、UART等外设是属于外设时钟域的。
时钟管理单元(CMU)
各个逻辑部件的所需要的工作的时钟不一样,低速设备需要低速时钟,高速设备需要高速时钟。这些问题有时钟管理单元来解决。
配置s5pv210时钟主要便是对上面三个部件的设置。
S5PV210部件高性能时工作时钟
如何配置时钟?
查看数据手册,可知时钟配置主要跟一下寄存器时钟相关。
时钟树:
1、APLL_CON0(APLL控制寄存器0)相关
APLL倍频公式:
从倍频公式可以看出,时钟倍频主要跟APLL_CON0寄存器的MDIV、PDIV、SDIV这三个位相关。单纯看上面的倍频公式很难计算得到,数据手册还提供了设置成倍频到某个时钟频率的典型值。
可以看到只要将PDIV、MDIV、SDIV这个三个分别设置为3、125、1即可将倍频到1000MHZ。
APLL_CON0寄存器:
bit[30]: PLL使能失能位
bit[25:16]:MDIV
bit[13:8]:PDIV
bit[2:0]:SDIV
2、MPLL_CON(MPLL的控制寄存器)相关
MPLL倍频公式:
可以看到MPLL的配置与APLL很相似。
MPLL倍频典型值:
若要倍频到667MHZ,从表中可以看到,将PDIV、MDIV、SDIV这个三个分别设置为12、667、1即可。
MPLL_CON寄存器:
bit[30]: PLL使能失能位
bit[25:16]:MDIV
bit[13:8]:PDIV
bit[2:0]:SDIV
3、CLK_SRC0(时钟源控制寄存器0)
结合时钟树和时钟源控制寄存器可以看到通过设置时钟源控制寄存器的某个位来控制选择器从而选择时钟源。
比如,选择MPLL倍频后的时钟作为时钟,将MPLL_SEL位及时钟源控制寄存器的bit4位设置为1即可。
4、CLK_DIV0(时钟分频控制寄存器0)
通过该寄存器将倍频或直接外部输入的时钟分频得到适合不同部件的工作频率。
比如,设置 PSYS域的HCLK,需设置HCLK_PSYS_RATIO位的值,根据HCLK_PSYS = MOUT_PSYS / (HCLK_PSYS_RATIO + 1) ,等到HCLK的频率值。
5、XXX_LOCK(PLL锁定时间寄存器)
这个XXX可以是APLL、MPLL、EPLL或VPLL,这个几个寄存器的作用是一样的。
该寄存器在技术手册中的描述如下:
这段话翻译过来就是:
当输入频率改变或分频(乘法)值改变时,APLL需要锁定周期。PLL_LOCK寄存器指定此锁定周期,该周期基于PLL的源时钟。在此期间,输出将处于低状态。
这个翻译很官方。用大白话来讲就是设置APLL_CON、时钟分频控制寄存器0、时钟源控制寄存器0这些寄存器改变了输入的频率时这个频率不是稳定的,要给它一个逐渐稳定的时间,这个时间就是通过PLL锁定寄存器设置。
时钟配置程序编写
1、时钟配置步骤
(1)时钟源选择(CLK_SRC0)寄存器清0不使用PLL。
(2)锁定时间寄存器(APLL_LOCK、MPLL_LOCK)赋值,设定锁定时间。
(3)设分频值(CLK_DIV0)。
(4)设倍频值(APLL_CON0、MPLL_CON)。
(5)开启PLL时钟源(CLK_SRC0)
2、程序编写
s5pv210.h:
//时钟相关寄存器定义
#define APLLCLOCK (*(volatile unsigned long *)0xE0100000)
#define APLLCON0 (*(volatile unsigned long *)0xE0100100) //0xE0100100
#define MPLLCLOCK (*(volatile unsigned long *)0xE0100008)
#define MPLLCON (*(volatile unsigned long *)0xE0100108) //0xE0100108
#define CLKSRC0 (*(volatile unsigned long *)0xE0100200)
#define CLKDIV0 (*(volatile unsigned long *)0xE0100300)
clock.c:
#include "s5pv210.h"
#include "clock.h"
void clock_init(void)
{
CLKSRC0 &= 0;//close PLL
/* 设定锁定时间为最大值 */
APLLCLOCK = 0xFFFF;
MPLLCLOCK = 0xFFFF;
CLKDIV0 = 0x14131440; /* 设置分频 0001 0100 0001 0011 0001 0100 0100 0000 */
APLLCON0 = (125 << 16) | (3 << 8) | (1 << 0) | (1 << 31); /* 设置APLL为1000MHZ,使能APLL */
MPLLCON = (12 << 8) | (667 << 16) | (1 << 0) | (1 << 31); /* 设置MPLL为667MHZ ,使能MPLL */
/* 选择时钟源 0000 0000 0000 0000 00001 0001 0001 0001
APLL、MPLL、EPLL、VPLL都选择它们倍频后的输出频率*/
CLKSRC0 = 0x00001111;
}
查看寄存器分频寄存器和时钟源控制寄存器的以及结合时钟树来看就能知道各个域的HCLk、PCLK的时钟是多少。