ARM时钟
来源:互联网 发布:js如何存map 编辑:程序博客网 时间:2024/06/11 01:01
时钟作用:系统中的设备需要时间进行同步。
时钟的产生:PLL(锁相环),利用外部晶体加上一些电路,对晶体产生的特定频率进行分频或加倍。晶振相对来说结构简单,但是受频率受到晶体制约,得到很高的频率的晶振价格高,用锁相环难度价格低些。
外部晶振作为时钟源,S3c2440有两个锁相环:MPLL和UPLL,UPLL用于USB设备。MPLL用于CPU及其 外围器件,通过MPLL会产生三个时钟频率:FCLK,HCLK,PCLK,FCLK最高533MHz用于CPU核(CPU频率),HCLK用于高速总线,PCLK用于低俗的外围设备。
一旦上电之后,CPU频率等于外部晶振频率12Mz,CPU工作后配置PLL,在A点完成配置,完成后CPU频率降成0,这段时间为lock time,在这段时间CPU未工作,lock time结束后CPU频率提高,,因为配置PLL时,提高输出频率400Mz,这就是时钟启动流程。
PLL配置涉及3个寄存器,LOCKTIME,MOLLCON,CLKDIVN。
1:LOCKTIME:确定启动时LOCKTIME时间。
2:MPLLCON:用于设置FCLK和FIN(输入时钟频率晶振)。计算关系:
MPLL(FCLK) = (2 * m * Fin) / (p*2^s) 其中m=MDIV+8,p=PDIV+2,s=SDIV。
通过MPLLCON的设置就可以设置MDIV、PDIV、SDIV。
3:CLKDIVN:用于设置FCLK,PCLK,HCLK三这个关系。
设计定时器:s3c2440有5个16位寄存器,其中定时器1,2,3有PWM功能,都有一个输出引脚,控制引脚上电压的变化,定时器4没有输出引脚,定时器的时钟源为PCLK,经过两次分频。
定时器初始化,让它在一定时间后超时,超时后产生中断,就可以执行中断处理函数。
1:设置定时器时钟频率,比如为50,表示每一秒把初始值减50,
2:设置定时器计数值。比如为100,频率50,则在2s后超时。
3:设置中断处理函数。
定时器输出时钟频率=PCLK/{prescaler + 1}/{divider value}
prescaler :TCFG0中设置。divider value:TCFG1设置。
计数值初始化:TCMPB0 TCNTB0 存放初始值,启动定时器后,初始值导入TCMP0,TCNT0,每次时钟频率TCNT0减一,直到与TCMP0相等,产生中断,有Timer n auto reload on打开可以再一次重新计数,TCON启动寄存器。
定时器程序(每隔0.5s闪烁一次):
void Timer0_init(void);static void __irq IRQ_Timer0_Handle(void);void Set_Clk(void);static void cal_cpu_bus_clk(void);void Led1_init(void);void Led1_run(void);void delay(int times) { int i,j; for(i=0;i<times;i++) for(j=0;j<400;j++);}void Main(void) { Set_Clk(); //系统时钟设置,通过几个寄存器选定CPU、外部总线频率,FCLK,PCLK,HCLK MMU_Init(); Led1_init(); Timer0_init();while(1);} void Timer0_init(void) { //Timer 0 init,设置两个寄存器 rTCFG0 = 49; //pclk/(49+1),第一次分频 rTCFG1 = 0x03; //16分频=62500HZ 第二次分频 rTCNTB0 = 62500/2; //设置计数值,TCNTB0[15:0]=计数值 rTCMPB0 = 0; rTCON |=(1<<1); //将计数值装入TCNTB0、TCMPB0 rTCON =0x09; rPRIORITY = 0x00000000; // 默认优先级 rINTMOD = 0x00000000; // 默认优先级 ClearPending(BIT_TIMER0); pISR_TIMER0 = (U32)IRQ_Timer0_Handle; EnableIrq(BIT_TIMER0); }static void __irq IRQ_Timer0_Handle(void) { Led1_run();ClearPending(BIT_TIMER0); }void Set_Clk(void) {int i;U8 key;U32 mpll_val = 0 ;i = 2 ; //don't use 100M! //boot_params.cpu_clk.val = 3;switch ( i ) {case 0://200key = 12;mpll_val = (92<<12)|(4<<4)|(1);break;case 1://300key = 13;mpll_val = (67<<12)|(1<<4)|(1);break;case 2://400key = 14;mpll_val = (92<<12)|(1<<4)|(1);break;case 3://440!!!key = 14;mpll_val = (102<<12)|(1<<4)|(1);break;default:key = 14;mpll_val = (92<<12)|(1<<4)|(1);break;}//init FCLK=400M, so change MPLL firstChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3); //set the register--rMPLLCONChangeClockDivider(key, 12); //the result of rCLKDIVN [0:1:0:1] 3-0 bitcal_cpu_bus_clk(); //HCLK=100M PCLK=50M}static void cal_cpu_bus_clk(void) {static U32 cpu_freq; static U32 UPLL;U32 val;U8 m, p, s;val = rMPLLCON;m = (val>>12)&0xff;p = (val>>4)&0x3f;s = val&3;//(m+8)*FIN*2 不要超出32位数!FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100; //FCLK=400M FIN=12000000val = rCLKDIVN;m = (val>>1)&3;p = val&1;val = rCAMDIVN;s = val>>8;switch (m) {case 0:HCLK = FCLK;break;case 1:HCLK = FCLK>>1;break;case 2:if(s&2)HCLK = FCLK>>3;elseHCLK = FCLK>>2;break;case 3:if(s&1)HCLK = FCLK/6;elseHCLK = FCLK/3;break;}if(p)PCLK = HCLK>>1;elsePCLK = HCLK;if(s&0x10)cpu_freq = HCLK;elsecpu_freq = FCLK;val = rUPLLCON;m = (val>>12)&0xff;p = (val>>4)&0x3f;s = val&3;UPLL = ((m+8)*FIN)/((p+2)*(1<<s));UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;}void Led1_init(void) { rGPBCON &= ~(0x3<<10); rGPBCON |= (0x1<<10);}void Led1_run(void) { //rGPBDAT = rGPBDAT^(0x1<<5); if(rGPBDAT &(1<<5)) rGPBDAT &=~(1<<5); else rGPBDAT |=(1<<5);}
- ARM时钟
- ARM时钟问题
- ARM-Linux时钟初始化
- Arm的时钟
- ARM时钟 S3C2440
- ARM时钟体系
- ARM时钟管理
- ARM中的时钟
- ARM-Linux时钟初始化
- ARM时钟系统(S5PV210)
- ARM之时钟体系
- ARM-S3C2410硬件之时钟
- s3c2410 ARM 时钟与设置
- ARM裸机之系统时钟
- ARM时钟及电源管理
- 专题7-ARM时钟初始化
- ARM跑快了 --- 时钟初始化
- ARM学习之时钟体系结构
- js和css的顺序关系
- 黑马程序员---图形用户界面GUI
- 调色板
- Hadoop生态圈
- usaco 1.33
- ARM时钟
- 30分钟学MongoDB系列 ——性能优化和性能监控篇
- 整数连接
- Android之ContentProvider总结
- 黑客与画家
- Python——条件、循环和其他语句
- 线段树点修改uva12299
- Windows socket网络编程
- Android之LinearLayout内部控件间距设置