uboot启动流程分析之一

来源:互联网 发布:linux可以用来干什么 编辑:程序博客网 时间:2024/06/05 20:18

最开始的就是start.S



<pre name="code" class="html"> 一个可执行的Image 必须有一个入口点并且只能有一个唯一的全局入口,通常这个入口放在Rom(flash)的0x0地址。start.S· _start:<span style="font-family: Arial, Helvetica, sans-serif;"> /*异常向量表*/</span><pre code_snippet_id="650016" snippet_file_name="blog_20150422_2_4063097" name="code" class="plain">  /*大小32个字节,每个异常占据4个字节,保留4个字节空间*/<pre code_snippet_id="650016" snippet_file_name="blog_20150422_3_8027903" name="code" class="plain">  /*将异常中断处理程序注册到向量表,或使用跳转指令或使用数据      *读取指令LDR向PC中直接赋值    */<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
//声明-----------·  breset             /*复位,可能出现情况:系统加电,系统复位*/·  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                    /*快速异常中断,响应时间要求高*//*中断程序入口地址*/·  _undefined_instruction:     .wordirq_undefined_instruction·  _software_interrupt:          .word irq_software_interrupt ·  _prefetch_abort:                .word irq_prefetch_abort ·  _data_abort:                       .word irq_data_abort·  _not_used:                         .word irq_not_used·  _irq:                                   .word irq_irq·  _fiq:                                   .word irq_firq·  _pad1:                                .word 0x12345678               .....·  /* ·   *  复位程序入口 ·   */  ·  reset:                                        //上电触发reset ·    /* ·   *MCU  微控制单元准备   ·   */ ·   ldr  r0, =0x100 ·    delay_wait_mcu:   ·   sub r0, #1            ·   cmp  r0, #0                    //判断MCU是否准备好·   bne delay_wait_mcu ·  ·   ldr r0, =REG_BASE_SCTL ·  mov r1, #0 ·  wait_mux_finish: ·   add r1, r1, #1 ·  str r1, [r0, #REG_SC_GEN1]      /*系统通用寄存器0x0084*/ ·   ldr r2, [r0, #REG_SC_GEN1]·   cmp  r1, r2·  bne wait_mux_finish         /*确保地址范围是可读写的 RAM 空间*/·  mrs  r1,cpsr          /*将CPSR状态寄存器读取,保存到r1中  保存标志位FIQ.r8-10*/·  bic  r2, r1, #0x1f          /*反码0x1110 0000    低五位清零*/·  orr  r2, r2, #0xd1        /*或  0x1101 0001*/·  msr cpsr,r2·  adrl  r8,_start              /*取地址       分组寄存器fiq单独的物理寄存器*/·  mov r9,r3·  mov r10,r4·  msr cpsr, r1   /初始化PLL  DDR  PIN/·  /*PLL(统一脉冲信号)/DDR/pin mux 引脚/...* /·  ldr r0, _blank_zone_start·  ldr r1, _TEXT_BASE·  sub r0, r0,r1·  add r0, r0,#RAM_START_ADRS·  mov r1, #0x0                /* flags: 0->normal 1->pm*/·  mov r2, #INIT_REG_ITEM1·  bl  init_registers/屏蔽中断//*设置为SVC32模式  系统模式*/·  mrs r0, cpsr               /*将状态寄存器的内容传送至通用寄存器,将CPSR中的内容传送至R0保存当前处理器状态,中断屏蔽位以及各标志位*/·   bic  r0,r0,#0x1f          /*位清除指令  将R0最低5位清零,其余位不变工作模式位清零     工作模式位清零,设置CPSR中相应的位,使处理器进入相应的执行模式*/·   orrr0,r0,#0xd3/*r0=(0xd3|r0)*/          /*工作模式位设置为10011,将中断禁止位和快中断位置1               "1101 0011" 指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中*/ ·  msr cpsr, r0                                               /*将通用寄存器的内容传送至状态寄存器,将中的内容R0传送至CPSR*/ /*初始化串口*/ bl  uart_early_init/检查启动介质     NAND/SPI/EMMC  FLASH/·  cmp  r6, #BOOT_FROM_NAND                     /*判断启动介质*/   ·  bne  check_from_spi ·  cmp r0,#0x01 ·  bne  check_from_nand·   cmp r6, #BOOT_FROM_SPI ·   bne check_from_emmc 标准操作:·   /*i-cache初始化               指令cache 与数据cache*/ ·  mrc p15, 0, r0, c1, c0, 0   ·  orr r0, r0, #0x00001000 ·  mcr p15, 0, r0, c1, c0, 0 /*关闭MCU*/ ·  #ldr  r0,=0xf840f000 ·  #ldr  r1,[r0] ·  #bic    r1,r1,#0x1 ·  #str    r1,[r0] ·  /*时钟*/·  # ldr    r0,=REG_BASE_TIMER01 ·  #mov   r1,#0 ·  #str    r1,[r0,#REG_TIMER_CONTROL] ·  /*看门狗*/·  # mov     r1,#0 ·  # str  r1,[r4,#REG_SC_WDG_RST_CTRL] /*初始化寄存器1*/ ·  normal_init_item1: ·  ldr r0,_blank_zone_start ·  ldr r1, _TEXT_BASE ·  subr0,r0,r1 ·  ldr r1,[r4,#REG_SC_GEN14] ·  add r0,r0,r1·  mov r1,#0x0 /*flags:0->normal1->pm*/ ·  mov r2,#INIT_REG_ITEM1 ·  bl init_registers ·  b normal_init_item2 ·  copy_to_ddr:                        /*重定位uboot*/ ·  ldr r4,=REG_BASE_SCTL ·  ldr r0, [r4, #REG_SC_GEN14] ·                   /*r0存放的是程序开始的地址*/ ·  ldr r1, _TEXT_BASE            /* r1 存放的是内存中的地址* ·  ·   /* 比较两个地址是否相等*/ ·   cmp  r0,r1 ·   beq stack_setup                      /* 比较r0/r1是否相等,这个比较就是确定当前是不是从Flash中执行的,还是这段代码已装载到_TEXT_BASE处执行的。如果不等,则将 FLASH中的u-boot代码搬到_TEXT_BASE处。*/ ·如果不等  ·  ldr r2,_armboot_start ·  ldrr3,_bss_start                      /*flash中存储的u-boot可执行文件中,代码段、数据段以及BSS段都是首尾相连存储的,所以在计算搬移大小的时候就是利用了用BSS段的首地址减去代码的首地址,这样算出来的就是实际使用的空间。*/  ·   sub  r2,r3,r2 ·   /*memcpy(r1,r0,r2)*/    /*r1存放的是TEXT_BASE*/ ·  bl  memcpy ·   ·  stack_setup:                                                                         /*设置栈*/ ·   ldr  r0,_TEXT_BASE       /*往上128KB是重定位的uboot*/ ·   sub r0,r0,#CONFIG_BOOTHEAD_GAP ·   sub r0, r0,#CONFIG_SYS_MALLOC_LEN       /* 向下分配空间   因为u-boot中其它地方调用了malloc函数,该空间就是供其动态分配的。*/ ·   sub r0,r0,#CONFIG_SYS_GBL_DATA_SIZE  /*全局数据区   为global_data结构体预留的空间*/ ·   sub sp,r0,#12       /*为取址中止异常留三个字*/ ·   and sp,sp,#~7            /*用户栈顶*/ ·   ·   /*清零BSS段*/·  clear_bss:·  ldr r0,_bss_start·  ldr r1,_bss_end·  mov r2,#0x00000000·  ·  clear_bss_loop:·  str r2,[r0]               /*清零*/·  cmp r0, r1                 //是否清理到段尾·  add r0, r0, #4   //移动指针·  bne clear_bss_loop /*执行C程序,board.c参数r0,r1,r2*/·  ldr pc,_start_armboot·  _start_armboot: .word start_armboot


0 0