clock.h
#ifndef _CLOCK_H_
#define _CLOCK_H_
/*System Clock Pins*/
#define APLL_LOCK ( *(volatile unsigned long *)0xE0100000 )
#define MPLL_LOCK ( *(volatile unsigned long *)0xE0100008 )
#define APLL_CON0 ( *(volatile unsigned long *)0xE0100100 )
#define MPLL_CON ( *(volatile unsigned long *)0xE0100108 )
#define CLK_SRC0 ( *(volatile unsigned long *)0xE0100200 )
#define CLK_DIV0 ( *(volatile unsigned long *)0xE0100300 )
void sys_clock_init();
#endif //_CLOCK_H_
clock.c
#include"clock.h"
/*S5PV210有三个时钟域:
主系统时钟(MSYS) 显示系统时钟(DSYS),外设相关时钟(PSYS);
有4路PLL时钟
APPL(驱动MSYS),MPLL(驱动DSYS时钟域),EPLL(产生audio时钟),VPPL(主要video时钟);
FOUT=MDIV*FIN/(PDIV*2^(SDIV-1))
时钟关系:
MSYS:
-freq(ARMCLK) =freq(MOUT_MSYS)/N(1<N<8);
-freq(HCLK_MSYS) =freq(ARMCLK)/N(1<N<8);
-freq(PCLK_MSYS) =freq(HCLK_MSYS)/N(1<N<8);
-freq(HCLK_IMEM) =freq(HCLK_MSYS)/2;
DSYS:
-freq(HCLK_DSYS) =freq(MOUT_DSYS)/N(1-16);
-freq(PCLK_DSYS) =freq(HCLK_DSYS)/N(1-8);
PSYS:
freq(HCLK_PSYS)=freq(MOUT_PSYS)/N(1<N<16)
freq(PCLK_PSYS)=freq(HCLK_PSYS)/N(1<N<8);
freq(PCLK_ONENAND)=freq(HCLK_PSYS)/N(1<N<8);
*/
/*
* sys_clock_init()函数的总体设置时钟情况如下:
* ARMCLK=1000MHz, HCLKM=200MHz, HCLKD=166.75MHz
* HCLKP =133.44MHz, PCLKM=100MHz, PCLKD=83.375MHz,
* PCLKP =66.7MHz
*/
/*配置步骤:
1.设置系统锁相环电路(PLL)的锁定时间
2.配置PLL
3.选择时钟源
4.配置MDIV,PDIV,SDIV的分频系数。
每个时钟为了方便配置都给了写推荐值
例如:
APLL:
FIN TargetFout P M S FOUT (MHZ)
24 1000 3 125 1 1000
FOUT=125*24/(3*2^(1-1))=1000;
void sys_clock_init()
{
/*
* 由Fin通过PLL上升到一定的频率所需要的锁定时间
*/
APLL_LOCK = 0xFFFF;
MPLL_LOCK = 0xFFFF;
/*
* 使能APLL控制器,使能锁标志位,MDIV = 0x7d,PDIV = 0x3,SDIV = 0x1
* FOUTapll = MDIV * FIN / (PDIV*2^(SDIV-1))
* = 0x7d*24/(0x3*2^(0x1-1))
* = 125*24/(3*2) = 1000MHz
*/
/*
bit[31]:使能位;
bit[29]:锁定位;
bit[25:16]:MDIV;
bit[13:8]:PDIV;
bit[2:0]:SDIV;*/
APLL_CON0 = (1 << 31)|(1 << 29)|(0x7d << 16)|(0x3 << 8)|(0x1 << 0);
/*
* 使能MPLL控制器,使能锁标志位,MDIV = 0x29b,PDIV = 0xc,SDIV = 0x1
* FOUTmpll = MDIV * FIN / (PDIV*2^SDIV)
* = 0x29b*24/(0xc*2^1)
* = 667*24/(12*2) = 667MHz
*/
MPLL_CON = (1 << 31)|(1 << 29)|(0x29b << 16)|(0xc << 8)|(0x1 << 0);
/*
* 时钟源的设置
* ONENAND_SEL = HCLK_DSYS 高位
* MUX_PSYS_SEL = SCLKMPLL
* MUX_DSYS_SEL = SCLKMPLL /|\
* MUX_MSYS_SEL = SCLKAPLL |
* VPLL_SEL = FOUTVPLL |
* EPLL_SEL = FOUTEPLL |
* MPLL_SEL = FOUTMPLL
* APLL_SEL = FOUTAPLL 低位
*/
CLK_SRC0 = (1 << 28)|(1 << 12)|(1 << 8)|(1 << 4)|(1 << 0);
/*
* 设置系统时钟分频系数
* PCLK_PSYS_RATIO = 0x1 高位
* HCLK_PSYS_RATIO = 0x4
* PCLK_DSYS_RATIO = 0x1 /|\
* HCLK_DSYS_RATIO = 0x3 |
* PCLK_MSYS_RATIO = 0x1 |
* HCLK_MSYS_RATIO = 0x4 |
* A2M_RATIO = 0x4
* APLL_RATIO = 0x0 低位
*/
CLK_DIV0 = (0x1 << 28)|(0x4 << 24)|(0x1 << 20)|(0x3 << 16)|(0x1 << 12)|(0x4 << 8)|(0x4 << 4)|(0 << 0);
}
#include"led.h"
#include"clock.h"
/* 如果去掉这个注释,流水灯的速度会慢很多
* 读者可以尝试去掉,观察流水的速度。
*/
//#define CLOCK_INIT
int main()
{
led_init(); //初始化LED,让LED初始灭状态
#ifndef CLOCK_INIT
sys_clock_init(); //系统时钟初始化函数
#endif //CLOK_INIT
led_flow_water();
return 0;
}