嵌入式 hi3518c默认看门狗没有开启,uboot汇编start.s解析

时间:2021-01-10 19:37:15

嵌入式 hi3518c默认看门狗没有开启,uboot汇编start.s解析

/*====================================Hi3518c start.S Begin 2014-04-20=============================================*/
/*
 *  armboot - Startup Code for ARM926EJS CPU-core
 *
 *  Copyright (c) 2003  Texas Instruments
 *
 *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
 *
 *  Copyright (c) 2001 Marius Gr?ger <
mag@sysgo.de>
 *  Copyright (c) 2002 Alex Z?pke <
azu@sysgo.de>
 *  Copyright (c) 2002 Gary Jennejohn <
garyj@denx.de>
 *  Copyright (c) 2003 Richard Woodruff <
r-woodruff2@ti.com>
 *  Copyright (c) 2003 Kshitij <
kshitij@ti.com>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */


#include <config.h>
#include <version.h>

/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */


.globl _start //汇编程序都要提供一个_start符号并且用.globl声明
_start: b reset //B或BL指令引起处理器转移到“子程序名”处开始执行 复位
 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: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort:  .word data_abort
_not_used:  .word not_used
_irq:   .word irq
_fiq:   .word fiq
_pad:   .word 0x12345678 /* now 16*4=64 */

/*.fill
     语法:.fill repeat, size, value
     含义是反复拷贝 size个字节,重复 repeat 次,
         其中 size 和 value 是可选的,默认值分别为 1 和 0.
*/
__blank_zone_start:
.fill 1024*4,1,0 //给某个具体的寄存器里填数
__blank_zone_end:

.globl _blank_zone_start
_blank_zone_start:
.word __blank_zone_start


.globl _blank_zone_end
_blank_zone_end:
.word __blank_zone_end

 .balignl 16,0xdeadbeef
/*
 *************************************************************************
 *
 * Startup Code (reset vector)
 *
 * do important init only if we don't start from memory!
 * setup Memory and board specific bits prior to relocation.
 * relocate armboot to ram
 * setup stack
 *
 *************************************************************************
 */

_TEXT_BASE:
 .word TEXT_BASE

.globl _armboot_start
_armboot_start:
 .word _start

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
 .word __bss_start

.globl _bss_end
_bss_end:
 .word _end

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
 .word 0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
 .word 0x0badc0de
#endif


_clr_remap_spi_entry:
    .word   SF_TEXT_ADRS + do_clr_remap - TEXT_BASE
_clr_remap_nand_entry:
    .word   NAND_TEXT_ADRS + do_clr_remap - TEXT_BASE

/*
 * the actual reset code
 */

reset:
 /*
  * set the cpu to SVC32 mode
  */
 mrs r0,cpsr //将状态寄存器的内容传送至通用寄存器,将CPSR中的内容传送至R0
 bic r0,r0,#0x1f //位清除指令 将R0最低5位清零,其余位不变 工作模式位清零
 orr r0,r0,#0xd3 //工作模式位设置为“10011”(管理模式),并将中断禁止位和快中断禁止位置1 "1101 0011" 指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中
 msr cpsr,r0 //将通用寄存器的内容传送至状态寄存器,将中的内容R0传送至CPSR

 /*
  * we do sys-critical inits only at reboot,
  * not when booting from ram!
  */

 /*
  * flush v4 I/D caches
  */
 mov r0, #0 //置零ro通用寄存器
 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ //向c7写入0将使ICache与DCache无效 "0"表示省略opcode_2 MCR{<cond>} p15, 0, <Rd>, <CRn>, <CRm>{,<opcode_2>}
 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ //MCR{条件} 协处理器编码,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,协处理器操作码2

 /*
  * disable MMU stuff and caches
  */
 mrc p15, 0, r0, c1, c0, 0
 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
 mcr p15, 0, r0, c1, c0, 0 //保存r0到控制寄存器

 mov  r0, pc, lsr#24 //LSL、LSR、ASR、ROR 寄存器移位
 cmp  r0, #0x0
 bne do_clr_remap //检测是否需要跳转,PC的高八位如果不为0(已经在ram中运行了)则跳转 不等于则调转

check_start_mode:
 ldr r0, =REG_BASE_SCTL
 ldr r0, [r0, #REG_SYSSTAT]
 mov r6, r0, lsr#5
 and r6, #0x1

 /* reg[0x2005008c:5]:
  * 0: start from spi
  * 1: start from nand
  */

 cmp r6, #BOOT_FROM_SPI
 ldreq   pc, _clr_remap_spi_entry

 ldr pc, _clr_remap_nand_entry
 @b . /* bug here */

/*
LDR和STR用来存取内存,关于"索引偏移",你是不是指pre-indexed addressing和post-indexed addressingpre-indexed addressing是指地址经过运算不写回基址寄存器post-indexed addressing则回写到基址寄存器比如pre-indexed addressing:mov r1,#0STR r0, [r1, #0x10]       ;r1+0x10这个是所用的实际地址值,但是不回写入r1,在此句之后,r1=0post-indexed addressing:STR r0, [r1], #0x10       ;r1+0x10这个是所用的实际地址值,这个值回写入r1,此句之后,r1=0x10
*/
do_clr_remap:
 ldr     r4, =REG_BASE_SCTL //用来从存储器(确切地说是地址空间)中装载数据到通用寄存器 系统控制器寄存器 0x20050000 写地址
 ldr  r0, [r4, #REG_SC_CTRL] //加载32位的立即数或一个地址值到指定寄存器 不回写 其实是r4+#0x0是实际地址值

 /* reg[0x20050000:8]:
  * 0: keep remap
  * 1: clear remap 重映射
  */
 @Set clear remap bit.
 orr  r0, #(1<<8) //第八位置1
 str  r0, [r4, #REG_SC_CTRL] //不回写 @表示注释

 @Setup TCM (ENABLED, 2KB) // TCM时钟门控使能
 ldr     r0, =( 1 | (MEM_CONF_ITCM_SIZE<<2) | MEM_BASE_ITCM)
 mcr     p15, 0, r0, c9, c1, 1

 @enable I-Cache now
 mrc p15, 0, r0, c1, c0, 0
 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
 mcr p15, 0, r0, c1, c0, 0

 @Check if I'm running in ddr //代码内存运行测试
 mov r0, pc, lsr#28
 cmp r0, #8
 bleq    relocate //小于等于跳转

 ldr     r0, _blank_zone_start
 ldr     r1, _TEXT_BASE //代码段
 sub     r0, r0, r1 //减法 sub a,b (a-b)
 adrl    r1, _start //将相对于程序或相对于寄存器的地址载入寄存器中 adrl宽
 add     r0, r0, r1 //加法
 mov     r1, #0          /* flags: 0->normal 1->pm */
 bl      init_registers //初始化寄存器

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:
 @copy arm exception table in 0 address
 adrl r0, _start
 mov r1, #0
 mov r2, #0x100  /* copy arm Exception table to 0 addr */
 add     r2, r0, r2
copy_exception_table:
 ldmia   r0!, {r3 - r10}
 stmia   r1!, {r3 - r10}
 cmp     r0, r2
 ble     copy_exception_table

 @relocate U-Boot to RAM
 adrl r0, _start  /* r0 <- current position of code   */
 ldr r1, _TEXT_BASE  /* test if we run from flash or RAM */
 cmp     r0, r1                  /* don't reloc during debug         */
 beq     stack_setup
 ldr r2, _armboot_start
 ldr r3, _bss_start
 sub r2, r3, r2  /* r2 <- size of armboot            */
 add r2, r0, r2  /* r2 <- source end address         */

copy_loop:
 ldmia r0!, {r3-r10}  /* copy from source address [r0]    */
 stmia r1!, {r3-r10}  /* copy to   target address [r1]    */
 cmp r0, r2   /* until source end addreee [r2]    */
 ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

 /* Set up the stack          */
stack_setup:
 ldr r0, _TEXT_BASE  /* upper 128 KiB: relocated uboot   */
 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area      */
 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo      */
#ifdef CONFIG_USE_IRQ
 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
 sub sp, r0, #12  /* leave 3 words for abort-stack    */
 bic sp, sp, #7  /*8-byte alignment for ABI compliance*/

clear_bss:
 ldr r0, _bss_start  /* find start of bss segment        */
 ldr r1, _bss_end  /* stop here                        */
 mov r2, #0x00000000  /* clear                            */

clbss_l:str r2, [r0]  /* clear loop...                    */
 add r0, r0, #4
 cmp r0, r1
 ble clbss_l

 ldr pc, _start_armboot

_start_armboot:
 .word start_armboot


/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
 /*
  * flush v4 I/D caches
  */
 mov r0, #0
 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

 /*
  * disable MMU stuff and caches
  */
 mrc p15, 0, r0, c1, c0, 0
 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
 mcr p15, 0, r0, c1, c0, 0

 /*
  * Go setup Memory and board specific bits prior to relocation.
  */
 mov ip, lr  /* perserve link reg across call */
 @bl lowlevel_init /* go setup pll,mux,memory */
 mov lr, ip  /* restore link */
 mov pc, lr  /* back to my caller */
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

#ifndef CONFIG_PRELOADER
/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */

@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72

#define S_OLD_R0 68
#define S_PSR  64
#define S_PC  60
#define S_LR  56
#define S_SP  52

#define S_IP  48
#define S_FP  44
#define S_R10  40
#define S_R9  36
#define S_R8  32
#define S_R7  28
#define S_R6  24
#define S_R5  20
#define S_R4  16
#define S_R3  12
#define S_R2  8
#define S_R1  4
#define S_R0  0

#define MODE_SVC 0x13
#define I_BIT  0x80

/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 */

 .macro bad_save_user_regs
 @ carve out a frame on current user stack
 sub sp, sp, #S_FRAME_SIZE
 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12

 ldr r2, _armboot_start
 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
 @ set base 2 words into abort stack
 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
 @ get values for "aborted" pc and cpsr (into parm regs)
 ldmia r2, {r2 - r3}
 add r0, sp, #S_FRAME_SIZE  @ grab pointer to old stack
 add r5, sp, #S_SP
 mov r1, lr
 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
 mov r0, sp  @ save current stack into r0 (param register)
 .endm

 .macro irq_save_user_regs
 sub sp, sp, #S_FRAME_SIZE
 stmia sp, {r0 - r12}   @ Calling r0-r12
 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
 add r8, sp, #S_PC
 stmdb r8, {sp, lr}^  @ Calling SP, LR
 str lr, [r8, #0]  @ Save calling PC
 mrs r6, spsr
 str r6, [r8, #4]  @ Save CPSR
 str r0, [r8, #8]  @ Save OLD_R0
 mov r0, sp
 .endm

 .macro irq_restore_user_regs
 ldmia sp, {r0 - lr}^   @ Calling r0 - lr
 mov r0, r0
 ldr lr, [sp, #S_PC]   @ Get PC
 add sp, sp, #S_FRAME_SIZE
 subs pc, lr, #4  @ return & move spsr_svc into cpsr
 .endm

 .macro get_bad_stack
 ldr r13, _armboot_start  @ setup our mode stack
 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
 @ reserved a couple spots in abort stack
 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8)

 str lr, [r13] @ save caller lr in position 0 of saved stack
 mrs lr, spsr @ get the spsr
 str lr, [r13, #4] @ save spsr in position 1 of saved stack
 mov r13, #MODE_SVC @ prepare SVC-Mode
 @ msr spsr_c, r13
 msr spsr, r13 @ switch modes, make sure moves will execute
 mov lr, pc  @ capture return pc
 movs pc, lr  @ jump to next instruction & switch modes.
 .endm

 .macro get_irq_stack   @ setup IRQ stack
 ldr sp, IRQ_STACK_START
 .endm

 .macro get_fiq_stack   @ setup FIQ stack
 ldr sp, FIQ_STACK_START
 .endm
#endif /* CONFIG_PRELOADER */

/*
 * exception handlers
 */
#ifdef CONFIG_PRELOADER
 .align 5 //加上.align汇编语句后,指令就对齐
do_hang:
 ldr sp, _TEXT_BASE   /* switch to abort stack */
1:
 bl 1b    /* hang and never return */
#else /* !CONFIG_PRELOADER */
 .align  5
undefined_instruction:
 get_bad_stack
 bad_save_user_regs
 bl do_undefined_instruction

 .align 5
software_interrupt:
 get_bad_stack
 bad_save_user_regs
 bl do_software_interrupt

 .align 5
prefetch_abort:
 get_bad_stack
 bad_save_user_regs
 bl do_prefetch_abort

 .align 5
data_abort:
 get_bad_stack
 bad_save_user_regs
 bl do_data_abort

 .align 5
not_used:
 get_bad_stack
 bad_save_user_regs
 bl do_not_used

#ifdef CONFIG_USE_IRQ

 .align 5
irq:
 get_irq_stack
 irq_save_user_regs
 bl do_irq
 irq_restore_user_regs

 .align 5
fiq:
 get_fiq_stack
 /* someone ought to write a more effiction fiq_save_user_regs */
 irq_save_user_regs
 bl do_fiq
 irq_restore_user_regs

#else

 .align 5
irq:
 get_bad_stack
 bad_save_user_regs
 bl do_irq

 .align 5
fiq:
 get_bad_stack
 bad_save_user_regs
 bl do_fiq

#endif
#endif /* CONFIG_PRELOADER */
#include "lowlevel_init.S"
/*====================================Hi3518c start.S End=============================================*/

 

/*====================================Hi3518c lowlevelinit.s Begin=====================================*/
 .text
 .align 2
 .global init_registers
 .type init_registers, %function
init_registers:
 @ args = 0, pretend = 0, frame = 0
 @ frame_needed = 0, uses_anonymous_args = 0
 @ link register save eliminated.
 ldr r2, [r0, #0]
 cmp r2, #0
 mov r6, #1
 bne .L43
.L2:
 ldr r3, [r0, #4]
 cmp r3, #0
 bne .L43
 ldr r3, [r0, #8]
 cmp r3, #0
 ldrne ip, [r0, #12]
 bne .L3
 ldr ip, [r0, #12]
 cmp ip, #0
 beq .L6
.L3:
 cmp r1, #0
 beq .L7
.L45:
 tst ip, #2
 beq .L8
 and r4, ip, #248
 mov r4, r4, lsr #3
 add r4, r4, #1
 cmp r4, #32
 movne r4, r6, asl r4
 andne ip, ip, #63488
 ldr r5, [r2, #0]
 movne ip, ip, lsr #11
 subne r4, r4, #1
 bicne r5, r5, r4, asl ip
 ldrne r4, [r0, #4]
 ldreq ip, [r0, #4]
 orrne ip, r5, r4, asl ip
 cmp r3, #0
 str ip, [r2, #0]
 beq .L11
.L29:
@ 38 "lowlevel_init.c" 1
 nop
@ 0 "" 2
 subs r3, r3, #1
 bne .L29
.L11:
 add r0, r0, #16
.L46:
 ldr r2, [r0, #0]
 cmp r2, #0
 beq .L2
.L43:
 cmp r1, #0
 ldr r3, [r0, #8]
 ldr ip, [r0, #12]
 bne .L45
.L7:
 tst ip, #4
 beq .L18
 and r4, ip, #248
 mov r4, r4, lsr #3
 add r4, r4, #1
 cmp r4, #32
 movne r4, r6, asl r4
 andne ip, ip, #63488
 ldr r5, [r2, #0]
 movne ip, ip, lsr #11
 subne r4, r4, #1
 bicne r5, r5, r4, asl ip
 ldrne r4, [r0, #4]
 ldreq ip, [r0, #4]
 orrne ip, r5, r4, asl ip
 cmp r3, #0
 str ip, [r2, #0]
 beq .L11
.L32:
@ 38 "lowlevel_init.c" 1
 nop
@ 0 "" 2
 subs r3, r3, #1
 bne .L32
 add r0, r0, #16
 b .L46
.L8:
 tst ip, #131072
 bne .L13
 cmp r3, #0
 beq .L11
.L31:
@ 38 "lowlevel_init.c" 1
 nop
@ 0 "" 2
 subs r3, r3, #1
 bne .L31
 add r0, r0, #16
 b .L46
.L18:
 tst ip, #262144
 bne .L22
 cmp r3, #0
 beq .L11
.L34:
@ 38 "lowlevel_init.c" 1
 nop
@ 0 "" 2
 subs r3, r3, #1
 bne .L34
 add r0, r0, #16
 b .L46
.L13:
 and r4, ip, #16252928
 mov r4, r4, lsr #19
 add r4, r4, #1
 mov r7, r6, asl r4
 ldr r5, [r0, #4]
 mov r8, ip, lsr #27
 sub r7, r7, #1
.L16:
 ldr ip, [r2, #0]
 cmp r4, #32
 andne ip, r7, ip, lsr r8
@ 38 "lowlevel_init.c" 1
 nop
@ 0 "" 2
 cmp r5, ip
 bne .L16
 cmp r3, #0
 beq .L11
.L30:
@ 38 "lowlevel_init.c" 1
 nop
@ 0 "" 2
 subs r3, r3, #1
 bne .L30
 add r0, r0, #16
 b .L46
.L22:
 and r4, ip, #16252928
 mov r4, r4, lsr #19
 add r4, r4, #1
 mov r8, r6, asl r4
 ldr r5, [r0, #4]
 sub r8, r8, #1
 mov r7, ip, lsr #27
.L25:
 ldr ip, [r2, #0]
 cmp r4, #32
 andne ip, r8, ip, lsr r7
@ 38 "lowlevel_init.c" 1
 nop
@ 0 "" 2
 cmp r5, ip
 bne .L25
 cmp r3, #0
 beq .L11
.L33:
@ 38 "lowlevel_init.c" 1
 nop
@ 0 "" 2
 subs r3, r3, #1
 bne .L33
 add r0, r0, #16
 b .L46
.L6:
@ 38 "lowlevel_init.c" 1
 nop
@ 0 "" 2
 bx lr
/*====================================Hi3518c lowlevelinit.s End=====================================*/

1. 引言 1.1 编写目的

编写此文档记录学习uboot的过程,本文为系列第二篇

1.2 定义

2. 概述

U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下:

       (1)第一阶段的功能

·   硬件设备初始化

·   加载U-Boot第二阶段代码到RAM空间

·   设置好栈

·   跳转到第二阶段代码入口

       (2)第二阶段的功能

·   初始化本阶段使用的硬件设备

·   检测系统内存映射

·   将内核从Flash读取到RAM中

·   为内核设置启动参数

·   调用内核

本文主要分析启动的第一阶段

3. 硬件设备初始化

根据链接脚本(本系列第一篇)\u-boot-2008.10\cpu\arm926ejs\start.s  文件为cpu上电后执行的第一的文件(第一段代码)

Start.s代码开头如下:

3.1 设置异常向量

.globl _start

_start:    b     start_code                         /* 复位 */

       ldr   pc, _undefined_instruction      /* 未定义指令向量 */

       ldr   pc, _software_interrupt            /*  软件中断向量 */

       ldr   pc, _prefetch_abort                  /*  预取指令异常向量 */

       ldr   pc, _data_abort                        /*  数据操作异常向量 */

       ldr   pc, _not_used                           /*  未使用   */

       ldr   pc, _irq                                     /*  irq中断向量  */

       ldr   pc, _fiq                                     /*  fiq中断向量  */

/*  中断向量表入口地址 */

_undefined_instruction:    .word undefined_instruction

_software_interrupt:  .word software_interrupt

_prefetch_abort:  .word prefetch_abort

_data_abort:        .word data_abort

_not_used:          .word not_used

_irq:                     .word irq

_fiq:                     .word fiq

       .balignl 16,0xdeadbeef                            //设置对齐方式为16位对齐方式,空白区域自动用0xdeafbeef填充

其中

_undefined_instruction;_software_interrupt为lable,和C语言里面的lable一样,lable的值为当前代码的地址。

.word为GCC汇编伪指令,表示在当前位置定义一个字的变量,变量的内容紧跟其后。

所以执行_undefined_instruction:    .word undefined_instruction指令后的内存映像为:

 

地址

内容

大小

0x000000004

_undefined_instruction

undefined_instruction

Word(32)

       以上代码设置了ARM异常向量表,各个异常向量介绍如下:

表 2.1 ARM异常向量表

 

地址

异常

进入模式

描述

0x00000000

复位

管理模式

复位电平有效时,产生复位异常,程序跳转到复位处理程序处执行

0x00000004

未定义指令

未定义模式

遇到不能处理的指令时,产生未定义指令异常

0x00000008

软件中断

管理模式

执行SWI指令产生,用于用户模式下的程序调用特权操作指令

0x0000000c

预存指令

中止模式

处理器预取指令的地址不存在,或该地址不允许当前指令访问,产生指令预取中止异常

0x00000010

数据操作

中止模式

处理器数据访问指令的地址不存在,或该地址不允许当前指令访问时,产生数据中止异常

0x00000014

未使用

未使用

未使用

0x00000018

IRQ

IRQ

外部中断请求有效,且CPSR中的I位为0时,产生IRQ异常

0x0000001c

FIQ

FIQ

快速中断请求引脚有效,且CPSR中的F位为0时,产生FIQ异常

       在cpu\arm926ejs\start.s中还有这些异常对应的异常处理程序。当一个异常产生时,CPU根据异常号在异常向量表中找到对应的异常向量,然后执行异常向量处的跳转指令,CPU就跳转到对应的异常处理程序执行。

       其中复位异常向量的指令“b start_code”决定了U-Boot启动后将自动跳转到标号“start_code”处执行。

3.2 设置定位lable

_TEXT_BASE:

       .word      TEXT_BASE

TEXT_BASE在系列一中有分析,在MAKEFIE 中通过TEXT_BASE指定代码段的VMA地址偏移,其中TEXT_BASE保存于board\hi3515v100\config.mk 中,在这里用来计算其他的地址偏移

.globl _armboot_start

_armboot_start:

       .word _start

.globl _img_end

_img_end:

       .word __img_end

/*

* These are defined in the board-specific linker script.

*/

.globl _bss_start

_bss_start:

       .word __bss_start

.globl _bss_end

_bss_end:

       .word _end

以上代码定义了一些断地址,并导出为全局变量(.globle),在连接文件里面有对这些变量赋值,在这里同样用于计算偏移

#ifdef CONFIG_USE_IRQ

/* IRQ stack memory (calculated at run-time) */

.globl IRQ_STACK_START

IRQ_STACK_START:

       .word      0x0badc0de

/* IRQ stack memory (calculated at run-time) */

.globl FIQ_STACK_START

FIQ_STACK_START:

       .word 0x0badc0de

#endif

此处尚有疑问

#ifdef CONFIG_HISILICON

_clr_remap_rom_entry:

       .word   ROM_TEXT_ADRS + do_clr_remap - TEXT_BASE

_clr_remap_nand_entry:

       .word   NAND_TEXT_ADRS + do_clr_remap - TEXT_BASE

#endif

此处计算do_clr_remap的LMA,由于没有进行代码搬移前代码是执行在LMA地址上的(同时这一段代码也是地址无关的代码即PIC,关于地址无关的代码见博文http://hi.baidu.com/kinylei/blog/item/c7acf92235b8104493580795.html ),此处分别计算代码存储在norflash和nandflash里面的LMA.

3.3 设置其他相关

reset:

       /*

        * set the cpu to SVC32 mode

        */

       mrs  r0,cpsr

       bic   r0,r0,#0x1f

       orr   r0,r0,#0xd3

       msr  cpsr,r0

CPSR位图

              /*

        * we do sys-critical inits only at reboot,

        * not when booting from ram!

        */

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

       /*

        * flush v4 I/D caches

        */

       mov r0, #0

       mcr  p15, 0, r0, c7, c7, 0       /* flush v3/v4 cache */

       mcr  p15, 0, r0, c8, c7, 0       /* flush v4 TLB */

       /*

        * disable MMU stuff and caches

        */

       mrc  p15, 0, r0, c1, c0, 0

       bic   r0, r0, #0x00002300      /* clear bits 13, 9:8 (--V- --RS) */

       bic   r0, r0, #0x00000087      /* clear bits 7, 2:0 (B--- -CAM) */

       orr   r0, r0, #0x00000002      /* set bit 2 (A) Align */

       mcr  p15, 0, r0, c1, c0, 0

以上禁止MMU

       ldr   r0, =REG_BASE_SCTL

       ldr     r1, [r0, #0x8c]

       and     r1, r1, #0x60

       lsr    r4, r1, #5

以上获取BOOT状态到R4

       mov       r0, pc, lsr#24s

       cmp       r0, #0x0

       bne  do_clr_remap

检测是否需要跳转,PC的高八位如果不为0(已经在ram中运行了)则跳转

       cmp     r4, #2           /* boot from nand flash*/

       ldreq   pc, _clr_remap_nand_entry

       cmp       r4, #0             /* boot from nor flash */

       ldreq   pc, _clr_remap_rom_entry

此处的_clr_remap_nand_entry与_clr_remap_rom_entry为LMA地址,前面已分析

do_clr_remap:

       ldr     r4, =REG_BASE_SCTL

       @ldr       r0, =REG_VALUE_SC_NOLOCK

       @str       r0, [r4, #REG_VALUE_SC_LOCKED]

       ldr   r0, [r4, #REG_SC_CTRL]

       @Set clear remap bit.

       orr   r0, #(1<<8)

       str    r0, [r4, #REG_SC_CTRL]

       @Setup ITCM (ENABLED, 4KB)

       ldr   r0, =( 1 | (MEM_CONF_ITCM_SIZE<<2) | MEM_BASE_ITCM)

       mcr     p15, 0, r0, c9, c1, 1

       以上清除重映射,清除重映射后地址0x000000处安排为ITCM,此处有一个疑问,既然还运行在flash里面那么清重映射后就会运行在ITCM里面,但是ITCM里面保存有代码吗?

       @enable I-Cache now

       mrc  p15, 0, r0, c1, c0, 0

       orr   r0, r0, #0x00001000      /* set bit 12 (I) I-Cache */

       mcr  p15, 0, r0, c1, c0, 0

       @Setup lowlevel sp

       ldr   sp, =(MEM_BASE_ITCM + MEM_SIZE_ITCM)

//     @Check if I'm running in static mem bank

       mov r0, pc, lsr#28

       cmp r0, #(TEXT_BASE>>28)

       /*

        * Go setup Memory and board specific bits prior to relocation.

        */

       beq  relocate

       bl    lowlevel_init   /* go setup pll,mux,memory */

#endif

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

relocate:                       /* relocate U-Boot to RAM       */

       ldr     r0, =REG_BASE_SCTL

       ldr     r6, [r0, #0x8c]

       and     r6, #0x60

       lsr   r4, r6, #5

       adr   r0, _start        /* r0 <- current position of code   */

       ldr   r1, _TEXT_BASE         /* test if we run from flash or RAM */

       cmp     r0, r1                  /* don't reloc during debug         */

       beq     stack_setup

       ldr   r2, _armboot_start

       ldr   r3, _img_end

       sub  r2, r3, r2        /* r2 <- size of armboot            */

       cmp       r4, #2

       ldreq   r2, =(CFG_NAND_U_BOOT_ONE_PART)

       add  r2, r0, r2        /* r2 <- source end address         */

copy_loop:

       ldmia      r0!, {r3-r10}         /* copy from source address [r0]    */

       stmia       r1!, {r3-r10}         /* copy to   target address [r1]    */

       cmp r0, r2                    /* until source end addreee [r2]    */

       ble   copy_loop

#endif     /* CONFIG_SKIP_RELOCATE_UBOOT */

以上重定位代码,既把代码段复制到ram空间里面

/* Set up the stack                                         */

stack_setup:

       ldr   r0, _TEXT_BASE         /* upper 128 KiB: relocated uboot   */

       sub  r0, r0, #CFG_MALLOC_LEN      /* malloc area                      */

       sub  r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */

#ifdef CONFIG_USE_IRQ

       sub  r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

       sub  sp, r0, #12             /* leave 3 words for abort-stack    */

以上设置堆栈

clear_bss:

       ldr   r0, _bss_start         /* find start of bss segment        */

       ldr   r1, _bss_end          /* stop here                        */

       mov r2, #0x00000000           /* clear                            */

clbss_l:str       r2, [r0]           /* clear loop...                    */

       add  r0, r0, #4

       cmp r0, r1

       ble   clbss_l

以上清除BSS

       ldr   pc, _start_armboot

_start_armboot:

       .word start_armboot

以上跳转到第二段

下图是分析到目前为止存储空间的示意图

嵌入式 hi3518c默认看门狗没有开启,uboot汇编start.s解析