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
下面是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
相关文章推荐
- mini-uboot 启动过程简单分析
- mini-uboot 启动过程简单分析
- mini-uboot 启动过程简单分析
- u-boot简单学习笔记(三)——AR9331 uboot启动分析
- u-boot_smdkv210 分析五:硬件启动过程
- NanoPC-T2 Uboot启动过程分析 - 2-4 init_sequence_f[] part 2
- U-Boot启动过程完全分析
- u-boot启动过程源码分析之第二阶段(S3C24XX系列)
- Spring Boot 2.x 启动全过程源码分析(上)入口类剖析
- u-boot分析 六 (从code flow看u-boot到kernel的启动过程)
- OMPL138及U-Boot的启动过程分析(三)
- U-Boot启动过程--详细版的完全分析(全)
- U-Boot启动过程完全分析
- Angular 2 应用启动过程简单分析
- u-boot-201611 启动过程分析——基于smdk2410
- (一)U-Boot启动过程--详细版的完全分析
- NanoPC-T2 Uboot启动过程分析 - 2-5 board_init_r() part 1
- U-Boot启动过程完全分析
- 移植u-boot学习笔记1-----实验及分析启动过程之概述