开发板学习Day9:第010课 掌握ARM芯片时钟体系

第001节_S3C2440时钟体系结构

S3C2440是System On Chip(SOC),在芯片上不仅仅有CPU还有一堆外设。
至于有哪些外设,可以查看参考手册。在S3C2440参考手册的第一章PRODUCT OVERVIEW里面有个BLOCK DIAGRAM图:
这里写图片描述

可以把该图分为上中下三块,上面的是与CPU密切相关的,工作于FCLK;中间的一些对性能要求较高的设备,像LCD显示、相机等,在AHB BUS,H即为High,高速之意,工作于HCLK;下面的是一些对性能要求不那么高的低速设备,在APB BUS,P即为Peripheral之意,工作在PCLK。

在参考手册的特性里介绍了S3C2440的工作频率,Fclk最高400MHz,Hclk最高136MHz,Pclk最高68MHz。

如何得到以上的三种时钟?
硬件电路上有个12M的晶振,作为时钟源产生12MHz的频率,经过SOC的PLL(锁相环)倍频产生Fclk、Hclk、Pclk。
在Clock Generator Block Diagram展示了时钟的产生。

这里写图片描述

从左上角看起,晶振和一个外部时钟接在一个选择器上,这个选择器通过OM[3:2]的值来决定选择哪个时钟源。通过查看芯片手册我们可以找到选择关系,如下图所示:
这里写图片描述

再查找原理图如下(图中黄色部分),我们发现OM[3:2]两个引脚接地,即为00,所以默认状态下,MPLL和UPLL都使用晶振作为时钟源。
这里写图片描述

时钟信号输入关系如下图所示:
这里写图片描述

第002节_编程提高运行时钟

怎么编程控制MPLL、HDIV、PDIV,使FCLK=400MHz,HCLK=100MHz,PLCK=50MHz?

答:需要设置 MPLLCON 使 FCLK=400MHz,设置 CLKDIVN 使 HCLK=FCLK/4=100MHZ、PCLK=FCLK/8=50MHZ。

开发板上电启动顺序:
这里写图片描述
1,上电之后(Power由低电平变为高电平)复位信号会在复位芯片的作用下维持一段时间的低电平,待电源稳定之后输出高电平。
2,上电后,晶振便开始起振;此时的FCLK由OM[3:2]的值默认为00使得FCLK=12MHZ(晶振)。此时CPU未开始运行,当复位信号输出高电平时,CPU才开始运行。
3,PLL锁存OM[3:2]的值,同时CPU开始运行。
4,设置PLL,此时,时钟进入LOCK TIME而停振,CPU也停止工作;
5,在LOCK TIME中,PLL开始工作,并在LOCK TIME结束前达到稳定输出值。
6,LOCK TIME结束后,FCLK=PLL的OUTPUT frequence,CPU在新的时钟频率下稳定工作;

第一步:设置MPLLCON控制FCLK
在设置MPLLCON之前呢,我们由芯片手册第七章的NOTES可知:
这里写图片描述
如果HDIVN不为0,那么CPU必须工作在异步模式(使用下述指令来设置),否则CPU使用HCLK的频率来工作:

mrc p15,0,r0,c1,c0,0
orr r0,r0,#r1_nf:or:r1_ia//其值为0xc0000000
mcr p15,0,r0,c1,c0,0 

下面我们设置MPLLCON:

这里写图片描述

先看最下面的·PLL VALUE SELECTION TABLE·:我们的晶振输入频率(Input Frequency)为12MHZ,而我们想要得到的输出频率(Output Frequency )为400MHZ,所以我们的MDIV=92(0x5c),PDIV=1,SDIV=1。

这里写图片描述
由上图可知:

m=(92+8)=100
p=(1+2)=3
s=1
MPLL=(2*100*12)/(3*2^1)=400MHZ

接下来,我们编写代码:

//MDIV[19:12]=92(0x5c),PDIV[9:4]=1,SDIV[1:0]=1
//MPLLCON(0X4C000004)=(92<<12)|(1<<4)|(1<<0)
ldr r0,=0x4c000004
ldr r1,=(92<<12)|(1<<4)|(1<<0)
str r1,[r0]

第二步:设置CLKDIVN寄存器设置HCLK和PHCLK

这里写图片描述

FCLK我们已经设置好,为400MHZ,所以为了
让HCLK=FCLK/4=100MHZ,应将HDIVN[2:1]=10 CAMDIVN[9]=0;由下图可知CAMDIVN[9]的默认值为0,所以忽略。
让PCLK=HCLK/2=50MHZ,应将PDIVN[0]=1。

下面我们来编程:

//HDIVN[2:1]=10 CAMDIVN[9]=0;
//CLKDIVN(0X4C000014)=0X5
ldr r0,=0x4c000014
ldr r1,=0x5
str r1,[r0]

第三步:设置LOCK TIME
LOCK TIME使用默认值即可。
这里写图片描述

//LOCKTIME(0x4C000000)=0XFFFFFFFF
ldr r0,=0x4c000000
ldr r1,=0xFFFFFFFF
str r1,[r0]

完整代码如下:

start.S:

.text
.global _start
_start:
    //首先关闭看门狗
    ldr r0,=0x53000000
    mov r1,#0
    str r1,[r0]

    //首先,设置CPU工作在异步模式
    mrc p15,0,r0,c1,c0,0
    orr r0,r0,#0xc0000000//其值为0xc0000000
    mcr p15,0,r0,c1,c0,0 

    //第一步,设置MPLL
    //MDIV[19:12]=92(0x5c),PDIV[9:4]=1,SDIV[1:0]=1
    //MPLLCON(0X4C000004)=(92<<12)|(1<<4)|(1<<0)
    ldr r0,=0x4c000004
    ldr r1,=(92<<12)|(1<<4)|(1<<0)
    str r1,[r0]

    //第二步,设置CLKDIVN
    //HDIVN[2:1]=10 CAMDIVN[9]=0;
    //CLKDIVN(0X4C000014)=0x5
    ldr r0,=0x4c000014
    ldr r1,=0x5
    str r1,[r0]

    //LOCKTIME(0x4C000000)=0XFFFFFFFF
    ldr r0,=0x4c000000
    ldr r1,=0xFFFFFFFF
    str r1,[r0]


    //然后判断启动方式
    ldr r1,=0
    ldr r0,[r1]
    str r1,[r1]
    ldr r2,[r1]
    cmp r1,r2
    ldr sp,=0x40000000+4096
    moveq sp,#4096
    streq r0,[r1]


    bl led_clk

halt:
    b halt

led_clk.h:

#define GPFCON (*((volatile int*)0x56000050))
#define GPFDAT (*((volatile int*)0x56000054))

led_clk.c

#include"led_clk.h"

void Delay(volatile int n)
{
  while(n--);
}
void led_clk()
{

    GPFCON &= ~((3<<8)|(3<<10)|(3<<12));
    GPFCON |= ((1<<8)|(1<<10)|(1<<12));
    int val=0;

    while(1)
    {
       GPFDAT &= ~(7<<4);
       GPFDAT |= (~val << 4);

       Delay(100000);
       ++val;

       if(val==8)
        val=0;
    }
}

makefile:

all:
    arm-linux-gcc -c -o led.o led_clk.c
    arm-linux-gcc -c -o start.o start.S
    arm-linux-ld -Ttext -0 start.o led.o -o led.elf
    arm-linux-objcopy -O binary -S led.elf led.bin
    arm-linux-objdump -D led.elf > led.dis
clean:
    rm -rf *.bin *.o *.elf *.dis

猜你喜欢

转载自blog.csdn.net/rdgfdd/article/details/81222059