ARMBoot-1.1.0 在 mini2440 开发板上的移植 之稻草人手记

本文档详细记录了将ARMBoot 1.1.0移植到mini2440开发板的步骤,包括移植目标、版本、开发环境和具体移植操作。移植涉及驱动串口、网络芯片dm9000、内核下载和启动Linux kernel。通过修改配置文件、代码文件以及添加个性化启动信息,最终实现从NandFlash启动。
摘要由CSDN通过智能技术生成

ARMBoot-1.1.0 在 mini2440 开发板上的移植 之稻草人手记
< snallieATtomDOTcom >

作为U-boot的鼻祖-ARMboot以其小巧玲珑(代码压缩包仅有400K多),但又麻雀虽小,五脏俱全,不失为研究U-boot的第一步,
而且在ARMboot中处处还能看到U-boot的影子。好啦,开始我们的移植之旅吧。

移植目标:      驱动串口;驱动网络芯片dm9000;实现内核的下载(uImage);实现启动 Linux kernel(zImage),实现Nand Flash启动
移植版本:        ARMboot-1.1.0
ARMboot在哪:   http://www.sourceforge.net/projects/armboot
交叉编译器:    arm-linux-gcc 2.95.3 (在该版本下可以一次编译成功,所以采用该版本的交叉编译器)
开发板配置:    RAM:64MB,Nor:2MB,Nand:64MB,Processor:Samsung S3C2440网卡芯片:dm9000
操作系统环境:  RedHat Linux 9.0

环境查看:
编译器:
[root@arms root]# arm-linux-gcc -v
Reading specs from /usr/local/arm/2.95.3/lib/gcc-lib/arm-linux/2.95.3/specs
gcc version 2.95.3 20010315 (release)

源代码包:
[root@arms arms]# ls -l
total 428
-rw-r--r--    1 root     root       431099 Feb 25  2007 armboot-1.1.0.tgz

解压源码包:
[root@arms arms]# tar zxvf armboot-1.1.0.tgz

进入源码目录:(之后的所用工作均在该目录下完成)
[root@arms arms]# cd armboot-1.1.0
[root@arms armboot-1.1.0]#

armboot-1.1.0已经支持smdk2410开发板,该开发板和mini2440有一定的相似性,我们在
在SMDK2410开发板的基础上进行移植。

测试smdk2410是否能通过编译:
[root@arms armboot-1.1.0]# make distclean; make smdk2410_config ; make all

通过编译,查看生成的文件如下:
[root@arms armboot-1.1.0]# ls -altr
-rwxr-xr-x    1 root     root       224812 May 24 08:43 armboot.srec
-rw-r--r--    1 root     root        28391 May 24 08:43 armboot.map
-rw-r--r--    1 root     root       210779 May 24 08:43 armboot.hex
-rwxr-xr-x    1 root     root        74916 May 24 08:43 armboot.bin
-rwxr-xr-x    1 root     root        91185 May 24 08:43 armboot

其中的armboot.bin即为最终的可以烧写到NandFlash的文件,由于代码还需修改,现在这个文件还不能适应mini2440的开发板环境,
上面的过程只是验证了smdk2410的配置即程序文件可以在arm-linux-gcc 2.95.3顺利编译通过,我们还需对代码做进一步的修改使得
其可以运行在到MINI2440上。

下面开始进行MINI2440的移植,为便于查看,将所涉及到的代码的行首都加了行号标示。
*************************************************************************************************************************************************
** 初步移植,复制关于SMDK2410的全部文件,并做相应地修改,在smdk2410的基础上构建MINI2440的代码环境
*************************************************************************************************************************************************
0)    清除上面的编译结果:
[root@arms armboot-1.1.0]# make distclean

1)    复制smdk2410_config的配置文件(注:所有板子的配置文件均在include/configs下)
[root@arms armboot-1.1.0]# cp include/configs/config_smdk2410.h  include/configs/config_mini2440.h

复制完成后在config_mini2440.h做一个简单的修改标记-该变提示符:(建议:修改时先做做备份-即注释掉原来的代码,而后改成新的),
可用如下的sed 命令直接修改(用sed脚本修改只可执行1遍,切勿多次执行!)
[root@arms armboot-1.1.0]# sed -i'~'  -e "/^/(#define/tCFG_PROMPT..*/)/ {N; s//(..*/)/n//1 snallie, `date +%F_%H%M%S_%a`/n/1 snallie, `date +%F_%H%M%S_%a`/n/g; s/SMDK2410/ARMboot@MINI2440/2 }"  include/configs/config_mini2440.h

或者用vi进行全屏幕编辑修改:
[root@arms armboot-1.1.0]# vi +99 include/configs/config_mini2440.h

具体修改的位置为:

    99 #define CFG_PROMPT  "SMDK2410 # "   /* Monitor Command Prompt       */
为:
    99  //#define       CFG_PROMPT              "SMDK2410 # "   /* Monitor Command Prompt       */ // snallie, 2011-05-24_090111_Tue
   100  #define CFG_PROMPT              "ARMboot@MINI2440 # "   /* Monitor Command Prompt       */ // snallie, 2011-05-24_090111_Tue

2)    拷贝smdk2410的板级的程序文件为mini2440
[root@arms armboot-1.1.0]# cp -a board/smdk2410/  board/mini2440

3)    修改mini2440的板级的Makefile,文件位置在 board/mini2440/Makefile

    28 OBJS    := smdk2410.o flash.o env.o
为:
    28  # OBJS  := smdk2410.o flash.o env.o # snallie, 2011-05-24_091150_Tue
    29  OBJS    := mini2440.o flash.o env.o # snallie, 2011-05-24_091150_Tue

可用如下的sed 命令直接修改:(用sed脚本修改只可执行1遍,切勿多次执行!)
[root@arms armboot-1.1.0]# sed -i'~' -e "/^/(OBJS/t:= smdk2410.o..*/)/ {N; s//(..*/)/n/# /1 # snallie, `date +%F_%H%M%S_%a`/n/1 # snallie, `date +%F_%H%M%S_%a`/n/g; s/smdk2410/mini2440/2 }" board/mini2440/Makefile

或者用vi进行全屏幕编辑修改:
[root@arms armboot-1.1.0]# vi +28 board/mini2440/Makefile

4)    修改mini2440的板级的文件名,涉及文件为 board/mini2440/smdk2410.c
[root@arms armboot-1.1.0]#  mv board/mini2440/smdk2410.c board/mini2440/mini2440.c

5)    修改顶层的Makefile:找到smdk2410_config,仿照smdk2410_config,添加mini2440_config,如下:

   200  smdk2410_config :       unconfig
   201          @echo "Configuring for $(@:_config=) Board..." ; /
   202          cd include ; /
   203          echo "ARCH  = arm"      > config.mk ;   /
   204          echo "BOARD = smdk2410" >>config.mk ;   /
   205          echo "CPU   = arm920t"  >>config.mk ;   /
   206          echo "#include <configs/config_$(@:_config=).h>" >config.h
   207
   208  # snallie, 2011-05-24_091758_Tue
   209  mini2440_config :       unconfig
   210          @echo "Configuring for $(@:_config=) Board..." ; /
   211          cd include ; /
   212          echo "ARCH  = arm"      > config.mk ;   /
   213          echo "BOARD = mini2440" >>config.mk ;   /
   214          echo "CPU   = arm920t"  >>config.mk ;   /
   215          echo "#include <configs/config_$(@:_config=).h>" >config.h
   216

可用如下的sed 命令直接修改:(用sed脚本修改只可执行1遍,切勿多次执行!)
[root@arms armboot-1.1.0]# sed -i'~'  -e "/smdk2410/,+7 {N;N;N;N;N;N;N; s//(..*/)/n/(..*/)/n/(..*/)/n/(..*/)/n/(..*/)/n/(..*/)/n/(..*/)/n/&/n# snallie, `date +%F_%H%M%S_%a`/n/1/n/2/n/3/n/4/n/5/n/6/n/7/n/g;s/smdk2410/mini2440/3;s/smdk2410/mini2440/3 } " -e "/backup/,/gtar/ {N;N;N; s//(..*/)/n/(..*/)/n/(..*/)/n/#/1/n#/2/n#/3/n/n# snallie, `date +%F_%H%M%S_%a`/n/1/n/2/n/3/n/g; s//"/([^/n]*/)/(/.tar/.gz/)//"+/$/$F-gk-%Y%m%d_%H%M%S/2/2 } " -e "/^armboot.bin/ {N;N;N; s//(..*/)/n/(..*/)/n/(..*/)/n//1/n/2/n# snallie, `date +%F_%H%M%S_%a`/n#/3/n/g }" Makefile

或者用vi进行全屏幕编辑修改:
[root@arms armboot-1.1.0]# vi +200 Makefile

注意:用vi手工修改时候,Makefile中的新添的210~215行的行首为制表符(TAB键),而不是空格,若输入的是空格,则编译出错

6)    程序的版本号有误,修改:include/version.h
改:
    28  #define ARMBOOT_VERSION "ARMboot 1.0.2"
为:
    28  //#define       ARMBOOT_VERSION "ARMboot 1.0.2"
    29    #define ARMBOOT_VERSION "ARMboot 1.1.0" // snallie, 2011-05-24_093229_Tue

可用如下的sed 命令直接修改:(用sed脚本修改只可执行1遍,切勿多次执行!)
[root@arms armboot-1.1.0]# sed -i'~' -e "/1.0.2/ {N; s//(..*/)/n//1/n/1/g; s/1.0.2/"/1.1.0/"/t snallie, `date +%F_%H%M%S_%a`/n/2;}" include/version.h

或者用vi进行全屏幕编辑修改
[root@arms armboot-1.1.0]# vi +28 include/version.h

7)    关于SMDK2410的全部文件复制完成,编译测试:
[root@arms armboot-1.1.0]# make distclean; make mini2440_config; make all

通过编译!

*************************************************************************************************************************************************
** 进一步的移植,完成目标中的全部工作:驱动串口;驱动网络芯片dm9000;实现内核的下载(uImage);实现启动 Linux kernel(zImage),实现Nand Flash启动
*************************************************************************************************************************************************
mini2440板配置初步完成,下面进行具体的移植工作,由于SMDK2410 的代码和MINI2440板子略有出入,SMDK2410代码认为程序是直接在NOR或RAM中运行,
而我们的代码最终是烧写到NandFlash中的,可NandFlash不具有片上执行代码的能力,所以程序启动的第一步就是要将整个的程序从NandFlash中搬移到RAM中,
即TEXT_BASE(配置在board/mini2440/config.mk文件中)的起始地址上去。另外SAMSUNG的S3C2440的处理器在系统启动时候会自动将NandFlash的前4K的代码
移动到内部的4K大小的称为Steppingstone的SRAM中运行,所以搬移用的代码必须放到程序映像的头部的4K的范围内,否则不能正常启动。综上所述,对SMDK2410
代码的改造主要为:实现代码的搬移工作,并将搬移用的代码放到程序映像的头部的4K的范围内;而后要驱动串口,这样我们才能获取到程序的运行时的输出状态
信息,串口驱动不起来等于是瞎子一样,所以串口驱动很重要,有了串口还可通过串口下载小体积的代码;在这之后再驱动网络芯片,实现网络下载代码,启动内核等等。

查看SMDK2410的代码,知道和CPU相关的代码通过在include/configs/config_smdk2410.h的宏定义CONFIG_S3C2410进行控制,和开发板SMDK2410相关的代码通过
在include/configs/config_smdk2410.h的宏定义CONFIG_SMDK2410进行控制,如下所示:

#define CONFIG_S3C2410          1       /* in a SAMSUNG S3C2410 SoC     */
#define CONFIG_SMDK2410         1       /* on an SAMSUNG SMDK2410 Board */

顺着这个线索,我们看看在原有的SMDK2410的代码有那些和CONFIG_S3C2410和CONFIG_SMDK2410的代码,以及它们分布在那些文件中:

和CONFIG_S3C2410相关的:
[root@arms armboot-1.1.0]# grep -rHn CONFIG_S3C2410 *
cpu/arm920t/interrupts.c:36:#elif defined(CONFIG_S3C2410)
cpu/arm920t/serial.c:25:#elif defined(CONFIG_S3C2410)
cpu/arm920t/start.S:134:#elif defined(CONFIG_S3C2410)
cpu/arm920t/start.S:153:#if defined(CONFIG_S3C2410)
include/configs/config_smdk2410.h:43:#define    CONFIG_S3C2410          1       /* in a SAMSUNG S3C2410 SoC     */

和CONFIG_SMDK2410相关的:
[root@arms armboot-1.1.0]# grep -rHn CONFIG_SMDK2410 *
cpu/arm920t/serial.c:45:#elif defined(CONFIG_SMDK2410)
include/configs/config_smdk2410.h:44:#define CONFIG_SMDK2410            1       /* on an SAMSUNG SMDK2410 Board */

看程序的连接脚本: board/mini2440/armboot.lds
    33          .text      :
    34          {
    35            cpu/arm920t/start.o   (.text)
    36            *(.text)
    37            }
   
知道程序的入口在cpu/arm920t/start.S上(现在U-boot中的该文件还保持着原有的风格)
查看该文件,知道整个程序的主要调用顺序为:
cpu_init_crit-> memsetup(在board/mini2440/memsetup.S中)
->start_armboot (在common/board.c中)
void start_armboot(void)进行了一系列的初始化工作,最后就进入  
 for (;;) {
    main_loop(&bd);
    }
主要是接受串口命令,分析并执行命令的循环中。

*************************************************************************************************************************************************
** 各个相关文件的修改 (为了便于说明,代码加了行号(所有新修改的代码均有snallie字样的注释,以示区别,并在代码段的下方对应中文注释说明)
*************************************************************************************************************************************************


cpu/arm920t/start.S的修改

     1    /*
     2     *  armboot - Startup Code for ARM920 CPU-core
     3     *
     4     *  Copyright (c) 2001    Marius Gr鰃er <mag@sysgo.de>
     5     *  Copyright (c) 2002    Alex Z黳ke <azu@sysgo.de>
     6     *  Copyright (c) 2002    Gary Jennejohn <gj@denx.de>
     7     *
     8     * See file CREDITS for list of people who contributed to this
     9     * project.
    10     *
    11     * This program is free software; you can redistribute it and/or
    12     * modify it under the terms of the GNU General Public License as
    13     * published by the Free Software Foundation; either version 2 of
    14     * the License, or (at your option) any later version.
    15     *
    16     * This program is distributed in the hope that it will be useful,
    17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
    18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19     * GNU General Public License for more details.
    20     *
    21     * You should have received a copy of the GNU General Public License
    22     * along with this program; if not, write to the Free Software
    23     * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
    24     * MA 02111-1307 USA
    25     */
    26   
    27   
    28   
    29    #include "config.h"
    30    #include "version.h"
    31   
    32   
    33    /*
    34     *************************************************************************
    35     *
    36     * Jump vector table as in table 3.1 in [1]
    37     *
    38     *************************************************************************
    39     */
    40   
    41   
    42    .globl _start
    43    _start:    b       reset
    44        ldr    pc, _undefined_instruction
    45        ldr    pc, _software_interrupt
    46        ldr    pc, _prefetch_abort
    47        ldr    pc, _data_abort
    48        ldr    pc, _not_used
    49        ldr    pc, _irq
    50        ldr    pc, _fiq
    51   
    52    _undefined_instruction:    .word undefined_instruction
    53    _software_interrupt:    .word software_interrupt
    54    _prefetch_abort:    .word prefetch_abort
    55    _data_abort:        .word data_abort
    56    _not_used:        .word not_used
    57    _irq:            .word irq
    58    _fiq:            .word fiq
    59   
    60        .balignl 16,0xdeadbeef
    61   
    62   
    63    /*
    64     *************************************************************************
    65     *
    66     * Startup Code (reset vector)
    67     *
    68     * do important init only if we don't start from memory!
    69     * relocate armboot to ram
    70     * setup stack
    71     * jump to second stage
    72     *
    73     *************************************************************************
    74     */
    75   
    76    /*
    77     * CFG_MEM_END is in the board dependent config-file (configs/config_BOARD.h)
    78     */
    79    _TEXT_BASE:
    80        .word    TEXT_BASE
    81   
    82    .globl _armboot_start
    83    _armboot_start:
    84        .word _start
    85   
    86    /*
    87     * Note: armboot_end is defined by the (board-dependent) linker script
    88     */
    89    .globl _armboot_end
    90    _armboot_end:
    91        .word armboot_end
    92       
    93    // start of snallie   
    94    .globl _bss_start
    95    _bss_start:
    96          .word __bss_start
    97   
    98    .globl _bss_end
    99    _bss_end:
   100          .word armboot_end
   101    // end of snallie
        /*
         *  94~100行 为新加入的代码,定义了2个全局变量,_bss_start和_bss_end,记录未初始化段的起止地址,其中的
         *  __bss_start和armboot_end 是在连接脚本 board/mini2440/armboot.lds 中定义的,后面309~317行用_bss_start
         *  和_bss_end来进行未初始化段数据的初始清零工作。
         */
  
   102   
   103    /*
   104     * _armboot_real_end is the first usable RAM address behind armboot
   105     * and the various stacks
   106     */
   107    .globl _armboot_real_end
   108    _armboot_real_end:
   109        .word 0x0badc0de
   110   
   111    #ifdef CONFIG_USE_IRQ
   112    /* IRQ stack memory (calculated at run-time) */
   113    .globl IRQ_STACK_START
   114    IRQ_STACK_START:
   115        .word    0x0badc0de
   116   
   117    /* IRQ stack memory (calculated at run-time) */
   118    .globl FIQ_STACK_START
   119    FIQ_STACK_START:
   120        .word 0x0badc0de
   121    #endif
   122   
   123   
   124    /*
   125     * the actual reset code
   126     */
   127   
   128    reset:
   129        /*
   130         * set the cpu to SVC32 mode
   131         */
   132        mrs    r0,cpsr
   133        bic    r0,r0,#0x1f
   134        orr    r0,r0,#0xd3
   135        msr    cpsr,r0
   136   
   137    /* turn off the watchdog */
   138    #if defined(CONFIG_S3C2400)
   139    #define pWTCON        0x15300000
   140    /* Interupt-Controller base addresses */
   141    #define INTMSK        0x14400008
   142    /* clock divisor register */
   143    #define CLKDIVN        0x14800014
   144    #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)  // snallie
   /* 144行 S3C2410和S3C2440的Watchdog以及中断屏蔽寄存器的地址相同,所以加入 || defined(CONFIG_S3C2440) 的判断 */

   145    #define pWTCON        0x53000000
   146    /* Interupt-Controller base addresses */
   147    #define INTMSK        0x4A000008
   148    #define INTSUBMSK    0x4A00001C
   149    /* clock divisor register */
   150    #define CLKDIVN        0x4C000014
   151    #endif
   152   
   153    // snallie
   154    #define CLK_CTL_BASE    0x4C000000    /* tekkaman */
   155    #define MDIV_405    0x7f << 12    /* tekkaman */
   156    #define PSDIV_405    0x21        /* tekkaman */
   157    #define MDIV_200    0xa1 << 12    /* tekkaman */
   158    #define PSDIV_200    0x31        /* tekkaman */
   159    // end of snallie
   /* 154~158行引入tekkaman 的几个关于时钟除数因子的定义 */

   160   
   161        ldr     r0, =pWTCON
   162        mov     r1, #0x0
   163        str     r1, [r0]
   164   
   165        /*
   166         * mask all IRQs by setting all bits in the INTMR - default
   167         */
   168        mov    r1, #0xffffffff
   169        ldr    r0, =INTMSK
   170        str    r1, [r0]
   171    #if defined(CONFIG_S3C2410)
   172        ldr    r1, =0x3ff
   173        ldr    r0, =INTSUBMSK
   174        str    r1, [r0]
   175    #endif
   176       
   177    // start of snallie   
   178    #if defined(CONFIG_S3C2440)
   179        ldr    r1, =0x7ff
   180        ldr    r0, =INTSUBMSK
   181        str    r1, [r0]
   182    #endif
   183    // end of snallie
   /*
    * 178~183 为适应S3C2440中断屏蔽位寄存器的设置,事实上,S3C2440处理器复位后屏蔽全部的外部中断
    * 168~183段的代码完全可以省略掉,为保持代码的完整行和历史风格,将其保留
    */

   184       
   185    // start of snallie, SMDK2410 boot from NOR flash!   
   186    #if defined(CONFIG_S3C2410)    
   187        /* FCLK:HCLK:PCLK = 1:2:4 */
   188        /* default FCLK is 120 MHz ! */
   189        ldr    r0, =CLKDIVN
   190        mov    r1, #3
   191        str    r1, [r0]
   192   
   193        /*
   194         * we do sys-critical inits only at reboot,
   195         * not when booting from ram!
   196         */
   197    #ifdef CONFIG_INIT_CRITICAL
   198        bl    cpu_init_crit
   199    #endif
   200   
   201    relocate:
   202        /*
   203         * relocate armboot to RAM
   204         */
   205        adr    r0, _start        /* r0 <- current position of code */
   206        ldr    r2, _armboot_start
   207        ldr    r3, _armboot_end
   208        sub    r2, r3, r2        /* r2 <- size of armboot */
   209        ldr    r1, _TEXT_BASE        /* r1 <- destination address */
   210        add    r2, r0, r2        /* r2 <- source end address */
   211   
   212        /*
   213         * r0 = source address
   214         * r1 = target address
   215         * r2 = source end address
   216         */
   217    copy_loop:
   218        ldmia    r0!, {r3-r10}
   219        stmia    r1!, {r3-r10}
   220        cmp    r0, r2
   221        ble    copy_loop
   222   
   223    #if 0
   224        /* try doing this stuff after the relocation */
   225        ldr     r0, =pWTCON
   226        mov     r1, #0x0
   227        str     r1, [r0]
   228   
   229        /*
   230         * mask all IRQs by setting all bits in the INTMR - default
   231         */
   232        mov    r1, #0xffffffff
   233        ldr    r0, =INTMR
   234        str    r1, [r0]
   235   
   236        /* FCLK:HCLK:PCLK = 1:2:4 */
   237        /* default FCLK is 120 MHz ! */
   238        ldr    r0, =CLKDIVN
   239        mov    r1, #3
   240        str    r1, [r0]
   241        /* END stuff after relocation */
   242    #endif
   243   
   244        /* set up the stack */
   245        ldr    r0, _armboot_end
   246        add    r0, r0, #CONFIG_STACKSIZE
   247        sub    sp, r0, #12        /* leave 3 words for abort-stack */
   248   
   249        ldr    pc, _start_armboot
   250   
   251    _start_armboot:    .word start_armboot
   252    #endif
   253    // end of snallie
        /*
         *   187~251 这段设置时钟和代码搬移即跳转的部分不适合MINI2440, 通过条件编译将其跳过:在 include/configs/config_mini2440.h
         *   中我们将取消CONFIG_S3C2410的宏定义,取而代之的是定义CONFIG_S3C2440这个宏,所以187~251将在预处理时候被视为空
         */
         
        /*
         *   257~323部分为新修改的代码,以适应S3C2440 ,在 include/configs/config_mini2440.h 定义了CONFIG_S3C2440这个宏,
         *   所以这段代码被编译
         */         
   254   
   255    // start of snallie, mini2440 boot from NAND flash   
   256    //#if defined(CONFIG_S3C2440) && defined(CONFIG_MINI2440)
   257    #if defined(CONFIG_S3C2440)
   258            /* FCLK:HCLK:PCLK = 1:4:8 */
   259            ldr     r0, =CLKDIVN
   260            mov     r1, #5
   261            str     r1, [r0]
   262   
   263            mrc     p15, 0, r1, c1, c0, 0
   264            orr     r1, r1, #0xc0000000
   265            mcr     p15, 0, r1, c1, c0, 0
   266   
   267            mov     r1, #CLK_CTL_BASE
   268            mov     r2, #MDIV_405        /* MPLL=405MHZ */
   269            add     r2, r2, #PSDIV_405
   270            str     r2, [r1, #0x04]         /* MPLLCON tekkaman */
        /*
         *   259~270部分为设定工作时钟频率
         */          
   271       
   272        /*
   273         * we do sys-critical inits only at reboot,
   274         * not when booting from ram!
   275         */
   276        adr    r0, _start        /* r0 <- current position of code   */  // snallie
   277        ldr    r1, _TEXT_BASE        /* test if we run from flash or RAM */  // snallie
   278        cmp     r0, r1                  /* don't reloc during debug         */  // snallie
   279        blne    cpu_init_crit                              // snallie
    /* 判断代码的执行位置,以确定是否进行CPU的初始化:
     * 276行为伪指令,工作是取_start这个标号的运行时的地址,277行取_TEXT_BASE单元中的一个字的数据
     * 278行判断二者是否相等,若是不等则跳转到cpu_init_crit,进行CPU的初始化工作。
     * 说明:这四条指令主要是为了是代码可以同时适应烧写到Flash运行和下载绝对地址TEXT_BASE处运行:
     * (1)当烧写到Flash运行时候,这段代码的运行的起始地址为0x00000000,这时候_TEXT_BASE总是存储
     * 常量TEXT_BASE(配置在board/mini2440/config.mk),比较后两者不等,表明是从Flash中启动的
     * 所以要进行CPU等的初始化工作。
     * (2)当代码是在下载绝对地址TEXT_BASE处运行时,_start的值和_TEXT_BASE中存放的值是相等的,
     * 表明是在代码测试阶段时下载运行的,所以不必进行CPU等的初始化工作。
     */  
  
   280   
   281        /* set up the stack */                             // snallie
   282        ldr    r0, _armboot_end                         // snallie
   283        add    r0, r0, #CONFIG_STACKSIZE                     // snallie
   284        sub    sp, r0, #12        /* leave 3 words for abort-stack */     // snallie
    /*
     * 在306行要调用C的函数
     * int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
     * 进行代码的读出工作,所以282~284设定了一段堆栈,位于代码的下方(即程序代码部分的高地址部分),参见后面的
     * 内存映像图。
     */  
  
   285   
   286    relocate:
   287        /*
   288         * relocate armboot to RAM
   289         */
   290        adr    r0, _start        /* r0 <- current position of code */
   291        ldr    r1, _TEXT_BASE        /* r1 <- destination address */
   292        cmp     r0,  r1                     /* test if we run from flash or RAM */
   293        beq      call_start_armboot     // snallie
    /*
     * 290~293行代码:在要搬移代码前,先判断代码是从Flash中开始运行的还是下载绝对地址TEXT_BASE处运行的,若是下载运行的,则
     * 不必搬移,直接到call_start_armboot,否则进行代码的搬移。具体原因和对276行的注释相同。
     */
  
   294        ldr    r2, _armboot_start
   295        ldr    r3, _armboot_end
   296        sub    r2, r3, r2        /* r2 <- size of armboot */
    /* 294~296行代码:求一下代码的长度,存放在r2寄存器中 */
   
   297   
   298        /*
   299         * r0 = source address
   300         * r1 = target address
   301         * r2 = size of armboot
   302         */
   303        // snallie, CopyCodeFromFlashToRam
   304        // int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
   305        /*args:r0:source,r1:dest,r2:size*/
   306        bl  CopyCode2Ram //snallie, CopyCode2Ram.o must be linked within s3c24x0's steppingzone   
    /*
     *  306行调用C的函数进行代码的搬移,ARM处理器下,汇编程序给C函数传递参数的方式为:参数个数小于4个时候,通过
     *  r0,r1,r2,r3,分别存放4个参数,若多于4个则其余的通过堆栈传递,这里CopyCode2Ram只有3个参数,分别放到
     *  r0,r1,r2中,r0存放代码在Flash上的开始地址,这里为0x00000000, r1存放代码搬移的起始地址TEXT_BASE(当前设定为0x31F00000),
     *  r2存放代码的大小
     */
  
   307   
   308    call_start_armboot: // snallie
    /*
     * 准备跳转的start_armboot() 函数,309~317行将BSS段的全部数据清零,
     * BSS存放的是未初始化的数据,包括外部的未初始化全局数据,函数内部的未初始化的静态变量等,均存放在BSS段中,
     * 对于编译好的在操作系统下运行的C代码,这些段中的数据在C程序启动是会由编译器调用一段常规的启动例程进行清零的工作,
     * 在这里我们的代码是独立运行的,不依赖于操作系统,我们要直接做这个工作。309~317 这段代码进行BSS段的全部数据清零工作。
     * BSS段的数据在启动时清零的工作很重要(只可进行初始时候的一次清零处理!),不做清零处理,则程序运行时候会出现异常情况。
     */
  
   309    clear_bss:              // clear bss segment ,!! important !!, snallie
   310            ldr     r0, _bss_start          /* find start of bss segment        */     
   311            ldr     r1, _bss_end            /* stop here                        */     
   312            mov     r2, #0x00000000         /* clear                            */     
   313   
   314    clbss_l:str     r2, [r0]                /* clear loop...                    */     
   315            add     r0, r0, #4
   316            cmp     r0, r1 
   317            ble     clbss_l  // clear bss segment ,!! important !!, snallie
   318   
   319        ldr    pc, _start_armboot // snallie, call start_armboot(), and start.S ends here
    /* 319行将跳转到start_armboot()函数,定义在 common/board.c中,此后start.S便完成其使命*/
  
   320   
   321    _start_armboot:    .word start_armboot
   322   
   323    #endif
   324    // end of snallie

  
   325   
   326    /*
   327     *************************************************************************
   328     *
   329     * CPU_init_critical registers
   330     *
   331     * setup important registers
   332     * setup memory timing
   333     *
   334     *************************************************************************
   335     */
   336   
   337   
   338    cpu_init_crit:
   339        /*
   340         * flush v4 I/D caches
   341         */
   342        mov    r0, #0
   343        mcr    p15, 0, r0, c7, c7, 0    // flush v3/v4 cache
   344        mcr    p15, 0, r0, c8, c7, 0    // flush v4 TLB
   345   
   346        /*
   347         * disable MMU stuff and caches
   348         */
   349        mrc    p15, 0, r0, c1, c0, 0
   350        bic    r0, r0, #0x00002300    @ clear bits 13, 9:8 (--V- --RS)
   351        bic    r0, r0, #0x00000087    @ clear bits 7, 2:0 (B--- -CAM)
   352        orr    r0, r0, #0x00000002    @ set bit 2 (A) Align
   353        orr    r0, r0, #0x00001000    @ set bit 12 (I) I-Cache  // snallie
    /* 353 加入设定指令Cache */
  
   354        mcr    p15, 0, r0, c1, c0, 0
   355   
   356   
   357        /*
   358         * before relocating, we have to setup RAM timing
   359         * because memory timing is board-dependend, you will
   360         * find a memsetup.S in your board directory.
   361         */
   362        mov    ip, lr
   363        bl    memsetup
   364        mov    lr, ip
   365   
   366        mov    pc, lr
   367   
   368   
   369   
   370   
   371    /*
   372     *************************************************************************
   373     *
   374     * Interrupt handling
   375     *
   376     *************************************************************************
   377     */
   378   
   379    @
   380    @ IRQ stack frame.
   381    @
   382    #define S_FRAME_SIZE    72
   383   
   384    #define S_OLD_R0    68
   385    #define S_PSR        64
   386    #define S_PC        60
   387    #define S_LR        56
   388    #define S_SP        52
   389   
   390    #define S_IP        48
   391    #define S_FP        44
   392    #define S_R10        40
   393    #define S_R9        36
   394    #define S_R8        32
   395    #define S_R7        28
   396    #define S_R6        24
   397    #define S_R5        20
   398    #define S_R4        16
   399    #define S_R3        12
   400    #define S_R2        8
   401    #define S_R1        4
   402    #define S_R0        0
   403   
   404    #define MODE_SVC 0x13
   405    #define I_BIT     0x80
   406   
   407    /*
   408     * use bad_save_user_regs for abort/prefetch/undef/swi ...
   409     * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
   410     */
   411   
   412        .macro    bad_save_user_regs
   413        sub    sp, sp, #S_FRAME_SIZE
   414        stmia    sp, {r0 - r12}            @ Calling r0-r12
   415        add     r8, sp, #S_PC
   416   
   417        ldr    r2, _armboot_end
   418        add    r2, r2, #CONFIG_STACKSIZE
   419        sub    r2, r2, #8
   420        ldmia    r2, {r2 - r4}                   @ get pc, cpsr, old_r0
   421        add    r0, sp, #S_FRAME_SIZE        @ restore sp_SVC
   422   
   423        add    r5, sp, #S_SP
   424        mov    r1, lr
   425        stmia    r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_r
   426        mov    r0, sp
   427        .endm
   428   
   429        .macro    irq_save_user_regs
   430        sub    sp, sp, #S_FRAME_SIZE
   431        stmia    sp, {r0 - r12}            @ Calling r0-r12
   432        add     r8, sp, #S_PC
   433        stmdb   r8, {sp, lr}^                   @ Calling SP, LR
   434        str     lr, [r8, #0]                    @ Save calling PC
   435        mrs     r6, spsr
   436        str     r6, [r8, #4]                    @ Save CPSR
   437        str     r0, [r8, #8]                    @ Save OLD_R0
   438        mov    r0, sp
   439        .endm
   440   
   441        .macro    irq_restore_user_regs
   442        ldmia    sp, {r0 - lr}^            @ Calling r0 - lr
   443        mov    r0, r0
   444        ldr    lr, [sp, #S_PC]            @ Get PC
   445        add    sp, sp, #S_FRAME_SIZE
   446        subs    pc, lr, #4            @ return & move spsr_svc into cpsr
   447        .endm
   448   
   449        .macro get_bad_stack
   450        ldr    r13, _armboot_end        @ setup our mode stack
   451        add    r13, r13, #CONFIG_STACKSIZE    @ resides at top of normal stack
   452        sub    r13, r13, #8
   453   
   454        str    lr, [r13]            @ save caller lr / spsr
   455        mrs    lr, spsr
   456        str     lr, [r13, #4]
   457   
   458        mov    r13, #MODE_SVC            @ prepare SVC-Mode
   459        @ msr    spsr_c, r13
   460        msr    spsr, r13
   461        mov    lr, pc
   462        movs    pc, lr
   463        .endm
   464   
   465        .macro get_irq_stack            @ setup IRQ stack
   466        ldr    sp, IRQ_STACK_START
   467        .endm
   468   
   469        .macro get_fiq_stack            @ setup FIQ stack
   470        ldr    sp, FIQ_STACK_START
   471        .endm
   472   
   473    /*
   474     * exception handlers
   475     */
   476        .align  5
   477    undefined_instruction:
   478        get_bad_stack
   479        bad_save_user_regs
   480        bl     do_undefined_instruction
   481   
   482        .align    5
   483    software_interrupt:
   484        get_bad_stack
   485        bad_save_user_regs
   486        bl     do_software_interrupt
   487   
   488        .align    5
   489    prefetch_abort:
   490        get_bad_stack
   491        bad_save_user_regs
   492        bl     do_prefetch_abort
   493   
   494        .align    5
   495    data_abort:
   496        get_bad_stack
   497        bad_save_user_regs
   498        bl     do_data_abort
   499   
   500        .align    5
   501    not_used:
   502        get_bad_stack
   503        bad_save_user_regs
   504        bl     do_not_used
   505   
   506    #ifdef CONFIG_USE_IRQ
   507   
   508        .align    5
   509    irq:
   510        get_irq_stack
   511        irq_save_user_regs
   512        bl     do_irq
   513        irq_restore_user_regs
   514   
   515        .align    5
   516    fiq:
   517        get_fiq_stack
   518        /* someone ought to write a more effiction fiq_save_user_regs */
   519        irq_save_user_regs
   520        bl     do_fiq
   521        irq_restore_user_regs
   522   
   523    #else
   524   
   525        .align    5
   526    irq:
   527        get_bad_stack
   528        bad_save_user_regs
   529        bl     do_irq
   530   
   531        .align    5
   532    fiq:
   533        get_bad_stack
   534        bad_save_user_regs
   535        bl     do_fiq
   536   
   537    #endif
   538   
   539        .align    5
   540    .globl reset_cpu
   541    reset_cpu:
   542        mov     ip, #0
   543        mcr     p15, 0, ip, c7, c7, 0           @ invalidate cache
   544        mcr     p15, 0, ip, c8, c7, 0           @ flush TLB (v4)
   545        mrc     p15, 0, ip, c1, c0, 0           @ get ctrl register
   546        bic     ip, ip, #0x000f                 @ ............wcam
   547        bic     ip, ip, #0x2100                 @ ..v....s........
   548        mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
   549        mov     pc, r0


board/mini2440/memsetup.S 的修改

     1    /*
     2     * Memory Setup stuff - taken from blob memsetup.S
     3     *
     4     * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
     5     *                     Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
     6     *
     7     * Modified for the Samsung SMDK2410 by
     8     * (C) Copyright 2002
     9     * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
    10     *
    11     * See file CREDITS for list of people who contributed to this
    12     * project.
    13     *
    14     * This program is free software; you can redistribute it and/or
    15     * modify it under the terms of the GNU General Public License as
    16     * published by the Free Software Foundation; either version 2 of
    17     * the License, or (at your option) any later version.
    18     *
    19     * This program is distributed in the hope that it will be useful,
    20     * but WITHOUT ANY WARRANTY; without even the implied warranty of
    21     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    22     * GNU General Public License for more details.
    23     *
    24     * You should have received a copy of the GNU General Public License
    25     * along with this program; if not, write to the Free Software
    26     * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
    27     * MA 02111-1307 USA
    28     */
    29   
    30   
    31   
    32    #include "config.h"
    33    #include "version.h"
    34   
    35   
    36    /* some parameters for the board */
    37   
    38    /*
    39     *
    40     * Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
    41     *
    42     * Copyright (C) 2002 Samsung Electronics SW.LEE  <hitchcar@sec.samsung.com>
    43     *
    44     */
    45   
    46    #define BWSCON    0x48000000
    47   
    48    /* BWSCON */
    49    #define DW8             (0x0)
    50    #define DW16             (0x1)
    51    #define DW32             (0x2)
    52    #define WAIT             (0x1<<2)
    53    #define UBLB             (0x1<<3)
    54   
    55    #define B1_BWSCON          (DW32)
    56    #define B2_BWSCON          (DW16)
    57    #define B3_BWSCON          (DW16 + WAIT + UBLB)
    58    #define B4_BWSCON          (DW16)
    59    #define B5_BWSCON          (DW16)
    60    #define B6_BWSCON          (DW32)
    61    #define B7_BWSCON          (DW32)
    62   
    63    /* BANK0CON */
    64    #define B0_Tacs             0x0    /*  0clk */
    65    #define B0_Tcos             0x0    /*  0clk */
    66    #define B0_Tacc             0x7    /* 14clk */
    67    #define B0_Tcoh             0x0    /*  0clk */
    68    #define B0_Tah             0x0    /*  0clk */
    69    #define B0_Tacp             0x0
    70    #define B0_PMC             0x0    /* normal */
    71   
    72    /* BANK1CON */
    73    #define B1_Tacs             0x0    /*  0clk */
    74    #define B1_Tcos             0x0    /*  0clk */
    75    #define B1_Tacc             0x7    /* 14clk */
    76    #define B1_Tcoh             0x0    /*  0clk */
    77    #define B1_Tah             0x0    /*  0clk */
    78    #define B1_Tacp             0x0
    79    #define B1_PMC             0x0
    80   
    81    #define B2_Tacs             0x0
    82    #define B2_Tcos             0x0
    83    #define B2_Tacc             0x7
    84    #define B2_Tcoh             0x0
    85    #define B2_Tah             0x0
    86    #define B2_Tacp             0x0
    87    #define B2_PMC             0x0
    88   
    89    #define B3_Tacs             0x0    /*  0clk */
    90    #define B3_Tcos             0x3    /*  4clk */
    91    #define B3_Tacc             0x7    /* 14clk */
    92    #define B3_Tcoh             0x1    /*  1clk */
    93    #define B3_Tah             0x0    /*  0clk */
    94    #define B3_Tacp             0x3     /*  6clk */
    95    #define B3_PMC             0x0    /* normal */
    96   
    97    #define B4_Tacs             0x0    /*  0clk */
    98    #define B4_Tcos             0x0    /*  0clk */
    99    #define B4_Tacc             0x7    /* 14clk */
   100    #define B4_Tcoh             0x0    /*  0clk */
   101    #define B4_Tah             0x0    /*  0clk */
   102    #define B4_Tacp             0x0
   103    #define B4_PMC             0x0    /* normal */
   104   
   105    #define B5_Tacs             0x0    /*  0clk */
   106    #define B5_Tcos             0x0    /*  0clk */
   107    #define B5_Tacc             0x7    /* 14clk */
   108    #define B5_Tcoh             0x0    /*  0clk */
   109    #define B5_Tah             0x0    /*  0clk */
   110    #define B5_Tacp             0x0
   111    #define B5_PMC             0x0    /* normal */
   112   
   113    #define B6_MT             0x3    /* SDRAM */
   114    #define B6_Trcd              0x1
   115    #define B6_SCAN             0x1    /* 9bit */
   116   
   117    #define B7_MT             0x3    /* SDRAM */
   118    #define B7_Trcd             0x1    /* 3clk */
   119    #define B7_SCAN             0x1    /* 9bit */
   120   
   121    /* REFRESH parameter */
   122    #define REFEN             0x1    /* Refresh enable */
   123    #define TREFMD             0x0    /* CBR(CAS before RAS)/Auto refresh */
   124    #define Trp             0x0    /* 2clk */
   125    #define Trc             0x3    /* 7clk */
   126    #define Tchr             0x2    /* 3clk */
   127    #define REFCNT             1113    /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
   128    /**************************************/
   129   
   130    _TEXT_BASE:
   131        .word    TEXT_BASE
   132   
   133    .globl memsetup
   134    memsetup:
   135        /* memory control configuration */
   136        /* make r0 relative the current location so that it */
   137        /* reads SMRDATA out of FLASH rather than memory ! */
   138        ldr     r0, =SMRDATA
   139        ldr    r1, _TEXT_BASE
   140        sub    r0, r0, r1
   141        ldr    r1, =BWSCON    /* Bus Width Status Controller */
   142        add     r2, r0, #13*4
   143    0:
   144        ldr     r3, [r0], #4
   145        str     r3, [r1], #4
   146        cmp     r2, r0
   147        bne     0b
   148   
   149        /* everything is fine now */
   150        mov    pc, lr
   151   
   152        .ltorg
   153    /* the literal pools origin */
   154    #if defined(CONFIG_SMDK2410) // snallie
   155    SMRDATA:
   156        .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
   157        .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
   158        .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
   159        .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
   160        .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
   161        .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
   162        .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
   163        .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
   164        .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
   165        .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
   166        .word 0x32
   167        .word 0x30
   168        .word 0x30
   169    #endif // snallie
    /*  将 155~169行的内容通过条件编译取消掉 ,直接使用 172~203 行的部分,以适应MINI2440开发板 */  
   
   170       
   171    // start of snallie   
   172    #if defined(CONFIG_MINI2440)
   173    SMRDATA:
   174        .word    0x2211d110
   175        .word    0x00000700
   176        .word    0x00000700
   177        .word    0x00000700
   178        .word    0x0001c740
   179        .word    0x00000700
   180        .word    0x0001c740
   181        .word    0x00018005
   182        .word    0x00018005
   183        .word    0x008e0459
   184        .word    0x000000b2
   185        .word    0x00000030
   186        .word    0x00000030
   187   
   188    // snallie, Sun Feb  6 10:09:44 HKT 2011
   189    //        .word 0x22111112
   190    //        .word 0x00000700
   191    //        .word 0x00000700
   192    //        .word 0x00000700
   193    //        .word 0x00000700
   194    //        .word 0x00000700
   195    //        .word 0x00000700
   196    //        .word 0x00018009
   197    //        .word 0x00018009
   198    //        .word 0x008e04eb
   199    //        .word 0x000000b2
   200    //        .word 0x00000030
   201    //        .word 0x00000030       
   202   
   203    #endif
   204    // end of snallie   
    /* 170~204行为MINI2440开发板关于存储器控制的配置数据 */

       
//
board/mini2440/armboot.lds 的修改
     1    /*
     2     * (C) Copyright 2002
     3     * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
     4     *
     5     * See file CREDITS for list of people who contributed to this
     6     * project.
     7     *
     8     * This program is free software; you can redistribute it and/or
     9     * modify it under the terms of the GNU General Public License as
    10     * published by the Free Software Foundation; either version 2 of
    11     * the License, or (at your option) any later version.
    12     *
    13     * This program is distributed in the hope that it will be useful,
    14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16     * GNU General Public License for more details.
    17     *
    18     * You should have received a copy of the GNU General Public License
    19     * along with this program; if not, write to the Free Software
    20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
    21     * MA 02111-1307 USA
    22     */
    23   
    24    OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
    25    /*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
    26    OUTPUT_ARCH(arm)
    27    ENTRY(_start)
    28    SECTIONS
    29    {
    30            . = 0x00000000;
    31   
    32            . = ALIGN(4);
    33        .text      :
    34        {
    35          cpu/arm920t/start.o    (.text)
    36          board/mini2440/memsetup.o    (.text)    /* snallie */
    37          board/mini2440/boot_init.o    (.text)    /* snallie */
        /*
         *   36~37行控制将start.o,memsetup.o,boot_init.o 放在程序映像的前4K的部分,
         *   不放在这里则程序的初始化部分将得不到运行,boot_init.o有boot_init.c编译而来,是新引入的文件,后面有说明
         */
   
    38          *(.text)
    39        }
    40   
    41            . = ALIGN(4);
    42            .rodata : { *(.rodata) }
    43   
    44            . = ALIGN(4);
    45            .data : { *(.data) }
    46   
    47            . = ALIGN(4);
    48            .got : { *(.got) }
    49   
    50            . = ALIGN(4);
    51            __bss_start = .; /* snallie */
        /* 51行定义了一个新的符号地址,供cpu/arm920t/start.S 中的第95行使用,以便记录BSS段的起始地址 */
   
    52            .bss : { *(.bss) }
    53   
    54        armboot_end = .;
    55    }

   
/
新引入一个boot_init.c,在MINI2440的配套盘上的u-boot-1.1.6中可找到,
放到 board/mini2440 目录下,(随之还引入几个相关文件随后进行说明)并作少许改动如下:
     1    //#include <common.h>  // snallie
     2    //#include <s3c2410.h> // snallie
     3    #include <s3c2410a.h>  // snallie
    /*
     * 第1行的common.h用不到,去掉,ARMboot-1.1.0中已经有了一个s3c2410.h,但是不适合boot_init.c 使用,
     * 去掉,引入一个新的s3c2410a.h 供boot_init.c使用,该文件只改这些。主要是cpu/arm920t/start.S中调用了
     * 这个文件中的int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
     */
     
     4   
     5    #define GSTATUS1        (*(volatile unsigned int *)0x560000B0)
     6    #define BUSY            1
     7   
     8    /* 供外部调用的函数 */
     9    void nand_init_ll(void);
    10    void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);
    11   
    12    /* NAND Flash操作的总入口, 它们将调用S3C2410或S3C2440的相应函数 */
    13    static void nand_reset(void);
    14    static void wait_idle(void);
    15    static void nand_select_chip(void);
    16    static void nand_deselect_chip(void);
    17    static void write_cmd(int cmd);
    18    static void write_addr(unsigned int addr);
    19    static unsigned char read_data(void);
    20   
    21    /* S3C2410的NAND Flash处理函数 */
    22    static void s3c2410_nand_reset(void);
    23    static void s3c2410_wait_idle(void);
    24    static void s3c2410_nand_select_chip(void);
    25    static void s3c2410_nand_deselect_chip(void);
    26    static void s3c2410_write_cmd(int cmd);
    27    static void s3c2410_write_addr(unsigned int addr);
    28    static unsigned char s3c2410_read_data(void);
    29   
    30    /* S3C2440的NAND Flash处理函数 */
    31    static void s3c2440_nand_reset(void);
    32    static void s3c2440_wait_idle(void);
    33    static void s3c2440_nand_select_chip(void);
    34    static void s3c2440_nand_deselect_chip(void);
    35    static void s3c2440_write_cmd(int cmd);
    36    static void s3c2440_write_addr(unsigned int addr);
    37    static unsigned char s3c2440_read_data(void);
    38   
    39    /* S3C2410的NAND Flash操作函数 */
    40   
    41    /* 复位 */
    42    static void s3c2410_nand_reset(void)
    43    {
    44        s3c2410_nand_select_chip();
    45        s3c2410_write_cmd(0xff);  // 复位命令
    46        s3c2410_wait_idle();
    47        s3c2410_nand_deselect_chip();
    48    }
    49   
    50    /* 等待NAND Flash就绪 */
    51    static void s3c2410_wait_idle(void)
    52    {
    53        int i;
    54        S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
    55       
    56        volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT;
    57        while(!(*p & BUSY))
    58            for(i=0; i<10; i++);
    59    }
    60   
    61    /* 发出片选信号 */
    62    static void s3c2410_nand_select_chip(void)
    63    {
    64        int i;
    65        S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
    66   
    67        s3c2410nand->NFCONF &= ~(1<<11);
    68        for(i=0; i<10; i++);   
    69    }
    70   
    71    /* 取消片选信号 */
    72    static void s3c2410_nand_deselect_chip(void)
    73    {
    74        S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
    75   
    76        s3c2410nand->NFCONF |= (1<<11);
    77    }
    78   
    79    /* 发出命令 */
    80    static void s3c2410_write_cmd(int cmd)
    81    {
    82        S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
    83   
    84        volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFCMD;
    85        *p = cmd;
    86    }
    87   
    88    /* 发出地址 */
    89    static void s3c2410_write_addr(unsigned int addr)
    90    {
    91        int i;
    92        S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
    93        volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFADDR;
    94       
    95        *p = addr & 0xff;
    96        for(i=0; i<10; i++);
    97        *p = (addr >> 9) & 0xff;
    98        for(i=0; i<10; i++);
    99        *p = (addr >> 17) & 0xff;
   100        for(i=0; i<10; i++);
   101        *p = (addr >> 25) & 0xff;
   102        for(i=0; i<10; i++);
   103    }
   104   
   105    /* 读取数据 */
   106    static unsigned char s3c2410_read_data(void)
   107    {
   108        S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
   109   
   110        volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA;
   111        return *p;
   112    }
   113   
   114    /* S3C2440的NAND Flash操作函数 */
   115   
   116    /* 复位 */
   117    static void s3c2440_nand_reset(void)
   118    {
   119        s3c2440_nand_select_chip();
   120        s3c2440_write_cmd(0xff);  // 复位命令
   121        s3c2440_wait_idle();
   122        s3c2440_nand_deselect_chip();
   123    }
   124   
   125    /* 等待NAND Flash就绪 */
   126    static void s3c2440_wait_idle(void)
   127    {
   128        int i;
   129        S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
   130        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
   131   
   132        while(!(*p & BUSY))
   133            for(i=0; i<10; i++);
   134    }
   135   
   136    /* 发出片选信号 */
   137    static void s3c2440_nand_select_chip(void)
   138    {
   139        int i;
   140        S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
   141   
   142        s3c2440nand->NFCONT &= ~(1<<1);
   143        for(i=0; i<10; i++);   
   144    }
   145   
   146    /* 取消片选信号 */
   147    static void s3c2440_nand_deselect_chip(void)
   148    {
   149        S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
   150   
   151        s3c2440nand->NFCONT |= (1<<1);
   152    }
   153   
   154    /* 发出命令 */
   155    static void s3c2440_write_cmd(int cmd)
   156    {
   157        S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
   158   
   159        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
   160        *p = cmd;
   161    }
   162   
   163    /* 发出地址 */
   164    static void s3c2440_write_addr(unsigned int addr)
   165    {
   166        int i;
   167        S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
   168        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
   169       
   170        *p = addr & 0xff;
   171        for(i=0; i<10; i++);
   172        *p = (addr >> 9) & 0xff;
   173        for(i=0; i<10; i++);
   174        *p = (addr >> 17) & 0xff;
   175        for(i=0; i<10; i++);
   176        *p = (addr >> 25) & 0xff;
   177        for(i=0; i<10; i++);
   178    }
   179   
   180    /* 读取数据 */
   181    static unsigned char s3c2440_read_data(void)
   182    {
   183        S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
   184        volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
   185        return *p;
   186    }
   187   
   188   
   189    /* 在第一次使用NAND Flash前,复位一下NAND Flash */
   190    static void nand_reset(void)
   191    {
   192        /* 判断是S3C2410还是S3C2440 */
   193        if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
   194        {
   195            s3c2410_nand_reset();
   196        }
   197        else
   198        {
   199            s3c2440_nand_reset();
   200        }
   201    }
   202   
   203    static void wait_idle(void)
   204    {
   205        /* 判断是S3C2410还是S3C2440 */
   206        if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
   207        {
   208            s3c2410_wait_idle();
   209        }
   210        else
   211        {
   212            s3c2440_wait_idle();
   213        }
   214    }
   215   
   216    static void nand_select_chip(void)
   217    {
   218        int i;
   219       
   220        /* 判断是S3C2410还是S3C2440 */
   221        if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
   222        {
   223            s3c2410_nand_select_chip();
   224        }
   225        else
   226        {
   227            s3c2440_nand_select_chip();
   228        }
   229       
   230        for(i=0; i<10; i++);
   231    }
   232   
   233    static void nand_deselect_chip(void)
   234    {
   235        /* 判断是S3C2410还是S3C2440 */
   236        if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
   237        {
   238            s3c2410_nand_deselect_chip();
   239        }
   240        else
   241        {
   242            s3c2440_nand_deselect_chip();
   243        }   
   244    }
   245   
   246    static void write_cmd(int cmd)
   247    {
   248        /* 判断是S3C2410还是S3C2440 */
   249        if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
   250        {
   251            s3c2410_write_cmd(cmd);
   252        }
   253        else
   254        {
   255            s3c2440_write_cmd(cmd);
   256        }   
   257    }
   258    static void write_addr(unsigned int addr)
   259    {
   260        /* 判断是S3C2410还是S3C2440 */
   261        if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
   262        {
   263            s3c2410_write_addr(addr);
   264        }
   265        else
   266        {
   267            s3c2440_write_addr(addr);
   268        }   
   269    }
   270   
   271    static unsigned char read_data(void)
   272    {
   273        /* 判断是S3C2410还是S3C2440 */
   274        if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
   275        {
   276            return s3c2410_read_data();
   277        }
   278        else
   279        {
   280            return s3c2440_read_data();
   281        }   
   282    }
   283   
   284    /* 初始化NAND Flash */
   285    void nand_init_ll(void)
   286    {
   287        S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
   288        S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
   289   
   290    #define TACLS   0
   291    #define TWRPH0  3
   292    #define TWRPH1  0
   293   
   294        /* 判断是S3C2410还是S3C2440 */
   295        if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
   296        {
   297            /* 使能NAND Flash控制器, 初始化ECC, 禁止片选, 设置时序 */
   298            s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
   299        }
   300        else
   301        {
   302            /* 设置时序 */
   303            s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
   304            /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
   305            s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
   306        }
   307   
   308        /* 复位NAND Flash */
   309        nand_reset();
   310    }
   311   
   312   
   313    #define NAND_SECTOR_SIZE    512
   314    #define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE - 1)
   315   
   316    /* 读函数 */
   317    void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
   318    {
   319        int i, j;
   320       
   321        if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
   322            return ;    /* 地址或长度不对齐 */
   323        }
   324   
   325        /* 选中芯片 */
   326        nand_select_chip();
   327   
   328        for(i=start_addr; i < (start_addr + size);) {
   329          /* 发出READ0命令 */
   330          write_cmd(0);
   331   
   332          /* Write Address */
   333          write_addr(i);
   334          wait_idle();
   335   
   336          for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
   337              *buf = read_data();
   338              buf++;
   339          }
   340        }
   341   
   342        /* 取消片选信号 */
   343        nand_deselect_chip();
   344       
   345        return ;
   346    }
   347   
   348    int bBootFrmNORFlash(void)
   349    {
   350        volatile unsigned int *pdw = (volatile unsigned int *)0;
   351        unsigned int dwVal;
   352       
   353        /*
   354         * 无论是从NOR Flash还是从NAND Flash启动,
   355         * 地址0处为指令"b    Reset", 机器码为0xEA00000B,
   356         * 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中,
   357         * 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0。
   358         * 对于NOR Flash,必须通过一定的命令序列才能写数据,
   359         * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:
   360         * 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash
   361         */
   362   
   363        dwVal = *pdw;      
   364        *pdw = 0x12345678;
   365        if (*pdw != 0x12345678)
   366        {
   367            return 1;
   368        }
   369        else
   370        {
   371            *pdw = dwVal;
   372            return 0;
   373        }
   374    }
   375   
   376    int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
   377    {
   378        unsigned int *pdwDest;
   379        unsigned int *pdwSrc;
   380        int i;
   381   
   382        if (bBootFrmNORFlash())
   383        {
   384            pdwDest = (unsigned int *)buf;
   385            pdwSrc  = (unsigned int *)start_addr;
   386            /* 从 NOR Flash启动 */
   387            for (i = 0; i < size / 4; i++)
   388            {
   389                pdwDest[i] = pdwSrc[i];
   390            }
   391            return 0;
   392        }
   393        else
   394        {
   395            /* 初始化NAND Flash */
   396            nand_init_ll();
   397            /* 从 NAND Flash启动 */
   398            nand_read_ll(buf, start_addr, (size + NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK));
   399            return 0;
   400        }
   401    }
   402   
   403    static inline void delay (unsigned long loops)
   404    {
   405        __asm__ volatile ("1:/n"
   406          "subs %0, %1, #1/n"
   407          "bne 1b":"=r" (loops):"0" (loops));
   408    }
   409   
   410    /* S3C2440: Mpll = (2*m * Fin) / (p * 2^s), UPLL = (m * Fin) / (p * 2^s)
   411     * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
   412     */
   413    #define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
   414    #define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))
   415    #define S3C2440_MPLL_100MHZ     ((0x5c<<12)|(0x01<<4)|(0x03))
   416    #define S3C2440_UPLL_96MHZ      ((0x38<<12)|(0x02<<4)|(0x01))
   417    #define S3C2440_UPLL_48MHZ      ((0x38<<12)|(0x02<<4)|(0x02))
   418    #define S3C2440_CLKDIV          (0x05) // | (1<<3))    /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */
   419    #define S3C2440_CLKDIV188       0x04    /* FCLK:HCLK:PCLK = 1:8:8 */
   420    #define S3C2440_CAMDIVN188      ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */
   421   
   422    /* S3C2410: Mpll,Upll = (m * Fin) / (p * 2^s)
   423     * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
   424     */
   425    #define S3C2410_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x00))
   426    #define S3C2410_UPLL_48MHZ      ((0x28<<12)|(0x01<<4)|(0x02))
   427    #define S3C2410_CLKDIV          0x03    /* FCLK:HCLK:PCLK = 1:2:4 */
   428    void clock_init(void)
   429    {
   430        S3C24X0_CLOCK_POWER *clk_power = (S3C24X0_CLOCK_POWER *)0x4C000000;
   431   
   432        /* support both of S3C2410 and S3C2440, by www.arm9.net */
   433        if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
   434        {
   435            /* FCLK:HCLK:PCLK = 1:2:4 */
   436            clk_power->CLKDIVN = S3C2410_CLKDIV;
   437   
   438            /* change to asynchronous bus mod */
   439            __asm__(    "mrc    p15, 0, r1, c1, c0, 0/n"    /* read ctrl register   */ 
   440                        "orr    r1, r1, #0xc0000000/n"      /* Asynchronous         */ 
   441                        "mcr    p15, 0, r1, c1, c0, 0/n"    /* write ctrl register  */ 
   442                        :::"r1"
   443                        );
   444           
   445            /* to reduce PLL lock time, adjust the LOCKTIME register */
   446            clk_power->LOCKTIME = 0xFFFFFFFF;
   447   
   448            /* configure UPLL */
   449            clk_power->UPLLCON = S3C2410_UPLL_48MHZ;
   450   
   451            /* some delay between MPLL and UPLL */
   452            delay (4000);
   453   
   454            /* configure MPLL */
   455            clk_power->MPLLCON = S3C2410_MPLL_200MHZ;
   456   
   457            /* some delay between MPLL and UPLL */
   458            delay (8000);
   459        }
   460        else
   461        {
   462            /* FCLK:HCLK:PCLK = 1:4:8 */
   463            clk_power->CLKDIVN = S3C2440_CLKDIV;
   464   
   465            /* change to asynchronous bus mod */
   466            __asm__(    "mrc    p15, 0, r1, c1, c0, 0/n"    /* read ctrl register   */ 
   467                        "orr    r1, r1, #0xc0000000/n"      /* Asynchronous         */ 
   468                        "mcr    p15, 0, r1, c1, c0, 0/n"    /* write ctrl register  */ 
   469                        :::"r1"
   470                        );
   471   
   472            /* to reduce PLL lock time, adjust the LOCKTIME register */
   473            clk_power->LOCKTIME = 0xFFFFFFFF;
   474   
   475            /* configure UPLL */
   476            clk_power->UPLLCON = S3C2440_UPLL_48MHZ;
   477   
   478            /* some delay between MPLL and UPLL */
   479            delay (4000);
   480   
   481            /* configure MPLL */
   482            clk_power->MPLLCON = S3C2440_MPLL_400MHZ;
   483   
   484            /* some delay between MPLL and UPLL */
   485            delay (8000);
   486        }
   487    }
   488   


新引入s3c2410a.h 放到include下, 内容如下,不需任何修改
include/s3c2410a.h
     1    /*

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值