一、时钟来源
SOC一般的时钟来源有:
1.外部时钟信号直接输入
2.外部晶振+内部时钟发生器
3.外部晶振+内部时钟发生器+PLL倍频+内部分频到各各外部时钟
S5PV210建议的工作频率:800MHz-1.2GHz,一般设置为1GHz。
二、S5PV210时钟系统
有3个时钟域:MSYS、DSYS、PSYS
各域对应的时钟:
1.MSYS:CPU(cortex-A8内核)、DRAM控制器、iROM、iRAM等。
2.DSYS:都是和视频显示、音频解码等有关。JPEG、I2C_HDMI_PHY。
3.PSYS:和内部外设有关,UART、PWM、RTC、SPI等。
APLL:cortex-A8内核、MSYS域
MPLL&EPLL:DSYS、PSYS
VPLL:video视频相关模块
三、时钟域详解
1. MSYS域:
ARMCLK:给CPU内核工作的时钟,就是主频。
HCLK_MSYS: MSYS域的高频时钟,给DMC1和DMC1使用(SDRAM)。
PCLK_MSYS: MSYS域的高频时钟。
HCLK_IMEM: 结合iRAM和iROM使用。
2.DSYS域:
HCLK_DSYS:DSYS域的高频时钟。
PCLK_DSYS:DSYS域的低频时钟。
3.PSYS域:
HCLK_PSYS:PSYS域的高频时钟。
PCLK_PSYS:PSYS域的低频时钟。
SCLK_ONENAND:
S5PV210内部时钟外设都是连接在内部AMBM总线上面,AMBM总线有一条高频分支AHB和一条低频分支APB,HCLK_XXX就是XXX域中AHB总线的工作频率,同样,PCLK_XXX就是XXX域中APB总线的工作频率。
四、各时钟的典型值(在iROM配置的时钟)
五、设置时钟的几个关键寄存器
1. xPLL_LOCK: 主要用来控制PLL锁定周期的。
2. xPLL_CON:用来打开/关闭PLL电路,设置倍频参数,查看PLL锁定状态等。
3. CLK_SRCN:设置时钟来源,对应MUX开关。设置时应将该寄存器设置为0,表
示暂时不用APLL和MPLL,因为开始只用24MHz外部时钟。
4. CLK_SRC_MASKn:在步骤3开MUX后,决定选择1时是否继续能否通过。
5. CLK_DIVn:设置各模块的分频系数。
6. CLK_GATE_x:对时钟进行开关控制。
7、CLK_DIV_STATn、CLK_MUX_STATn:用来查看DIV和MUX的状态是否完成还是在进行中。
总结:有3类寄存器,CON、SRC、DIV。CON设置倍频参数,SRC走哪一个时钟路,DIV设置分频参数。
六、时钟设置步骤
1.先选择不使用PLL,先用外部24MHz。
2.设置锁定时间,设置为0x0fff。
3.设置分频。由PLL出来再分频时钟。
4.设置PLL,设置产生多大的频率。
5.打开PLL。
***Clock.c文件的内容:
// 时钟控制器基地址
#define ELFIN_CLOCK_POWER_BASE0xE0100000
// 时钟相关的寄存器相对时钟控制器基地址的偏移值
#define APLL_LOCK_OFFSET0x00
#define MPLL_LOCK_OFFSET0x08
#define APLL_CON0_OFFSET0x100
#define APLL_CON1_OFFSET0x104
#define MPLL_CON_OFFSET0x108
#define CLK_SRC0_OFFSET0x200
#define CLK_SRC1_OFFSET0x204
#define CLK_SRC2_OFFSET0x208
#define CLK_SRC3_OFFSET0x20c
#define CLK_SRC4_OFFSET0x210
#define CLK_SRC5_OFFSET0x214
#define CLK_SRC6_OFFSET0x218
#define CLK_SRC_MASK0_OFFSET0x280
#define CLK_SRC_MASK1_OFFSET0x284
#define CLK_DIV0_OFFSET0x300
#define CLK_DIV1_OFFSET0x304
#define CLK_DIV2_OFFSET0x308
#define CLK_DIV3_OFFSET0x30c
#define CLK_DIV4_OFFSET0x310
#define CLK_DIV5_OFFSET0x314
#define CLK_DIV6_OFFSET0x318
#define CLK_DIV7_OFFSET0x31c
#define CLK_DIV0_MASK0x7fffffff
// 这些M、P、S的配置值来自手册的推荐值。
#define APLL_MDIV 0x7d// 125
#define APLL_PDIV 0x3
#define APLL_SDIV 0x1
#define MPLL_MDIV0x29b// 667
#define MPLL_PDIV0xc
#define MPLL_SDIV0x1
#define set_pll(mdiv, pdiv, sdiv)(1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
#define APLL_VALset_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV)
#define MPLL_VALset_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV)
#define REG_CLK_SRC0 (ELFIN_CLOCK_POWER_BASE + CLK_SRC0_OFFSET)
#define REG_APLL_LOCK(ELFIN_CLOCK_POWER_BASE + APLL_LOCK_OFFSET)
#define REG_MPLL_LOCK(ELFIN_CLOCK_POWER_BASE + MPLL_LOCK_OFFSET)
#define REG_CLK_DIV0 (ELFIN_CLOCK_POWER_BASE + CLK_DIV0_OFFSET)
#define REG_APLL_CON0(ELFIN_CLOCK_POWER_BASE + APLL_CON0_OFFSET)
#define REG_MPLL_CON (ELFIN_CLOCK_POWER_BASE + MPLL_CON_OFFSET)
#define rREG_CLK_SRC0(*(volatile unsigned int *)REG_CLK_SRC0)
#define rREG_APLL_LOCK(*(volatile unsigned int *)REG_APLL_LOCK)
#define rREG_MPLL_LOCK(*(volatile unsigned int *)REG_MPLL_LOCK)
#define rREG_CLK_DIV0(*(volatile unsigned int *)REG_CLK_DIV0)
#define rREG_APLL_CON0(*(volatile unsigned int *)REG_APLL_CON0)
#define rREG_MPLL_CON(*(volatile unsigned int *)REG_MPLL_CON)
void clock_init(void){
// 1 设置各种时钟开关,暂时不用PLL
rREG_CLK_SRC0 = 0x0;
// 2 设置锁定时间,使用默认值即可,设置PLL后,到目标时钟频率时,
即可锁定时间。
rREG_APLL_LOCK = 0x0000ffff;
rREG_MPLL_LOCK = 0x0000ffff;
// 3 设置分频
// 清bit[0~31]
rREG_CLK_DIV0 = 0x14131440;
// 4 设置PLL
// FOUT = MDIV*FIN/(PDIV*2^(SDIV-1))=0x7d*24/(0x3*2^(1-1))=1000 MHz
rREG_APLL_CON0 = APLL_VAL;
// FOUT = MDIV*FIN/(PDIV*2^SDIV)=0x29b*24/(0xc*2^1)= 667 MHz
rREG_MPLL_CON = MPLL_VAL;
// 5 设置各种时钟开关,使用PLL
rREG_CLK_SRC0 = 0x10001111;
}