您的位置:首页 > 其它

mini-uboot 启动过程简单分析

2016-06-19 19:53 489 查看
单片机有最小系统,所谓最小系统,就是单片机能正常工作所需要的最少外设。对于Uboot来说,同样有个最小系统,因为Uboot最主要的功能就是引导内核。下面我们通过一个简单的Mini-Uboot来分析Uboot的启动加载过程。(只是分析过程,此Uboot具有引导内核功能)

注:这个uboot 只是具有基本的内核引导功能,只是作为前期简单的学习使用,入门而已,并不是正常的uboot 启动流程

具体uboot (u-boot-2013.01)启动过程移步Exynos4412 Uboot 移植(二)—— Uboot 启动流程分析

下面是mini-uboot 的根目录树状图:



我们拿到一个工程,想了解它的功能,最方便的就是读它的makefile。

一、Makefile

[cpp] view
plain copy







sinclude 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 copy







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

OBJS为依赖文件,生成的.o文件。

[cpp] view
plain copy







ifeq ($(ARCH), arm)

CROSS_COMPILE=arm-cortex_a8-linux-gnueabi-

endif

根据相应的架构,制作相应的交叉编译工具。

[cpp] view
plain copy







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

第一步:连接 ;第二步:格式转换;第三步:反汇编 " >" 为重定向的意思;

[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 copy







OUTPUT_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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: