u-boot-2014.10移植第7天----深入代码分析(二)

现在从代码的角度来分析启动的流程:

从u-boot.lds文件知:

ENTRY(_start)
SECTIONS
{
    . = 0x00000000;

    . = ALIGN(4);
    .text :
    {
        *(.__image_copy_start)
        *(.vectors)
        CPUDIR/start.o (.text*)
        *(.text*)
    }

文件中__image_copy_start位映像文件复制起始地址,它在文件arch/arm/lib/sections.c中如下定义:

char __image_copy_start[0] __attribute__((section(".__image_copy_start")));
char __image_copy_end[0] __attribute__((section(".__image_copy_end")));

这个__image_copy_start在文件common/board_r.c中被调用,

static int initr_reloc_global_data(void)
{
#ifdef __ARM__
    monitor_flash_len = _end - __image_copy_start;

文件中.vectors(英文矢量)在arch/arm/lib/vectors.S的文件中定义:

.section ".vectors", "x"

.section伪操作
用户可以通过.section伪操作来自定义一个段,格式如下:
 .section section_name [, "flags"[, %type[,flag_specific_arguments]]]
每一个段以段名为开始, 以下一个段名或者文件结尾为结束。这些段都有缺省的标志(flags),连接器可以识别这些标志。(与armasm中的AREA相同)。

下面是ELF格式允许的段标志
<标志> 含义
a 允许段
w 可写段
x 执行段

参考:http://blog.sina.com.cn/s/blog_59b189220100au1k.html

所以x表示可执行段

该段下面就是可执行代码的起始位置:

_start:

通过下面的语句跳转到reset的入口:

b   reset

b汇编指令见:http://blog.chinaunix.net/uid-20799298-id-99633.html

先不跳入reset代码段返回,就会进入:

    ldr pc, _undefined_instruction
    ldr pc, _software_interrupt
    ldr pc, _prefetch_abort
    ldr pc, _data_abort
    ldr pc, _not_used
    ldr pc, _irq
    ldr pc, _fiq

ldr汇编指令见:http://blog.chinaunix.net/uid-28458801-id-4084264.html

举其中一个存储器地址“_undefined_instruction”为例,它定义如下:

    .globl  _undefined_instruction
    .globl  _software_interrupt
    .globl  _prefetch_abort
    .globl  _data_abort
    .globl  _not_used
    .globl  _irq
    .globl  _fiq

_undefined_instruction: .word undefined_instruction

undefined_instruction定义如下:

undefined_instruction:
    get_bad_stack
    bad_save_user_regs
    bl  do_undefined_instruction

获取坏掉的栈,保存用户寄存器,有打印信息供开发人员调试,最后就是在死循环了。

下面我们再来看看reset代码段,reset定义在:arch/arm/cpu/arm920t/start.S文件中,reset(英文复位),系统复位时也会从这里开始,处理硬件上的复位,软件复位命令时通过看门狗操作实现。reset开始的代码段实现切换到超级用户模式(SVC 模式),接着是异常重定位异常表:

#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
    /*
     * relocate exception table
     */
    ldr r0, =_start
    ldr r1, =0x0
    mov r2, #16
copyex:
    subs    r2, r2, #1
    ldr r3, [r0], #4
    str r3, [r1], #4
    bne copyex
#endif

CONFIG_AT91RM9200EK宏有定义,

LDR   r0,=label  
如果label是立即数,就把数值赋给r0, 如果lable是标识符,就把label地址的值赋给r0

r0保存了_start表示的地址,r1保存0,r2保存16,r2 = r2-1, subs中的s可以影响CPSR中的条件标志位,将r0地址处的内容读到r3中,再r0 = r0+4,str这条指令将R3中的字数据写入以R1为地址的存储器中,并将新地址R1+4写入R1,bne指令根据CPSR中的条件标志位判断是否跳转,如果subs指令中r2初值为16减为0时即影响了条件标志位,没有影响就跳转到copyex。所以异常重定位就是将__start开始的16个字拷贝到0地址开始的位置中去。

异常重定位结束后就是我们常说的关看门狗、屏蔽中断、设置系统时钟,

# if defined(CONFIG_S3C2400)
#  define pWTCON    0x15300000
#  define INTMSK    0x14400008  /* Interrupt-Controller base addresses */
#  define CLKDIVN   0x14800014  /* clock divisor register */
#else
#  define pWTCON    0x53000000
#  define INTMSK    0x4A000008  /* Interrupt-Controller base addresses */
#  define INTSUBMSK 0x4A00001C
#  define CLKDIVN   0x4C000014  /* clock divisor register */
# endif

    ldr r0, =pWTCON
    mov r1, #0x0
    str r1, [r0]

    /*
     * mask all IRQs by setting all bits in the INTMR - default
     */
    mov r1, #0xffffffff
    ldr r0, =INTMSK
    str r1, [r0]
# if defined(CONFIG_S3C2410)
    ldr r1, =0x3ff
    ldr r0, =INTSUBMSK
    str r1, [r0]
# endif

    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr r0, =CLKDIVN
    mov r1, #3
    str r1, [r0]
#endif  /* CONFIG_S3C24X0 */

下面是:

    /*
     * we do sys-critical inits only at reboot,
     * not when booting from ram!
     */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl  cpu_init_crit
#endif

从它的注释我们看到只在重启就进行系统临界初始化,我们计入cpu_init_curit查看。

明天再看。

时间: 2024-10-26 16:24:43

u-boot-2014.10移植第7天----深入代码分析(二)的相关文章

u-boot-2014.10移植第9天----深入分析代码(四)

硬件平台:tq2440 开发环境:Ubuntu-3.11 u-boot版本:2014.10 本文允许转载,请注明出处:http://blog.csdn.net/fulinus ENTRY(_main) /* * Set up initial C runtime environment and call board_init_f(0). */ #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) //在smdk2410开发板的相

u-boot-2014.10移植第8天----深入分析代码(三)

硬件平台:tq2440 开发环境:Ubuntu-3.11 u-boot版本:2014.10 本文允许转载,请注明出处:http://blog.csdn.net/fulinus 接着第七天的代码分析,下面是cpu_init_crit的代码段,同样位于文件arch/arm/cpu/arm920t/start.S中: /* ************************************************************************* * * CPU_init_cri

u-boot-2014.10移植第11天----深入分析代码(六)

硬件平台:tq2440 开发环境:Ubuntu-3.11 u-boot版本:2014.10 本文允许转载,请注明出处:http://blog.csdn.net/fulinus "从relocate_code回到_main中,接下来是main最后一段代码"也就是arch/arm/lib/crt0.S文件中: b   relocate_codehere://从这里开始u-boot已经在重定位的地方运行了 /* Set up final (full) environment */ bl  c

u-boot-2014.10移植第6天----深入分析代码(一)

硬件平台:tq2440 开发环境:Ubuntu-3.11 u-boot版本:2014.10 本文允许转载,请注明出处:http://blog.csdn.net/fulinus 前面我们看到了一个lds文件,我们这里深入的了解一下: section.c: /* * Copyright: (C) 2014 EAST fulinux <[email protected]> */ #include <stdio.h> #include <stdlib.h> int localm

u-boot-2014.10移植第2天----熟悉u-boot(二)

推荐阅读: 嵌入式系统 Boot Loader 技术内幕 http://www.ibm.com/developerworks/cn/linux/l-btloader/ 阅读并实际操作mini2440之U-boot移植详细手册.pdf文档中的内容.

u-boot-2014.10移植第12天----深入分析代码(七)

c_runtime_cpu_setup函数在arch/arm/cpu/arm920t/start.S文件中: .globl  c_runtime_cpu_setupc_runtime_cpu_setup:  mov pc, lr //没做什么就返回了 回到arch/arm/lib/crt0.S文件中: bl  c_runtime_cpu_setup /* we still call old routine here */ //bss段清零    ldr r0, =__bss_start    /

u-boot-2014.10移植第29天----nand flash的SPL启动(一)

硬件平台:tq2440 开发环境:Ubuntu-3.11 u-boot版本:2014.10 本文允许转载,请注明出处:http://blog.csdn.net/fulinus 前面在移植nand flash启动时做了很多探索性的工作,但是后来发现在relocate.S文件中调用的函数中有调用大部分的库函数,牵扯到的文件较多,很难将它们一一包含到前面4K空间中去.正在想其他方法时,突然意识到SPL功能.我初步了解了一下SPL的功能,简而言之是一个将u-boot从nand flash拷贝到SDRAM

u-boot-2014.10移植第21天----添加nand flash命令支持(三)

硬件平台:tq2440 开发环境:Ubuntu-3.11 u-boot版本:2014.10 本文允许转载,请注明出处:http://blog.csdn.net/fulinus 虽说nand flash读写操作是可以了,但是我使用nand markbad命令将一个块标记为坏块时,再用nand scrub命令恢复出厂设置时,却出现了下面的错误: nand0: MTD Erase failure: -5 说明我们的nand flash移植是不完全正确的. 下面查找原因 在文件drivers/mtd/n

u-boot-2014.10移植第14天----在SDRAM中运行

昨天遇到编译错误,我们从错误提示中寻找解决方法: 信息1:CHK     include/config.h /* Automatically generated - do not edit */ #define CONFIG_BOARDDIR board/samsung/tq2440 #include <config_defaults.h> #include <configs/tq2440.h> #include <asm/config.h> #include <