嵌入式Linux移植和Uboot(二):Uboot命令、启动过程、移植和烧写介绍

接上:嵌入式Linux移植和Uboot(一):Bootloader介绍,U-boot介绍(特点,目录结构)

U-boot命令介绍

命令分类:环境设置、数据传输、存贮器操作及其他

printenv 打印环境变量。

Uboot>printenv
baudrate=115200
ipaddr=192.168.1.1
ethaddr=12:34:56:78:9A:BC
serverip=192.168.1.5

setenv 设置新的变量

Uboot> setenv myboard  FS2410
Uboot>printenv
baudrate=115200
ipaddr=192.168.1.1
ethaddr=12:34:56:78:9A:BC
serverip=192.168.1.5
myboard=FS2410
Environment size: 102/8188 bytes

saveenv :将当前定义的所有变量的值存入flash中

tftp 通过网络下载程序

Uboot> tftp  33000000  zImage
Uboot> go  33000000

loadb下载二进制数据

通过串口Kermit协议下载二进制数据

protect 写保护操作

protect on 1:0-3(就是对第一块FLASH的0-3扇区进行保护)
protect off 1:0-3取消写保护

erase 擦除扇区

erase: 删除FLASH的扇区
erase 1:0-2(就是对每一块FLASH的0-2扇区进行删除)

go 命令

执行内存中的二进制代码,一个简单的跳转到指定地址

bootm 执行内存中的二进制代码

要求二进制代码为指定格式的。通常为mkimage处理过的二进制文件

bootp 通过网络启动

通过网络启动,需要提前设置好硬件地址

其他

md 显示内存区的内容
mm 修改内存,地址自动递增
nm 修改内存,地址不自动递增
mw 填充内存  mw 0x32000000 ff 0x10000
mtest 测试内存
cp 拷贝一块内存到另一块
cmp 比较两块内存区
nand info: 显示NAND 设备
nand device [dev]:显示或设置当前设备
nand bad – 显示坏块
nand read[.jffs2[s]]  addr off size
nand write[.jffs2] 	addr off size
nand erase [clean] [off size] 
nand read.oob addr off size
nand write.oob addr off size

U-Boot 启动过程介绍

第一阶段代码在Flash中运行,用汇编实现

  • 设置CPSR、关闭看门狗、屏蔽中断
  • 关MMU、关闭I/D cache、内存初始化
  • 自搬运、设置堆栈、清空BSS段

cpu/arm920t/start.S

异常向量表

.globl _start
_start:  b  start_code
     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

复位

start_code:
   mrs	r0, cpsr	
   bic	r0, r0, #0x1f	   ;  位清零 
   orr	r0, r0, #0xd3   ;  逻辑或0xd3= 1101 0011
   msr	cpsr, r0

在这里插入图片描述

模式位含义

在这里插入图片描述

关闭看门狗

ldr     r0, =pWTCON	
mov     r1, #0x0	
str     r1, [r0]

在这里插入图片描述

关闭中断

mov   r1, #0xffffffff	
ldr	r0,  =INTMSK	
str	r1,  [r0]

在这里插入图片描述

刷新指令/数据缓存

mov	r0, #0	
mcr	p15, 0, r0, c7, c7, 0  /* flush v3/v4 cache */
mcr	p15, 0, r0, c8, c7, 0  /* flush v4 TLB */

在这里插入图片描述

禁用MMU和缓存

mrc	p15, 0, r0, c1, c0, 0	
bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS)
bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM)
orr	r0, r0, #0x00000002	@ set bit 1 (A) Align	
orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache	
mcr	p15, 0, r0, c1, c0, 0

设置RAM

board/samsung/smdk2410/lowlevel_init.S

mov  ip, lr	
bl  lowlevel_init	
mov  lr, ip	
mov  pc, lr

重定位(Relocate)的概念

  • 加载地址和链接地址要求一致
    cpu/arm920t/u-boot.lds
  • 将u-boot从Flash中搬运到内存中

重定位的实现

relocate:			/* relocate U-Boot to RAM */
    adr   r0, _start	/*current address of code */
    ldr   r1, _TEXT_BASE	/* test if we run from flash or ram*/
    cmp  r0, r1             	/* don't reloc during debug */
    beq  stack_setup
    ldr  r2, _armboot_start
    ldr  r3, _armboot_end
    sub  r2, r3, r2		/* r2 <- size of armboot */
    add  r2, r0, r2		/* r2 <- source end address */
copy_loop:
    ldmia  r0!, {r3-r10}	/* copy from source address [r0] */
    stmia  r1!, {r3-r10}	/* copy to   target address [r1] */
    cmp  r0, r2		/* until source end addreee [r2] */
ble	copy_loop

设置堆栈

stack_setup:
    ldr  r0,  _TEXT_BASE  /* upper 128 KiB: relocated uboot */
    sub  r0,  r0,  #CFG_MALLOC_LEN    /* malloc area*/
    sub  r0,  r0,  #CFG_GBL_DATA_SIZE   /* bdinfo*/
#ifdef CONFIG_USE_IRQ
    sub  r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
    sub  sp,  r0,  #12	/* leave 3 words for abort-stack    */

清空BSS段、跳转到C函数

clear_bss:
    ldr   r0, _bss_start	/*   find start of bss segment    */
    ldr   r1, _bss_end	/*   stop here    */
    mov   r2, #0x00000000	/*    clear    */
clbss_l:  
    str   r2, [r0]	 /*    clear loop...      */
    add   r0, r0, #4
    cmp   r0, r1
    ble   clbss_l
    ldr   pc, _start_armboot
_start_armboot:	.word start_armboot

第二阶段代码

lib_arm/board.c

void start_armboot (void)
{
      ……
      init_fnc_ptr = init_sequence;
      for (; *init_fnc_ptr; ++init_fnc_ptr) {
          if ((*init_fnc_ptr)() != 0) { hang(); } }
      ……
      env_relocate();
      ……
      for (;;) {	
	   main_loop ();  }
}

在u-boot中添加命令

cmd_tbl_t/include/command.h

 struct cmd_tbl_s {
     char *name;
     int maxargs;
     int repeatable;
     int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
     char *usage;
     char *help;
};

添加命令hello

common/cmd_hello.c

 #include <common.h>
 #incude <command.h>

 int do_hello(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{  
      printf(“Hello World\n”);  
      return 0;
}
U_BOOT_CMD(
        hello, CFG_MAXARGS, 1, do_help,
        “hello  ---  brief info for hello\n”,
        “hello  ---  detailed info for hello\n”);

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name,
    maxargs, rep, cmd, usage, help}

common/Makefile

COBJS-y += cmd_hello.o

第三阶段代码

init_sequence[]

init_sequence[]数组保存着基本的初始化函数指针。这些函数名称和实现的程序文件在下列注释中。

init_fnc_t *init_sequence[] = {
       cpu_init,             /* 基本的处理器相关配置 -- cpu/arm920t/cpu.c */
       board_init,           /* 基本的板级相关配置 -- board/smdk2410/smdk2410.c */
       interrupt_init,       /* 初始化例外处理 -- cpu/arm920t/s3c24x0/interrupt.c */
       env_init,             /* 初始化环境变量 -- common/cmd_flash.c */
       init_baudrate,        /* 初始化波特率设置 -- lib_arm/board.c */
       serial_init,          /* 串口通讯设置 -- cpu/arm920t/s3c24x0/serial.c */
       console_init_f,       /* 控制台初始化阶段1 -- common/console.c */
       display_banner,       /* 打印u-boot信息 -- lib_arm/board.c */
       dram_init,            /* 配置可用的RAM -- board/smdk2410/smdk2410.c */
       display_dram_config,  /* 显示RAM的配置大小 -- lib_arm/board.c */
       NULL,
};

U-Boot的移植

U-Boot能够支持多种体系结构的处理器,支持的开发板也越来越多。因为Bootloader是完全依赖硬件平台的,所以在新电路板上需要移植U-Boot程序。

开始移植U-Boot之前,先要熟悉硬件电路板和处理器。确认U-Boot是否已经支持新开发板的处理器和I/O设备。假如U-Boot已经支持一块非常相似的电路板,那么移植的过程将非常简单。

移植U-Boot工作就是添加开发板硬件相关的文件、配置选项,然后配置编译。

开始移植之前,需要先分析一下U-Boot已经支持的开发板,比较出硬件配置最接近的开发板。选择的原则是,首先处理器相同,其次处理器体系结构相同,然后是以太网接口等外围接口。还要验证一下这个参考开发板的U-Boot,至少能够配置编译通过。

以S3C2410处理器的开发板为例,U-Boot-1.1.2版本已经支持SMDK2410开发板。我们可以基于SMDK2410移植,那么先把SMDK2410编译通过。
我们以S3C2410开发板fs2410为例说明。移植的过程参考SMDK2410开发板,SMDK2410在U-Boot-1.1.2中已经支持。

移植U-Boot的基本步骤

(1)在顶层Makefile中为开发板添加新的配置选项,使用已有的配置项目为例。

smdk2410_config   :       unconfig
         @./mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

参考上面2行,添加下面2行。

fs2410_config   :       unconfig
     @./mkconfig $(@:_config=) arm arm920t fs2410 NULL s3c24x0

(2)创建一个新目录存放开发板相关的代码,并且添加文件。

board/fs2410/config.mk
board/fs2410/flash.c
board/fs2410/fs2410.c
board/fs2410/Makefile
board/fs2410/memsetup.S
board/fs2410/u-boot.lds

(3)为开发板添加新的配置文件
可以先复制参考开发板的配置文件,再修改。例如:
$cp include/configs/smdk2410.h include/configs/fs2410.h
如果是为一颗新的CPU移植,还要创建一个新的目录存放CPU相关的代码。
(4)配置开发板
$ make fs2410_config
(5)编译U-Boot
执行make命令,编译成功可以得到U-Boot映像。有些错误是跟配置选项是有关系的,通常打开某些功能选项会带来一些错误,一开始可以尽量跟参考板配置相同。
(6)添加驱动或者功能选项
在能够编译通过的基础上,还要实现U-Boot的以太网接口、Flash擦写等功能。
对于FS2410开发板的以太网驱动和smdk2410完全相同,所以可以直接使用。CS8900驱动程序文件如下。

drivers/cs8900.c
drivers/cs8900.h

对于Flash的选择就麻烦多了,Flash芯片价格或者采购方面的因素都有影响。多数开发板大小、型号不都相同。所以还需要移植Flash的驱动。每种开发板目录下一般都有flash.c这个文件,需要根据具体的Flash类型修改。例如:board/fs2410/flash.c
(7)调试U-Boot源代码,直到U-Boot在开发板上能够正常启动。
调试的过程可能是很艰难的,需要借助工具,并且有些问题可能困扰很长时间。

该段引用https://www.cnblogs.com/anandexuechengzhangzhilu/p/10719869.html

烧写UBoot到Flash

新开发的电路板没有任何程序可以执行,也就不能启动,需要先将U-Boot烧写到Flash中。
如果主板上的EPROM或者Flash能够取下来,就可以通过编程器烧写。例如:计算机BIOS就存储在一块256KB的Flash上,通过插座与主板连接。
但是多数嵌入式单板使用贴片的Flash,不能取下来烧写。这种情况可以通过处理器的调试接口,直接对板上的Flash编程。
处理器调试接口是为处理器芯片设计的标准调试接口,包含BDM、JTAG和EJTAG 3种接口标准。JTAG接口在第4章已经介绍过;BDM(Background Debug Mode)主要应用在PowerPC8xx系列处理器上;EJTAG主要应用在MIPS处理器上。这3种硬件接口标准定义有所不同,但是功能基本相同,下面都统称为JTAG接口。
JTAG接口需要专用的硬件工具来连接。无论从功能、性能角度,还是从价格角度,这些工具都有很大差异。
最简单方式就是通过JTAG电缆,转接到计算机并口连接。这需要在主机端开发烧写程序,还需要有并口设备驱动程序。开发板上电或者复位的时候,烧写程序探测到处理器并且开始通信,然后把Bootloader下载并烧写到Flash中。这种方式速率很慢,可是价格非常便宜。一般来说,平均每秒钟可以烧写100~200个字节。
烧写完成后,复位实验板,串口终端应该显示U-Boot的启动信息。

完结
觉得有用的来个三连击
我也需要得到肯定的。。。。。
让更多的人能够看到学习到

发布了23 篇原创文章 · 获赞 37 · 访问量 4537

猜你喜欢

转载自blog.csdn.net/ywsydwsbn/article/details/105156959