×
单片机 > 单片机程序设计 > 详情

【系统移植】uboot详细分析

发布时间:2020-12-29 发布时间:
|

uboot使用

    uboot控制台,倒计时
    命令: 调试,操作一些硬件

setenv printenv saveenv 
 nand erase 
 nand write 
 tftp 20008000 zImage
 help: uboot可以提供哪些命令
 setenv == set == sete == seten

    环境变量: 为命令提供参数
     serverip : tftp命令提供tftp服务器的地址
     ipaddr : tftp命令提供tftp客户端(开发板)的地址

两个环境变量

    uboot: 下载内核,并启动内核
    bootcmd:  倒计时结束后,uboot应该自动做什么事情

 set bootcmd tftp 20008000 zImage ; bootm 20008000
 set serverip 192.168.7.2
 set ipaddr 192.168.7.6
 set ethaddr 00:22:23:24:25:ee

   倒计时结束的时候,uboot会执行bootcmd中的内容:
   tftp 20008000 zImage ; bootm 20008000

   从tftp服务器(serverip)中将zImage文件(/tftpboot/)下载到开发板(ipaddr)中内存的20008000

   set bootcmd tftp 20008000 zImage ; bootm 20008000

  bootargs: 负责告诉内核文件系统在哪里(uboot传递给内核, 内核要用)

  set bootargs init=/linuxrc console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.7.2:/opt/filesystem ip=192.168.7.6
  root=xxxx : 根文件系统目录在哪里
  /dev/nfs : 根文件系统目录在网络的远端
  
  nfsroot=xxxx: 根文件系统目录在哪台机器的哪个文件路径
  nfsroot=192.168.7.2:/opt/filesystem
  ip=192.168.7.6: 系统登录的时候,静态分配一个ip

  如果root=/dev/nfs
  root=/dev/nfs + nfsroot=xxxx +ip=xx
  
  如果root=/dev/mtdblock2(文件系统制作的时候会讲)
   root=/dev/mtdblock2 + rootfstype=cramfs
  
  console=ttySAC0,115200 : 内核启动过程中,调试信息往哪里输出,printk
  init=/linuxrc : 指定第一个init进程的可执行代码文件
  /opt/filesystem==> host: /etc/exports
  sudo vim /etc/exports
  /opt/filesystem         *(subtree_check,rw,no_root_squash,async)
  /opt/fs100/rootfs               *(subtree_check,rw,no_root_squash,async)

 

启动内核:go/bootm

官方的uboot

zImage
  : go
  set bootcmd tftp 20008000 zImage ; go 20008000
 
 uImage 
  : bootm(下载地址,不能是20008000)
  set bootcmd tftp 20800000 uImage ; bootm 20800000
 
 下载地址的选用:
  go==> 可以是任何地址
  bootm==> 20008000+zImage的大小以上==>20800000 
 综合用法:
  set bootcmd tftp 20800000 zImage ; go 20800000
  set bootcmd tftp 20800000 uImage ; bootm 20800000
uboot1.3.4:
 zImage/uImage ==>bootm
 set bootcmd tftp 20800000 uImage ; bootm 20800000

 

uboot的连接脚本

    所在路径:cpu/arm_cortexa8/u-boot.lds

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start) // 入口函数
SECTIONS
{
        . = 0x00000000;  // 当前的起始位置0x0
        . = ALIGN(4);
        .text(目标文件)   :
        { 
                cpu/arm_cortexa8/start.o        (.text) // 第一个文件的.text
                *(.text)
        }
        . = ALIGN(4); // 当前位置四字节对齐
        .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
        . = ALIGN(4);
        .data : { *(.data) }
        . = ALIGN(4);
        .got : { *(.got) }
        __u_boot_cmd_start = .;  // 用__u_boot_cmd_start记录当前的位置, 代码会用到,全局的
        .u_boot_cmd : { *(.u_boot_cmd) } // 段数据
        __u_boot_cmd_end = .; // 结束位置
        . = ALIGN(4);
        __bss_start = .;
        .bss : { *(.bss) }
        _end = .;
}

连接的基地址:
     -Ttext 0x34800000==>board/samsung/smdkc100/config.mk
     TEXT_BASE = 0x34800000
     1,TEXT_BASE指定uboot的连接的起始位置
     2,指定uboot重定位的位置(可以改成0x2ff00000)

 

uboot配置的详细说明

 

make smdkc100_config
vim Makefile
unconfig:
        @rm -f $(obj)include/config.h $(obj)include/config.mk
                $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp
                $(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep
MKCONFIG        := $(SRCTREE)/mkconfig == ./mkconfig  shell脚本(可执行程序)

smdkc100_config:        unconfig
        @$(MKCONFIG) $(@:_config=) arm arm_cortexa8 smdkc100 samsung s5pc1xx
 ./mkconfig  smdkc100 arm arm_cortexa8 smdkc100 samsung s5pc1xx
 执行一个脚本: 传递了6个参数(控制源码的编译)
 arm : 架构==> lib_arm
 smdkc100 : include/configs/smdkc100.h  // 开发板所有的宏的配置
 arm_cortexa8 : arm名 ==> cpu/arm_cortexa8
 smdkc100 samsung : 开发板名==> board/samsung/smdkc100
 s5pc1xx :cpu ==>cpu/arm_cortexa8/s5pc1xx

$(@:_config=): $@:_config= ==>smdkc100_config:_config=  // _config替换成空,去掉
  $(@:_config=xxx) ===>smdkc100xxx

 

uboot第一阶段启动流程

 

1,建立异常向量表:
_start: b reset
 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

2,
reset:
 /*
  * set the cpu to SVC32 mode, disable F, I
  */
 mrs r0, cpsr
 bic r0, r0, #0x1f
 orr r0, r0, #0xd3
 msr cpsr,r0

 bl cpu_init_crit
   |
   /*
    * Invalidate L1 I/D
    */
   mov r0, #0   @ set up for MCR
   mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
   mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
   /*
    * disable MMU stuff and caches
    */
   mrc p15, 0, r0, c1, c0, 0
   bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
   bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
   orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
   orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB
   mcr p15, 0, r0, c1, c0, 0

   bl lowlevel_init  //lowlevel_init.S (boardsamsungsmdkc100):lowlevel_init:
     |
     /* Disable Watchdog */
     ldr r0, =S5PC100_WATCHDOG_BASE  @0xEA200000
     orr r0, r0, #0x0
     str r5, [r0]
     /* setting SRAM */
     ldr r0, =S5PC100_SROMC_BASE
     ldr r1, =0x9
     str r1, [r0]

     /* S5PC100 has 3 groups of interrupt sources */
     ldr r0, =S5PC100_VIC0_BASE   @0xE4000000
     ldr r1, =S5PC100_VIC1_BASE   @0xE4000000
     ldr r2, =S5PC100_VIC2_BASE   @0xE4000000
     /* Disable all interrupts (VIC0, VIC1 and VIC2) */
     mvn r3, #0x0
     str r3, [r0, #0x14]    @INTENCLEAR
     str r3, [r1, #0x14]    @INTENCLEAR
     str r3, [r2, #0x14]    @INTENCLEAR
     /* Set all interrupts as IRQ */
     str r5, [r0, #0xc]    @INTSELECT
     str r5, [r1, #0xc]    @INTSELECT
     str r5, [r2, #0xc]    @INTSELECT
     /* Pending Interrupt Clear */
     str r5, [r0, #0xf00]   @INTADDRESS
     str r5, [r1, #0xf00]   @INTADDRESS
     str r5, [r2, #0xf00]   @INTADDRESS
     bl uart_asm_init // 只是设置了gpio的功能,波特率的设置在第二阶段
     #if 1  // 改动的部分
     /* init system clock */
     bl system_clock_init // 基本上没太大问题
     bl mem_ctrl_asm_init
     //mem_setup.S boardsamsungSmdkc100 
     // 内存的初始化比较复杂, 原厂会提供(1.3.4)
     // 向FAE要
     // 这部分代码运行有问题
     1,mem_ctrl_asm_init
     2,mem_setup.S需要被编译<===boardsamsungSmdkc100Makefile
     3,内存初始化代码应该在前16k (反汇编)
      修改cpu/arm_cotexa8/u-boot.lds


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM基础知识八