接上:嵌入式Linux移植和Uboot(一):Bootloader介绍,U-boot介绍(特点,目录结构)
嵌入式Linux移植和Uboot(二)
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的启动信息。
完结
觉得有用的来个三连击哈
我也需要得到肯定的。。。。。
让更多的人能够看到学习到