S3C2440的裸奔--系统时钟篇

S3C2440的裸奔
                                               --系统时钟篇

  Author       : He YiJun  (storysnail<at>gmail.com QQ:363559089)
LingYing Develop Team : 7fane Team (http://www.7fane.com) Editor : Yang QiuXi Art Designer : He YiJun License : 7fane Team License 1.0 Last Update : 2012-06-07




参考书目:
    人民邮电出版社          《嵌入式Linux应用开发完全手册》             --韦东山著
    机械工业出版社          《嵌入式Linux应用开发全程解析与实战》      --吴士力、刘奇、朱兰著
    电子工业出版社          《嵌入式Linux系统实用开发》                 --何永琪等著
    人民邮电出版社          《Linux设备驱动开发详解》                   --宋宝华著
    电子工业出版社          《ARM嵌入式常用模块与综合系统设计实例精讲》--张绮文、解书钢著
    电子工业出版社          《嵌入式系统Linux内核开发实战指南》        --王洪辉著
    北京航空航天大学出版社 《ARM LINUX入门与实践》                    --方强、程昌南著
    北京航空航天大学出版社 《嵌入式底层软件开发》                        --杨铸、唐攀著


    可能是宅的太久了吧,这几天情绪非常低落,直接影响我的学习进度,所以只是看了那么一点点内容!mini2440在没有开启时钟前,全靠一个板载的 12MHz晶振提供频率来运行。也就是CPU,内存,UART等等都运行在12MHz下面,这显然效率非常低,要知道S3C2440正常可以工作在 400MHz下呢,两者相差非常之大。

    s3c2440的时钟系统由3部分组成,
    内核工作频率:由FCLK提供,最高400MHz,为ARM920T内核使用的工作频率
    AHB总线频率:由HCLK提供,最高100MHz,为AHB总线上挂接的硬件提供工作频率,例如内存,NAND,LCD控制器等硬件
    APB总线频率:由PCLK提供,最高50MHz,为APB总线上挂接的硬件提供工作频率,例如UART串口,WATCHDOG等

    s3c2440的PLL:
    s3c2440时钟源为板载的12MHz晶振,为了得到更高的时钟频率,可通过PLL来提高频率,PLL有如下两种:
    MPLL:用来产生FCLK、HCLK、PCLK
    UPLL:用来产生USB设备的工作频率

    寄存器设置部分略,详见手册或相关书籍。

    下面是启动代码:

复制代码
@******************************************************************************
@ File:crt0.S
@ 功能:初始化系统时钟,然后转入C程序
@******************************************************************************       

.equ        WTCON,       0x53000000     @看门狗控制寄存器
.equ        WTDAT,       0x53000004     @看门狗数据寄存器
.equ        WTCNT,       0x53000008     @看门狗计数寄存器
.equ        LOCKTIME,    0x4c000000     @变频锁定时间寄存器
.equ        MPLLCON,     0x4c000004     @MPLL寄存器
.equ        CLKDIVN,     0x4c000014     @分频比寄存器

.text
.global _start
_start:
            ldr     r0, =WTCON          @ 关闭WATCHDOG
            mov     r1, #0x0                     
            str     r1, [r0]            @ 写入0,禁止WATCHDOG,否则CPU会不断重启

        bl      init_clock          @初始化系统时钟
            
            ldr     sp, =1024*4         @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
                                        @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
            bl      main                @ 调用C程序中的main函数
halt_loop:
            b       halt_loop


init_clock:
            @ 设置锁频时间
        ldr    r0, =LOCKTIME        @取得LOCKTIME寄存器地址
        ldr    r1, =0x00ffffff       @设置锁定时间
        str    r1, [r0]             @将r1中的数据写入r0  

        @设置FCLK,HCLK,PCLK三者之间的比例,本来还需要设置CAMDIVN寄存器,
        @但这里设置成1:4:8,所以CAMDIVN使用默认值就可以了!
        ldr    r0, =CLKDIVN         @取得CLKDIVN寄存器地址
        mov    r1, #0x05            @设定比例
        str    r1, [r0]    
    
        @修改CPU总线模式
        mrc    p15, 0, r1, c1, c0, 0
        orr    r1, r1, #0xc0000000
        mcr    p15, 0, r1, c1, c0, 0

        @倍频到400MHz  
        ldr    r0, =MPLLCON         @MPLL控制寄存器
        ldr    r1, =0x0005c011
        str    r1, [r0]
        mov    pc, lr               @ 返回

@******************************************************************************
复制代码


下面是C程序,其实就是上次那个leds.c程序,只是更改个名字而已!

复制代码
/******************************************************************************
SysClk.c
******************************************************************************/

#define GPBCON (*(volatile unsigned *)0x56000010)
#define GPBDAT (*(volatile unsigned *)0x56000014)
#define GPBUP  (*(volatile unsigned *)0x56000018)

#define    GPB5_out    (1<<(5*2))
#define    GPB6_out    (1<<(6*2))
#define    GPB7_out    (1<<(7*2))
#define    GPB8_out    (1<<(8*2))

void delay(unsigned long dly)
{
    for(;dly>0;dly--);
}

int main(void)
{

    GPBCON = GPB5_out|GPB6_out|GPB7_out|GPB8_out;
    //GPBUP=0xFFFF;
    GPBUP=0x0000;

    while(1)
    {
        GPBDAT&=~0x20;
        delay(30000);
        GPBDAT&=~0x60;
        delay(30000);
        GPBDAT&=~0xE0;
        delay(30000);
        GPBDAT&=~0x1E0;
        delay(30000);
        GPBDAT|=0x20;
        delay(30000);
        GPBDAT|=0x60;
        delay(30000);
        GPBDAT|=0xE0;
        delay(30000);
        GPBDAT|=0x1E0;
        delay(30000);

    }
    return 0;
}
/******************************************************************************/
复制代码

 





然后是编译用的Makefile.

复制代码
#******************************************************************************
#Makefile
#******************************************************************************
CFLAGS := -Wall -Wstrict-prototypes -fomit-frame-pointer -ffreestanding
SysClk.bin : crt0.S  SysClk.c
    arm-linux-gcc $(CFLAGS) -c -o crt0.o crt0.S
    arm-linux-gcc $(CFLAGS) -c -o SysClk.o SysClk.c
    arm-linux-ld -Ttext 0x0000000 crt0.o SysClk.o -o SysClk_elf
    arm-linux-objcopy -O binary -S SysClk_elf SysClk.bin
    arm-linux-objdump -D -m arm  SysClk_elf > SysClk.dis
clean:
    rm -f   SysClk.dis SysClk.bin SysClk_elf *.o
#****************************************************************************** 
复制代码


编译之后运行一下,比原来的leds快了很多吧!

版权声明:只有当您阅 读、理解并愿意遵守7fane Team License 1.0授权协议之后, 您才拥有了获取、使用、复制、分发或通过通信网络传播这篇文章的权利。您可以访问我们的网站http://www.7fane.com了解相关授权协议, 在网站上还有更多的由7fane小组原创的技术文章, 我们希望这些内容能对您有所帮助并给您带来快乐,同时我们也希望获得您的指点、 提问和补充。
posted @ 2013-03-17 21:33  天涯海角路  阅读(180)  评论(0)    收藏  举报