首先需要知道时钟的概念:
1、是用来同步系统信号;
就举例来说:
如果你cpu用i2c传输一个数据给从机设备,那么你传输数据时从设备怎么知道数据有没有到达,多久检测一次数据线??这个就需要时钟同步,起的作用就是我cpu传输一位数据就有一位时钟触发从设备;
2、
2440soc这么多器件时钟是如何分配??
目的:
配置cpu时钟为 400M AHB 100M APB 50M
2440系统时钟分配:
晶振->锁相环(主MPLL)->分频得到 Fclk Hclk Pclk ;
2440时钟:
Operating Frequency
· Fclk Up to 400MHz cpu运行时钟
· Hclk Up to 136MHz 给AHB总线上挂载的设备提供时钟
· Pclk Up to 68MHz 给APH总线挂载的设备停工时钟;
时钟来源:
由上图可知:
时钟来源可以有两个:
1、外部引脚提供时钟信号 EXTCLK
2、晶振提供时钟信号 XTIpll
经过OM[3:2]配置数据那种时钟源如下图(使用的板子是将OM[3:2]都接地,所以是晶振(12M)提供时钟):
3、经过主锁相环(MPLL)->FCLK(给cpu ARM920T)->HDIVN->HCLK AHB总线
主锁相环(MPLL)->FCLK(给cpu ARM920T)->->PDIVN->PCLK APB总线
Usb锁相环(UPLL)单独给usb评率配置;
如何设置cpu等其他外围器件的时钟?
1、步骤
(1)OM硬件接地已经确定;需要配置MPLL,配置MPLL需要用到P:M:S看下什么是PMS
这个是锁相环PLL 晶振输入对应输出评率时 MPS的取值对应表;
如我们晶振12M要输出FCLK400M M:P:S=92:1:1
利用公式:
Mpll = (2 * m * Fin) / (p * 2S)
m = (MDIV + 8), p = (PDIV + 2), s = SDIV
得到对应的MPLL值写入MPLLCON寄存器;
(2)配置HDIVN PDIVN 是在CLKDIVN寄存器中
我们目的是配置cpu时钟为 400M , AHB=100M , APB=50M
通过配置HDIVN配置为10,确定CADMIVN==0 得到HCLK
通过配置PDIV配置为1 得到PCLK
之后就是代码了:
.text
.global _start
_start:
/* 关闭看门狗 */
ldr r0, =53000000
ldr r1, =0
str r1,[r0]
/* 设置 CLKDIVN=0x4C000014 HCLK =FCLK/4 PCLK=HCLK/2
* HDIVN[2:1] =10 PDIVN[0] = 1
*/
ldr r0, =0x4C000014 //吧0x4C000014存入r0
ldr r1, =0x5
str r1, [r0] //r1的值0x5写入0x4C000014
/* 设置锁定时间 locktime 0x4C000000 默认锁定时间 */
ldr r0, =0x4C000000
ldr r1, =0xFFFFFFFF
str r1, [r0]
/* 设置cpu 工作模式 */
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000
mcr p15,0,r0,c1,c0,0
/*设置锁相环输出频率为 400M */
ldr r0, =0x4C000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1, [r0]
/* 设置内存: sp 栈 */
/* 分辨是nor/nand启动
* 写0到0地址, 再读出来
* 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
* 否则就是nor启动
*/
/*mov r1, #0
ldr r0, [r1] /* 读出原来的值备份 */
str r1, [r1] /* 0->[0] */
ldr r2, [r1] /* r2=[0] */
cmp r1, r2 /* r1==r2? 如果相等表示是NAND启动 */
*/
ldr sp, =0x4096 /* 先假设是nor启动 */
b main
moveq sp, #4096 /* nand启动 */
streq r0, [r1] /* 恢复原来的值 */
halt:
b halt
c代码测试程序: 通过不同的频率查看led闪烁的时间间隔;
/* 配置输出方式寄存器*/
#define GPFCON (*(volatile unsigned int *)0x56000050)
#define GPFDAT (*(volatile unsigned int *)0x56000054)
void delay(int cnt)
{
while(cnt--);
}
int main(void)
{
GPFCON = 0x500;
GPFDAT =0;
delay(100000);
GPFDAT =0xF0;
delay(100000);
GPFDAT =0;
delay(100000);
GPFDAT =0xF0;
return 0;
}
all:
arm-linux-gcc -c -o led_on.o led_on.c
arm-linux-gcc -c -o clock.o clock.S
arm-linux-ld -Ttext 0 clock.o led_on.o -o led_on.elf
arm-linux-objcopy -O binary -S led_on.elf led_on.bin
arm-linux-objdump -D led_on.elf > led_on.dis
clean:
rm *.bin *.o *.elf *.dis