单片机
返回首页

ARMBoot-1.1.0 在 mini2440 开发板上的移植

2024-06-28 来源:elecfans

作为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@www.linuxidc.com 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@www.linuxidc.com arms]# ls -l
total 428
-rw-r--r--    1 root     root       431099 Feb 25  2007 armboot-1.1.0.tgz

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

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

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

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

通过编译,查看生成的文件如下:
[root@www.linuxidc.com 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@www.linuxidc.com armboot-1.1.0]# make distclean

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

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

或者用vi进行全屏幕编辑修改:
[root@www.linuxidc.com 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@www.linuxidc.com 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@www.linuxidc.com armboot-1.1.0]# sed -i'~' -e '/^(OBJSt:= smdk2410.o..*)/ {N; s/(..*)n/# 1 # snallie, `date +%F_%H%M%S_%a`n1 # snallie, `date +%F_%H%M%S_%a`n/g; s/smdk2410/mini2440/2 }' board/mini2440/Makefile

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

4)    修改mini2440的板级的文件名,涉及文件为 board/mini2440/smdk2410.c
[root@www.linuxidc.com 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 ' >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 ' >config.h
   216

可用如下的sed 命令直接修改:(用sed脚本修改只可执行1遍,切勿多次执行!)
[root@www.linuxidc.com 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`n1n2n3n4n5n6n7n/g;s/smdk2410/mini2440/3;s/smdk2410/mini2440/3 } ' -e '/backup/,/gtar/ {N;N;N; s/(..*)n(..*)n(..*)n/#1n#2n#3nn# snallie, `date +%F_%H%M%S_%a`n1n2n3n/g; s/'([^n]*)(.tar.gz)/'+$$F-gk-%Y%m%d_%H%M%S2/2 } ' -e '/^armboot.bin/ {N;N;N; s/(..*)n(..*)n(..*)n/1n2n# snallie, `date +%F_%H%M%S_%a`n#3n/g }' Makefile

或者用vi进行全屏幕编辑修改:
[root@www.linuxidc.com 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@www.linuxidc.com armboot-1.1.0]# sed -i'~' -e '/1.0.2/ {N; s/(..*)n///1n1/g; s/1.0.2'/1.1.0't// snallie, `date +%F_%H%M%S_%a`n/2;}' include/version.h

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

7)    关于SMDK2410的全部文件复制完成,编译测试:
[root@www.linuxidc.com 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@www.linuxidc.com 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@www.linuxidc.com 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
     5     *  Copyright (c) 2002    Alex Z黳ke
     6     *  Copyright (c) 2002    Gary Jennejohn
     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段中,


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • PIC单片机控制的遥控防盗报警器电路

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 开关电源的基本组成及工作原理

  • RS-485基础知识:处理空闲总线条件的两种常见方法

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章