【系统移植】uboot详细分析
uboot使用
uboot控制台,倒计时
命令: 调试,操作一些硬件
nand erase
nand write
tftp zImage
help: uboot可以提供哪些命令
setenv == set == sete == seten
环境变量: 为命令提供参数
serverip : tftp命令提供tftp服务器的地址
ipaddr : tftp命令提供tftp客户端(开发板)的地址
两个环境变量
uboot: 下载内核,并启动内核
bootcmd: 倒计时结束后,uboot应该自动做什么事情
set serverip ...
set ipaddr ...
set ethaddr 00:ee
倒计时结束的时候,uboot会执行bootcmd中的内容:
tftp 20008000 zImage ; bootm 20008000
从tftp服务器(serverip)中将zImage文件(/tftpboot/)下载到开发板(ipaddr)中内存的20008000
set bootcmd tftp 20008000 zImage ; bootm 20008000
bootargs: 负责告诉内核文件系统在哪里(uboot传递给内核, 内核要用)
root...... : 内核启动过程中,调试信息往哪里输出,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
uImage
)
set bootcmd tftp uImage \; bootm
zImage \; go
set bootcmd tftp uImage \; bootm
uboot1.. uImage \; bootm
uboot的连接脚本
所在路径:cpu/arm_cortexa8/u-boot.lds
.text(目标文件) ); );
.data );
.got );
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
连接的基地址:
-Ttext 0x34800000==>board/samsung/smdkc100/config.mk
TEXT_BASE = 0x34800000
1,TEXT_BASE指定uboot的连接的起始位置
2,指定uboot重定位的位置(可以改成0x2ff00000)
uboot配置的详细说明
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第一阶段启动流程
@ set up , r0, c8, c7, @ invalidate TLBs
mcr p15, , r0, c7, c5, @ invalidate icache
, r0, c1, c0,
bic r0, r0, #0x00002000 @ clear bits ( ( ( (Z, r0, c1, c0,
,mem_ctrl_asm_init
,mem_setup.S需要被编译,内存初始化代码应该在前16k (反汇编)
修改cpu/arm_cotexa8/u-boot.lds
/* nand src offset : 0x0*/
mov r0, #0x0
/* ddr dst addr : 0x2ff00000*/
ldr r1,=0x2ff00000
/*size*/
ldr r2, =0x40000
bl copy2ddr
ddr的地址(重定位的目标地址): 和uboot的链接的基地址要一样
board/samsung/smdkc100/config.mk
TEXT_BASE=xxxx
clear_bss:
ldr r0, _bss_start @ find start of bss segment
ldr r1, _bss_end @ stop here
mov r2, #0x00000000 @ clear value
clbss_l:
str r2, [r0] @ clear BSS location
cmp r0, r1 @ are we at the end yet
add r0, r0, #4 @ increment clear index pointer
bne clbss_l @ keep clearing till at end
ldr pc, _start_armboot @ jump to C code
_start_armboot: .word start_armboot
//start_armboot它的值是在编译的时候就已经确定:0x2ff00000+offset==> 0x2ff00980
arm: 基本所有的指令都是位置无关(指令在哪里执行都可以)
有些代码是位置有关: ldr pc, _start_armboot (pc跳转的目标地址_start_armboot(0x2ff00980),和特定的位置相关)
ldr本身这条指令是位置无关,整个ldr pc, _start_armboot==>成为一个位置相关的指令
链接地址: 链接器为所有的指令做的排序, 肯定有有个基地址: 基地址+该指令的偏移量
运行地址: 指令实际加载的地址,运行时,指令存放地址
物理地址: 和硬件相关,数据手册中的地址都是物理地址, 硬件工程师为设备设定的值
虚拟地址: 一般和mmu相关
思路:
1,支持一种启动模式nand启动
a, 时钟和内存的初始化
1,mem_setup.S 被编译
b, 完成自拷贝的实现
nand_ops.c(读操作)
nand(0x0) --> ddr(TEXT_BASE)
board/samsung/smdkc100/config.mk
c,第一阶段的代码必须全部在前16k
u-boot.lds
d, 熟悉一下第一阶段的启动流程代码
uboot第二阶段代码
lib_arm/Board.c
void start_armboot (void)
为什么总是去看smkdc100.h
|
#include <config.h>
|
#define CONFIG_BOARDDIR board/samsung/smdkc100
#include <config_defaults.h>
#include <configs/smdkc100.h>
#include <asm/config.h>
先看主线流程
hang ();
}
}
);
}
if ((s = getenv ("bootfile")) != NULL) {
copy_filename (BootFile, s, sizeof (BootFile));
}
// 网卡的初始化
eth_initialize(gd->bd);
//死循环
for (;;) {
main_loop ();
}
模块的方式
hang ();
}
}
arch_cpu_init,
board_init, // smdkc100开发板的整体的初始化
timer_init, // 定时器的初始化, timer4==>倒计时的间隔时间,产生一个10ms的间隔
env_init, // 环境变量的初步初始化 /* initialize environment */
init_baudrate, // 波特率的设置 /* initialze baudrate settings */
serial_init, // 串口的初始化 /* serial communications setup */
// 分水岭, 才能够使用printf去打印调试信息
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
print_cpuinfo, /* display cpu info (and speed) */
checkboard, /* display board info */
dram_init, /* configure available RAM banks */
display_dram_config
环境变量处理:
env_relocate ();
, env_ptr, ], offset, ...
#...
#
#define CONFIG_BOOTCOMMAND "tftp 20800000 zImage35 \; go 20800000"
#define CONFIG_BOOTARGS "root=/de/nfs nfsroot=192.168.7.2:/opt/filesystem ip=192.168.7.6 console=ttySAC0,115200 init=/linuxrc"
插曲:函数指针
,初始化
,调用
fun(, );
,作用
a,产生api
b,用于抽象分层
,);
;
a.func ;
b.func = sub;
nandflash的初始化;
;
uboot命令处理的逻辑过程
,
.repeatable ,
.cmd ;
}
U_BOOT_CMD(
mycmd, , , do_mycmd,
uboot命令解析过程
mainloop:(一般不需要去修改)
zImage
argc
argv]] ] ]);
|
find_cmd_tbl(cmd, &__u_boot_cmd_start, len);
|// cmdtp为指针,执行.u_boot_cmd段的起始位置
for (cmdtp = table; cmdtp != table + table_len;cmdtp++)
if (strncmp (cmd, cmdtp->name, len)
return cmdtp;
(cmdtp->cmd) (cmdtp, flag, argc, argv) // 执行命令的处理函数
倒计时被打断的时候:
for (;;) {
len = readline (CONFIG_SYS_PROMPT);
rc = run_command (lastcommand, flag);
掌握:
1, 在uboot添加命令
2, 已知的命令对应的处理函数
nand 命令==> cmd_nand.c
do_nand
dm9000网卡:
,dm9000,执行dm9000的init方法
eth_init(gd]; ;
}
uboot是如何启动内核
1, 在0x20000100去存放内存的信息和bootargs的内容
2, 将r1=1826,告诉内核
gd, machid, bd->bi_boot_params);
全局的数据:gd
#];
gd;
init_baudrate
;
serial_init , , ;
}
gd;
dram_init].start ].size
;
gd].start ].size ;
gd;
gd->flags |= GD_FLG_RELOC;
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
串口的初始化
serial_initialize();
//将所有的外围设备全部做成对象 struct stdio_dev, 如果想要研究uboot中有lcd,研究这块
stdio_init (); /* get the devices list going. */
// 跳转表
jumptable_init ();
// 将stdin, out, err==> serial
console_init_r (); /* fully init console as a device */
/* enable exceptions */
enable_interrupts ();
smdkc100所有平台数据的注册流程
}
arch_initcall(customize_machine);
smdkc100_machine_init
|
platform_add_devices(smdkc100_devices, ARRAY_SIZE(smdkc100_devices));
|
platform_device_register(devs[i]);
init/main.c
start_kernel
|
printk(KERN_NOTICE "%s", linux_banner);
setup_arch(&command_line); // 建立平台相关的数据,会到0x200000100去uboot存放数据
|
mdesc = setup_machine(machine_arch_type); // 获取machine描述
//struct machine_desc *mdesc===>mach-smdkc100.c==>MACHINE_START
mdesc->boot_params; //获取0x20000100
tags = phys_to_virt(mdesc->boot_params);
parse_tags(tags); // 获取bootargs, from就在这里初始化
strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
内核是如何去处理bootargs中的所有参数:
在内核的任何地方);
printk(;
}
__setup("myval=", parse_myval);
uboot上电完整内存使用
@成鹏致远
(blogs:http://lcw.cnblogs.com)
(email:wwwlllll@126.com)
)
【系统移植】uboot详细分析的更多相关文章
- ARM开发板系统移植-----u-boot的编译
本文和另外两篇姊妹篇都是为了说明如何裁剪出适合在mini2440 开发板上运行的Linux系统,以记录自己的学习成果.其中本文先介绍了嵌入式系统的软件组成部分,然后介绍编译出适合在mini2440开发 ...
- 一步步教你用Prometheus搭建实时监控系统系列(二)——详细分析拉取和推送两种不同模式
前言 本系列着重介绍Prometheus以及如何用它和其周边的生态来搭建一套属于自己的实时监控告警平台. 本系列受众对象为初次接触Prometheus的用户,大神勿喷,偏重于操作和实战,但是重要的概念 ...
- javascript--苹果系统底部菜单--详细分析(转)
源码下载:http://pan.baidu.com/s/1hqvJJA8 代码来源: 这个DEMO来自“妙味课堂” 昨天看到了“妙味课堂”的一个苹果菜单的DEMO.根据里面提到的“勾股定理”.我自己分 ...
- 嵌入式Linux系统移植——uboot常用命令
flash的一般分区: 其它数据 环境变量 可执行程序.如bootloader print(可缩写为:pri):打印查看uboot这个软件中集成的环境变量setenv.saveenv:设置.保存环境变 ...
- linux 系统移植uboot
这里使用的版本为:u-boot-2014.04 查看并修改位置如下:u-boot-2014.04/include/configs/at91sam9x5ek.h(1)查看一下Linux内核在NandFl ...
- 【系统移植】kernel分析
内核启动流程 第二阶段 starte_kernel: | rest_init: | kernel_init | do_basic_setup(); // 加载驱动 | do_i ...
- 【课程分享】深入浅出嵌入式linux系统移植开发 (环境搭建、uboot的移植、嵌入式内核的配置与编译)
深入浅出嵌入式linux系统移植开发 (环境搭建.uboot的移植.嵌入式内核的配置与编译) 亲爱的网友,我这里有套课程想和大家分享,假设对这个课程有兴趣的,能够加我的QQ2059055336和我联系 ...
- 海思uboot启动流程详细分析(三)【转】
1. 前言 书接上文(u-boot启动流程分析(二)_平台相关部分),本文介绍u-boot启动流程中和具体版型(board)有关的部分,也即board_init_f/board_init_r所代表的. ...
- U-boot分析与移植(2)----U-boot stage1分析
我们要生成u-boot.bin文件,它首先依赖于很多.o文件和.lds链接脚本文件 我们只要找到对应的.lds链接脚本文件就可以分析u-boot的启动流程. 1.打开u-boot-1.1.6\u-bo ...
随机推荐
- Python爬虫之requests+正则表达式抓取猫眼电影top100以及瓜子二手网二手车信息(四)
requests+正则表达式抓取猫眼电影top100 一.首先我们先分析下网页结构 可以看到第一页的URL和第二页的URL的区别在于offset的值,第一页为0,第二页为10,以此类推. 二.< ...
- Ubuntu pkg_resources.DistributionNotFound: The 'Scrapy==1.0.3' distribution was not found and is required by the application
在Ubuntu16.0.4上安装scrapy,参考:Ubuntu16.04安装Scrapy命令 都安装成功后,import scrapy也都没出错,但是在终端输入:scrapy 命令时出现错误: Fi ...
- 关于H5在移动端架构的优化设计总结
各大互联网公司采取的策略 一.百度移动前端首页 1. 对于首屏的静态文件css/js,在上线前全部编译直出到HTML文件中:整个首页的渲染只需要一次请求: 2.使用缓存:把不变的js/css/html ...
- mac下配置Apache虚拟域名方案,以及遇到的坑
1. 配置Apache虚拟域名 1.执行 sudo vi /etc/apache2/httpd.conf 开始配置httpd.conf 的文件; //配置listen 80端口(默认配置), ...
- gevent实现异步
# coding:utf-8 import gevent import requests from gevent import monkey # 猴子补丁就是在运行时对代码进行修改 # 由于IO操作非 ...
- Python3函数式编程
Python函数式编程 函数式编程可以使代码更加简洁,易于理解.Python提供的常见函数式编程方法如下: map(函数,可迭代式)映射函数 filter(函数,可迭代式)过滤函数 reduce(函数 ...
- [HDU1392]Surround the Trees
思路: 凸包模板题. 注意n=1和n=2的情况. 当n=1时,不需要绳子. 当n=2时,绳子长度为两棵树之间距离. 当n≥e时,Graham求凸包即可.最后将凸包上的所有相邻点距离求和. #inclu ...
- Servlet中的过滤器
在web.xml中配置:(用eclipse工具,可以在创建filter的时选择,web.xml中的配置可以自动生成) <filter> <display-name>LoginF ...
- redis 在 php 中的应用(Server[ 服务器] 篇)
本文为我阅读了 redis参考手册 之后编写,注意 php_redis 和 redis-cli 的区别(主要是返回值类型和参数用法) 目录: Server(服务器) BGREWRITEAOF BGSA ...
- eclipse和jdk的版本问题,比如printf()出错
1.右键项目选中properties 2.Java Builder Path >>>Libraries>>>选中JRE Syste Library[jre7]然后r ...