单片机有最小系统,Uboot同样也有, mini-uboot 启动过程简单分析
2017年10月27日 09:24 发布者:技术小白
单片机有最小系统,所谓最小系统,就是单片机能正常工作所需要的最少外设。对于Uboot来说,同样有个最小系统,因为Uboot最主要的功能就是引导内核。下面我们通过一个简单的Mini-Uboot来分析Uboot的启动加载过程。(只是分析过程,此Uboot具有引导内核功能)
注:这个uboot 只是具有基本的内核引导功能,只是作为前期简单的学习使用,入门而已,并不是正常的uboot 启动流程
下面是mini-uboot 的根目录树状图:
我们拿到一个工程,想了解它的功能,最方便的就是读它的makefile。一、Makefilehttps://mmbiz.qpic.cn/mmbiz_png/MLfSTncC3tPMavpHf2f8C0MbERTakpQjvGbmg5t3laAqTYiaA770MdgN4LgjfBtHQRWRHyutSOwYVCVSblzDF5Q/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1> view plain copy1. sinclude include/config.mk 2. 3. #ARCH=arm 4. #CPU=arm920t 5. #VENDOR=samsung 6. #SOC=s3c2410 7. #BOARD=smdk2410 8. 9. SRC_TREE:=$(shell pwd) 10. MKCONFIG=$(SRC_TREE)/mkconfig 11. 12. INCLUDE_PATH=include 13. DRIVER_PATH=driver 14. LIB_DIR=lib 15. 16. 17. CFLAG=-mabi=apcs-gnu -fno-builtin -fno-builtin-function -g -O0 -c -I$(INCLUDE_PATH) -I$(DRIVER_PATH) -o 18. LDFLAG=-Tcpu/arm/arm_cortexa8/map.lds -o 19. OBJS= cpu/$(ARCH)/$(CPU)/start.o 20. OBJS+=lib_arm/board.o 21. OBJS+=board/$(VENDOR)/$(BOARD)/lowlevel_init.o 22. OBJS+=board/$(VENDOR)/$(BOARD)/mem_setup.o 23. OBJS+=board/$(VENDOR)/$(BOARD)/nand.o 24. OBJS+=driver/uart.o 25. OBJS+=lib/string.o 26. OBJS+=common/do_go.o 27. OBJS+=common/main.o 28. 29. ifeq ($(ARCH), arm) 30. CROSS_COMPILE=arm-cortex_a8-linux-gnueabi- 31. endif 32. 33. PROJ_NAME=mini_uboot 34. 35. all: $(OBJS) 36. $(CROSS_COMPILE)ld $(OBJS) $(LDFLAG) $(PROJ_NAME).elf 37. $(CROSS_COMPILE)objcopy -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin 38. $(CROSS_COMPILE)objdump -D $(PROJ_NAME).elf > $(PROJ_NAME).dis 39. cp *.bin /tftpboot 40. 41. %.o: %.S 42. $(CROSS_COMPILE)gcc $(CFLAG) $@ $< 43. %.o: %.s 44. $(CROSS_COMPILE)gcc $(CFLAG) $@ $< 45. 46. %.o: %.c 47. $(CROSS_COMPILE)gcc $(CFLAG) $@ $< 48. 49. fsc100_config: # ARCH CPU VENDOR BOARD SOC 50. $(MKCONFIG) $(@:_config=) arm arm_cortexa8 samsung fsc100 s5pc100 51. #mkconfig fsc100 arm arm_cortexa8 samsung fsc100 s5pc100 52. 53. smdk2410_config: # ARCH CPU VENDOR BOARD SOC 54. $(MKCONFIG) $(@:_config=) arm arm920t samsung smdk2410 s3c2410 55. 56. clean: 57. @rm -rf $(OBJS) *.bin *.elf config.mk
这里以2440为例,咱们来分析: view plain copy1. #ARCH=arm 2. #CPU=arm920t 3. #VENDOR=samsung 4. #SOC=s3c2410 5. #BOARD=smdk2410
架构为arm,CPU为arm920t,生产商 samsung,片上系统sc2410,板子为smdk2410。
view plain copy1. OBJS= cpu/$(ARCH)/$(CPU)/start.o 2. OBJS+=lib_arm/board.o 3. OBJS+=board/$(VENDOR)/$(BOARD)/lowlevel_init.o 4. OBJS+=board/$(VENDOR)/$(BOARD)/mem_setup.o 5. OBJS+=board/$(VENDOR)/$(BOARD)/nand.o 6. OBJS+=driver/uart.o 7. OBJS+=lib/string.o 8. OBJS+=common/do_go.o 9. OBJS+=common/main.o
OBJS为依赖文件,生成的.o文件。 view plain copy
1. ifeq ($(ARCH), arm) 2. CROSS_COMPILE=arm-cortex_a8-linux-gnueabi- 3. endif
根据相应的架构,制作相应的交叉编译工具。 view plain copy1. all: $(OBJS) 2. $(CROSS_COMPILE)ld $(OBJS) $(LDFLAG) $(PROJ_NAME).elf 3. $(CROSS_COMPILE)objcopy -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin 4. $(CROSS_COMPILE)objdump -D $(PROJ_NAME).elf > $(PROJ_NAME).dis
第一步:连接 ;第二步:格式转换;第三步:反汇编 " >" 为重定向的意思; view plain copy1. %.o: %.S 2. $(CROSS_COMPILE)gcc $(CFLAG) $@ $< 3. %.o: %.s 4. $(CROSS_COMPILE)gcc $(CFLAG) $@ $< 5. 6. %.o: %.c 7. $(CROSS_COMPILE)gcc $(CFLAG) $@ $<
将所有的.S 文件、.s文件、.c文件编译成.o文件。注意:.S文件可以在编译过程接受参数,.s文件不可以。
二、链接文件https://mmbiz.qpic.cn/mmbiz_png/MLfSTncC3tPMavpHf2f8C0MbERTakpQjvGbmg5t3laAqTYiaA770MdgN4LgjfBtHQRWRHyutSOwYVCVSblzDF5Q/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1> view plain copy1. OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 2. /*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ 3. OUTPUT_ARCH(arm) 4. ENTRY(_start) //指定入口地址 5. SECTIONS //段信息 6. { 7. /* . */ 8. . = 0x22000000; //elf文件的入口地址 9. . = ALIGN(4); //指定四字节对齐 10. .text : //代码段 11. { 12. cpu/arm/arm_cortexa8/start.o(.text) //确保执行的第一段代码是start.o 13. *(.text) //所有代码段融合在一起 14. } 15. . = ALIGN(4); 16. .rodata : //只读数据段 17. { *(.rodata) } //所有数据段 18. . = ALIGN(4); 19. .data : //数据段 20. { *(.data) } 21. . = ALIGN(4); 22. 23. _start_bss = .; //bss段开始地址 24. .bss : 25. { *(.bss) } 26. _end_bss = .; //bss段结束地址,两者可确定bss段大小 27. }
三、start.s文件(Uboot执行的第一个文件)https://mmbiz.qpic.cn/mmbiz_png/MLfSTncC3tPMavpHf2f8C0MbERTakpQjvGbmg5t3laAqTYiaA770MdgN4LgjfBtHQRWRHyutSOwYVCVSblzDF5Q/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1> view plain copy1. @ 汇编中的宏 2. .equ USER_MODE, 0x10 @define USER_MODE 0x10 3. .equ IRQ_MODE, 0x12 4. .equ SVC_MODE, 0x13 5. .equ MODE_MASK, 0x1f 6. 7. .section .text 8. .global _start 9. 10. @ 不支持异常处理的,这里只写了复位异常处理 11. _start: 12. vector: 13. b reset_handler 14. nop @undef ...... 15. nop 16. nop 17. nop 18. nop 19. nop 20. nop 21. 22. reset_handler: 23. @step 1: svc close irq fiq //第一步:将运行模式改成SVC模式 24. mrs r0, cpsr //修改cpsr模式位 25. bic r0, r0, #0x1f 26. orr r0, r0, #0xc0 @IRQ FIQ //关闭IRQ FIQ 27. msr cpsr_c, r0 28. 29. @step 2: cache 关闭I CACHE D CACHE //第二步:关闭cache,直接运行,不需缓存 30. mrc p15, 0, r0, c12, c0, 0 31. bic r0, #0x1000 32. bic r0, #0x2 33. mcr p15, 0, r0, c12, c0, 0 34. 35. @step 3: //第三步:调用电路板级初始化程序, system clock , dram, watchdog 36. @bl low_level_init //初始化时钟、dram、关闭看门狗 37. 38. @step 4: sp-> 0x30000000 //第四步:设置栈指针,使其指向一个地址即可 39. ldr sp, =0x2e000000 40. 41. @step 5: mini_uboot.bin > 16KB bin < 16KB 42. @step 5 代码自搬移 43. @copy_miniuboot_rto_sdram 如果你的代码大于了16KB代码需要实现自我搬移 44. 45. @step 6: //第六步:清除BSS段,BSS段大小由链接文件里确定 46. @STEP 6.1 , 清除 BSS段 47. @ 48. clear_bss: 49. ldr r0, =_start_bss @| BSS 起始地址 50. ldr r1, =_end_bss @| BSS 终止地址 51. mov r2, #0 52. bss_loop: 53. cmp r0, r1 54. strne r2, , #4 55. bne bss_loop 56. 57. @step 7, 进入C //跳转到C程序入口 58. b start_armboot 59. stop: 60. b stop 61. 62. .end