您的位置:首页 > 其它

mini-uboot 启动过程简单分析

2018-03-07 21:27 507 查看
单片机有最小系统,所谓最小系统,就是单片机能正常工作所需要的最少外设。对于Uboot来说,同样有个最小系统,因为Uboot最主要的功能就是引导内核。下面我们通过一个简单的Mini-Uboot来分析Uboot的启动加载过程。(只是分析过程,此Uboot具有引导内核功能)注:这个uboot 只是具有基本的内核引导功能,只是作为前期简单的学习使用,入门而已,并不是正常的uboot 启动流程       具体uboot (u-boot-2013.01)启动过程移步Exynos4412 Uboot 移植(二)—— Uboot 启动流程分析
下面是mini-uboot 的根目录树状图:

     我们拿到一个工程,想了解它的功能,最方便的就是读它的makefile。一、Makefile[cpp] view plain copysinclude include/config.mk  
  
#ARCH=arm  
#CPU=arm920t  
#VENDOR=samsung  
#SOC=s3c2410  
#BOARD=smdk2410  
  
SRC_TREE:=$(shell pwd)  
MKCONFIG=$(SRC_TREE)/mkconfig    
  
INCLUDE_PATH=include  
DRIVER_PATH=driver  
LIB_DIR=lib  
  
  
CFLAG=-mabi=apcs-gnu -fno-builtin  -fno-builtin-function -g -O0 -c  -I$(INCLUDE_PATH) -I$(DRIVER_PATH) -o   
LDFLAG=-Tcpu/arm/arm_cortexa8/map.lds  -o  
OBJS= cpu/$(ARCH)/$(CPU)/start.o  
OBJS+=lib_arm/board.o  
OBJS+=board/$(VENDOR)/$(BOARD)/lowlevel_init.o  
OBJS+=board/$(VENDOR)/$(BOARD)/mem_setup.o  
OBJS+=board/$(VENDOR)/$(BOARD)/nand.o  
OBJS+=driver/uart.o  
OBJS+=lib/string.o  
OBJS+=common/do_go.o  
OBJS+=common/main.o  
  
ifeq ($(ARCH), arm)   
CROSS_COMPILE=arm-cortex_a8-linux-gnueabi-  
endif  
  
PROJ_NAME=mini_uboot  
      
all: $(OBJS)   
    $(CROSS_COMPILE)ld $(OBJS) $(LDFLAG) $(PROJ_NAME).elf                
    $(CROSS_COMPILE)objcopy -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin   
    $(CROSS_COMPILE)objdump -D $(PROJ_NAME).elf  > $(PROJ_NAME).dis  
    cp *.bin /tftpboot  
  
%.o: %.S  
    $(CROSS_COMPILE)gcc $(CFLAG) $@ $<       
%.o: %.s  
    $(CROSS_COMPILE)gcc $(CFLAG) $@ $<       
  
%.o: %.c  
    $(CROSS_COMPILE)gcc $(CFLAG) $@ $<       
  
fsc100_config:          #    ARCH  CPU       VENDOR   BOARD  SOC  
    $(MKCONFIG) $(@:_config=) arm arm_cortexa8 samsung fsc100 s5pc100  
    #mkconfig  fsc100 arm arm_cortexa8 samsung fsc100 s5pc100  
  
smdk2410_config:            #    ARCH  CPU       VENDOR   BOARD  SOC  
    $(MKCONFIG) $(@:_config=) arm arm920t samsung smdk2410 s3c2410  
  
clean:  
    @rm -rf $(OBJS) *.bin *.elf config.mk  
这里以2440为例,咱们来分析:[cpp] view plain copy#ARCH=arm  
#CPU=arm920t  
#VENDOR=samsung  
#SOC=s3c2410  
#BOARD=smdk2410  
架构为arm,CPU为arm920t,生产商 samsung,片上系统sc2410,板子为smdk2410。[cpp] view plain copyOBJS= cpu/$(ARCH)/$(CPU)/start.o  
OBJS+=lib_arm/board.o  
OBJS+=board/$(VENDOR)/$(BOARD)/lowlevel_init.o  
OBJS+=board/$(VENDOR)/$(BOARD)/mem_setup.o  
OBJS+=board/$(VENDOR)/$(BOARD)/nand.o  
OBJS+=driver/uart.o  
OBJS+=lib/string.o  
OBJS+=common/do_go.o  
OBJS+=common/main.o  
OBJS为依赖文件,生成的.o文件。[cpp] view plain copyifeq ($(ARCH), arm)   
CROSS_COMPILE=arm-cortex_a8-linux-gnueabi-  
endif  
根据相应的架构,制作相应的交叉编译工具。[cpp] view plain copyall: $(OBJS)   
    $(CROSS_COMPILE)ld $(OBJS) $(LDFLAG) $(PROJ_NAME).elf                
    $(CROSS_COMPILE)objcopy -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin   
    $(CROSS_COMPILE)objdump -D $(PROJ_NAME).elf  > $(PROJ_NAME).dis  
第一步:连接 ;第二步:格式转换;第三步:反汇编 " >" 为重定向的意思;[cpp] view plain copy%.o: %.S  
    $(CROSS_COMPILE)gcc $(CFLAG) $@ $<       
%.o: %.s  
    $(CROSS_COMPILE)gcc $(CFLAG) $@ $<       
  
%.o: %.c  
    $(CROSS_COMPILE)gcc $(CFLAG) $@ $<       
将所有的.S 文件、.s文件、.c文件编译成.o文件。注意:.S文件可以在编译过程接受参数,.s文件不可以。 二、链接文件[cpp] view plain copyOUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")  
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/  
OUTPUT_ARCH(arm)  
ENTRY(_start)  //指定入口地址  
SECTIONS    //段信息  
{  
    /* . */   
    . = 0x22000000; //elf文件的入口地址  
    . = ALIGN(4);   //指定四字节对齐  
    .text      :    //代码段  
    {  
        cpu/arm/arm_cortexa8/start.o(.text) //确保执行的第一段代码是start.o  
        *(.text)        //所有代码段融合在一起  
    }  
    . = ALIGN(4);  
    .rodata :   //只读数据段  
    { *(.rodata) }  //所有数据段  
    . = ALIGN(4);  
    .data :     //数据段  
    { *(.data) }  
    . = ALIGN(4);  
  
    _start_bss = .; //bss段开始地址  
    .bss :  
     { *(.bss) }  
    _end_bss = .;       //bss段结束地址,两者可确定bss段大小  
}  

三、start.s文件(Uboot执行的第一个文件)[cpp] view plain copy@ 汇编中的宏  
.equ USER_MODE, 0x10    @define USER_MODE 0x10  
.equ IRQ_MODE,  0x12  
.equ SVC_MODE,  0x13  
.equ MODE_MASK, 0x1f  
  
.section .text  
.global _start  
  
    @ 不支持异常处理的,这里只写了复位异常处理  
_start:  
vector:  
    b  reset_handler  
    nop     @undef ......  
    nop  
    nop  
    nop  
    nop  
    nop  
    nop  
  
reset_handler:  
    @step 1: svc close irq fiq      //第一步:将运行模式改成SVC模式    
    mrs r0, cpsr            //修改cpsr模式位  
    bic r0, r0, #0x1f  
    orr r0, r0, #0xc0  @IRQ FIQ     //关闭IRQ FIQ  
    msr cpsr_c, r0  
  
    @step 2: cache 关闭I CACHE D CACHE    //第二步:关闭cache,直接运行,不需缓存  
    mrc p15, 0, r0, c12, c0, 0  
    bic r0, #0x1000  
    bic r0, #0x2  
    mcr p15, 0, r0, c12, c0, 0  
      
    @step 3:                //第三步:调用电路板级初始化程序, system clock , dram, watchdog  
    @bl low_level_init      //初始化时钟、dram、关闭看门狗  
  
    @step 4: sp-> 0x30000000     //第四步:设置栈指针,使其指向一个地址即可  
    ldr sp, =0x2e000000  
  
    @step 5: mini_uboot.bin  > 16KB   bin < 16KB   
    @step 5 代码自搬移  
    @copy_miniuboot_rto_sdram 如果你的代码大于了16KB代码需要实现自我搬移  
  
    @step 6:                //第六步:清除BSS段,BSS段大小由链接文件里确定   
    @STEP 6.1 , 清除 BSS段  
    @  
clear_bss:  
    ldr r0, =_start_bss   @| BSS 起始地址  
    ldr r1, =_end_bss     @| BSS 终止地址  
    mov r2, #0  
bss_loop:  
    cmp r0, r1  
    strne r2, [r0], #4  
    bne bss_loop  
  
    @step  7, 进入C           //跳转到C程序入口  
    b start_armboot  
stop:  
    b stop  
  
    .end  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: