1-系统移植_u-boot移植

c语言、汇编、脚本、Makefile、Kconfig、设备树


装windows:BIOS界面、运行系统内核、安装驱动、装软件
移植就是给一个开发板装一个系统:学完这门课之后我们都是嵌入式的网管
嵌入式平台:引导程序(u-boot)、uImage、写驱动(改驱动)、第三方源码(相当于一个应用软件)

* 什么是移植?软件系统移植、硬件系统移植

一个平台的代码应用到另一个不同体系的平台上,需要做的工作就是移植

在移植过程中:
  • 虚拟内存空间分配:用户空间、内核空间(文件系统,驱动,内存管理,网络协议栈,设备管理,中断,进程管理)
  • 上层的open和内核的open有什么关系?
struct file_operations
{
    int (*open)(struct *file,);
}
交叉编译器
  • x86 arm 交叉编译器:在x86平台编写代码,然后通过交叉编译器编译后生成了适用于arm平台的二进制代码
  • arm-none-linux-gnueabi-gcc
编译过程:
  • 预处理 gcc -E 1.c -o 1.i 或 cpp(预处理器) 1.c -o 1.i
  • 编译 gcc -S 1.i -o 1.s 或 cc1(编译器) 1.i -o 1.s
  • 汇编 gcc -c 1.s -o 1.o 或 as(汇编器) 1.s -o 1.o
  • 链接 gcc 1.o 或 ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o 1 1.o /usr/lib/i386-linux-gnu/crt1.o
  • /usr/lib/i386-linux-gnu/crti.o /usr/lib/gcc/i686-linux-gnu/4.6/crtbegin.o -lc
  • /usr/lib/gcc/i686-linux-gnu/4.6/crtend.o /usr/lib/i386-linux-gnu/crtn.o
  • 链接器调用.o文件,.o文件中包含分段信息。
  • .data .text .bss .rodata
nm 二进制文件 显示二进制文件中符号表的信息
  • 显示的内容包含3列:

  • 内存地址 属于哪个分段 符号名称

  • 大写字母代表全局

  • 小写字母代表局部

  • T D B R W

void fun() __atteibute__((weak));
//将fun函数变成弱标号,如果没有调用的话不会报错,编译器会直接忽略掉fun相关链接操作

strip 二进制文件 清除二进制文件中的符号 清除符号表的目的是为了节省资源
什么是符号?函数名或者变量名
符号什么作用? 符号是给链接器使用的或者说链接器通过符号的名字来找到了代码分段的位置
链接器在生成可执行文件时要使用符号,如果符号被清除,那么链接器失效。所以strip不要对中间文件进行瘦身。

在操作开发板前要先对u-boot进行配置。

u-boot有两种模式:交互模式,自启动模式.
  • 在配置时要进入到交互模式中,一旦配置好之后使用自启动模式.
  • 在交互模式中的命令操作:注意这里的命令不是shell命令。
设置环境变量内容:
  • setenv 环境变量名 内容
  • 例如:setenv serverip 172.21.1.250
删除环境变量:
  • setenv 环境变量名
setenv bootargs root=/dev/nfs nfsroot=172.21.1.250:/rootfs rw console=ttySAC2,115200 init=/linuxrc  ip=开发板的ip地址
//使用nfs服务,通过nfs服务挂载/rootfs,创建了init进程

setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;bootm 41000000 - 42000000
//tftp 41000000 uImage 在u-boot中通过tftp命令从Ubuntu的/tftpboot目录下下载uImage文件到开发板的偏外内存41000000地址处

//三星手册给的偏外内存最大地址范围40000000 - A0000000 1.5G 我们实际用的是40000000 - 8000000 1G

//bootm 内核镜像地址 文件系统镜像地址 设备树二进制文件地址   这三个地址顺序不能改变.
//本质:1、类似于go命令有跳转到指定地址的作用
      2、可以给内核传递参数
//2.4 2.6 3.0不支持设备树  ————————   3.1x可以选择是否支持设备树

u-boot移植:

配置过程:
  • 1、自己去百度
  • 2、每个源码顶层目录下都会有一个README文件,查看README文件知道配置方法为:make 板子名称_config
    • 我们华清的板子叫做FS4412,这个板子包含了——SOC,外设.
    • 其中SOC还有分类,exynos就是SOC中的某一类,我们FS4412使用的SOC是exynos系列的芯片,这个芯片系列三星公司规定必须以origen为模板。
    • 所以配置时可以执行 make origen_config
  • 为什么要配置?
    • 因为使用了make命令所以会用到Makefile文件。
    • 在使用一个大型Makefile时,一定要先确定入口,千万别从第一行开始读。
    • 通过make origen_config 可以知道当前的Makefile入口是origen_config(也就是说我们要去寻找目标或者伪目标叫做origen_config)
Makefile的基本机制:
  • Makefile的基本机制:显示规则、隐式规则、变量、条件语句、函数
  • 显示规则语法:
  • 目标文件:依赖文件
    • 生成目标文件的命令
    • 779 %_config:: unconfig
    • 780 @$(MKCONFIG) -A $(@:_config=)
查找变量的方法:
  • 1、/变量名
  • 2、命令模式下 按#
  • 3、通过ctags -R生成tags文件,然后ctrl ]
  • 4、make -p Makefile > 随便一个文件名
  • $(@:_config=) 以$@为基础添加一个规则,而这个规则的作用就是将_config替换为空,所以最终%_config会变成origen
  • @$(MKCONFIG) -A $(@:_config=) ==> @顶层目录/mkconfig -A origen
* 文件系统移植:根文件系统的制作以及文件系统镜像的制作
line=`egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg`

line=origen               arm     armv7       origen      samsung    exynos
        $1                                                                $6
//-i忽略大小写
//[[:space:]]空格或者TAB

set $line 根据变量的内容重置$#的值,当前$#=6

57 CONFIG_NAME="${1%_config}" ==> CONFIG_NAME=origen

59 [ "${BOARD_NAME}" ] || BOARD_NAME="${1%_config}"  ==> BOARD_NAME=origen

61 arch="$2" ==> arm
62 cpu=`echo $3 | awk 'BEGIN {FS = ":"} ; {print $1}'`  ==> armv7
63 spl_cpu=`echo $3 | awk 'BEGIN {FS = ":"} ; {print $2}'`  spl_cpu=
64 if [ "$4" = "-" ] ; then
65     board=${BOARD_NAME}
66 else
67     board="$4" ==> board = origen
68 fi
69 [ $# -gt 4 ] && [ "$5" != "-" ] && vendor="$5" ==> samsung
70 [ $# -gt 5 ] && [ "$6" != "-" ] && soc="$6" ==> exynos

97     echo "Configuring for ${BOARD_NAME} board..."

113     cd ./include
114     rm -f asm
115     ln -s ../arch/${arch}/include/asm asm

123     ln -s ${LNPREFIX}arch-${soc} asm/arch  <==>     ln -s arch-exynos asm/arch
//当我们创建软链接时有一种用法是:如果当前目录下不存在源文件,会到目标路径下去寻找是否有源文件

128     ln -s ${LNPREFIX}proc-armv asm/proc
//到此为止我们发现产生了3个软连接文件。无论换成什么平台什么架构我们只需要关心这些软链接文件就可以,至于软链接文件存放的路径是随平台的改变而改变的。

134 ( echo "ARCH   = ${arch}"
135     if [ ! -z "$spl_cpu" ] ; then
136     echo 'ifeq ($(CONFIG_SPL_BUILD),y)'
137     echo "CPU    = ${spl_cpu}"
138     echo "else"
139     echo "CPU    = ${cpu}"
140     echo "endif"
141     else
142     echo "CPU    = ${cpu}"
143     fi
144     echo "BOARD  = ${board}"
145
146     [ "${vendor}" ] && echo "VENDOR = ${vendor}"
147     [ "${soc}"    ] && echo "SOC    = ${soc}"
148     exit 0 ) > config.mk
在config.mk中存放5个变量的赋值:
ARCH = arm
CPU = armv7
BOARD = origen
VENDOR = samsung
SOC = exynos
config.mk文件会被顶层目录的Makefile引用,然后将里面的变量变成全局
154     BOARDDIR=${vendor}/${board} ==> samsung/origen
164     > config.h 创建一个空的config.h头文件

echo "#define CONFIG_SYS_ARCH  \"${arch}\""  >> config.h
174 echo "#define CONFIG_SYS_CPU   \"${cpu}\""   >> config.h
175 echo "#define CONFIG_SYS_BOARD \"${board}\"" >> config.h
176
177 [ "${vendor}" ] && echo "#define CONFIG_SYS_VENDOR \"${vendor}\"" >> config.h
178
179 [ "${soc}"    ] && echo "#define CONFIG_SYS_SOC    \"${soc}\""    >> config.h
180
181 cat << EOF >> config.h
182 #define CONFIG_BOARDDIR board/$BOARDDIR
183 #include <config_cmd_defaults.h>
184 #include <config_defaults.h>
185 #include <configs/${CONFIG_NAME}.h>
186 #include <asm/config.h>
187 #include <config_fallbacks.h>
188 #include <config_uncmd_spl.h>
189 EOF
将一些宏定义和系统头文件存放到include/config.h头文件中
配置u-boot的功能:产生了3个软链接,include/config.mk include/config.h
常用的Makefile命名:GNUmakefile makefile Makefile
.mk .Linux .AIX

编译过程:

  • make all
428 all:        $(ALL-y) $(SUBDIR_EXAMPLES)
//ALL-y = u-boot.bin 所以后续要去以u-boot.bin为目标

411 ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map
443 $(obj)u-boot.bin:   $(obj)u-boot
444         $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
445         $(BOARD_SIZE_CHECK)

//要生成u-boot.bin必须事先生成u-boot,所以要搜索u-boot目标
570 $(obj)u-boot:   depend \
571         $(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
572         $(GEN_UBOOT)

248 OBJS := $(addprefix $(obj),$(OBJS) $(RESET_OBJS-))

236 OBJS  = $(CPUDIR)/start.o

B=
A=$(B)
//ifdef A 判断的是变量A是否有内容,如果有内容成立,没有内容不成立

LDSCRIPT=arch/arm/cpu/u-boot.lds

561 GEN_UBOOT = \
562         UNDEF_LST=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
563         sed  -n -e 's/      .*(_u_boot_list_.*)/-u\1       /p'|sort|uniq`;\

564         cd $(LNDIR) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
565             $$UNDEF_LST $(__OBJS) \
566             --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
567             -Map u-boot.map -o u-boot

// sed基本功能用来字符串替换的
// \1的作用是用来标记的,标记的是前面的括号内部的内容
// -u\1作用就是用-u替换标记前面的内容
/ /所以替换完成后是 -u_u_boot_list_.*


// -u\1的用法:sed -n  -e 's/.*(_u_boot)_list_.*/-u\1' 替换后变成-u_u_boot_list_.*
// \1-u用法:sed -n -e 's/.*_u_boot-u'
// $(@F) <==> $(notdir $@)
验证:
  • abc=/home/linux/Makefilex
  • info=$(notdir $(abc))
start:
    echo $(info)
最终结果为Makefilex,无论有没有这个文件,我们关心的是能否去掉文件前的路径

$(LDFLAGS_$(@F)) 转化完成后为 LDFLAGS_u-boot
LDFLAGS_u-boot = -pie -T $(obj)u-boot.lds $(LDFLAGS_FINAL) -Ttext $(CONFIG_SYS_TEXT_BASE)

-pie -T u-boot.lds为了告诉链接器,根据u-boot.lds的内容哪些分段是需要链接的哪些分段是需要抛弃的。

312 LDFLAGS_FINAL = -Bstatic 所有内容进行静态链接
-Ttext 0x43e00000  一旦进行链接后,u-boot.lds中的00000000地址会被替换成0x43e00000
--start-group $(__LIBS) --end-group 指定一组库的二进制文件
上面一堆操作我们重点关心链接器链接时用到哪些内容?
  • 1、分段,符号,分段和符号是一堆.o文件提供的
  • 2、用到哪些分段u-boot.lds指定的
    分段相对于符号来讲是一个整体,分段是包含符号的。
    u-boot.map会告诉链接器,在链接时使用到的符号对应的地址是什么
链接最终的结果生成的u-boot可执行文件,再通过objcopy将u-boot转化为u-boot.bin
理论来讲这个u-boot.bin可以烧写到开发板上了。但是三星板子不允许。
* 我们最终用的u-boot-fs4412.bin包含u-boot.bin、bl1、bl2、填充代码、trustzone
开发板——SOC、外设
  • SOC内部——CPU(cortex-a9)、外设控制器、IROM、IRAM
  • 我们的SOC三星公司给取名为exynos4412
  • 在SOC内部的IROM中固化了一部分代码叫做bl0,bl0的作用是将bl1加载到IRAM中运行,bl1是三星提供的二进制文件,作用是初始化硬件
    同时将bl2加载到IRAM中运行,bl2是u-boot.bin的前14k,这14K的主要作用是计算出片外内存可用的高位地址,然后将u-boot.bin整体
    搬移到计算出的高位地址中去运行。
linux内核:主版本号.次版本号.修订版本号
通常情况下次版本号为偶数的是稳定版本。www.kernel.org
2.4devfs 2.6sysfs 3.0 3.1x sysfs
选择内核版本时,不要选择比较老的版本,最好不要选择最新版本。
linux重要的目录:
  • arch存放的是和体系架构相关的代码
  • Documentation存放说明文档
  • drivers存放驱动代码
  • init/main.c 存放了内核启动代码的c语言程序
  • include 存放的是头文件

linux内核:

配置
  • 方法:
    • 1、make exynos(芯片名称)_defconfig
    • 2、cp arch/arm/configs/exynos_defconfig .config
  • 目的: 通过配置方法让内核的功能只支持当前平台。
如何对内核进行软件裁剪:make menuconfig
  • 注意:
    • 1、在顶层目录
    • 2、屏幕不能太小
    • 3、第一次在执行make menuconfig时会不成功,可能是因为没安装一个软件包
进入menuconfig后选项的种类主要使用3种:
  • [] 有两种状态——选中和未选中
  • <> 有三种状态——选中和未选中、模块
  • () 可以存放十进制整数,十六进制整数、字符串
  • 内核选项是如何添加到menuconfig中的?必须要先学习Kconfig语法
Kconfig中的属性:
  • source "路径/Kconfig" 引用某个路径下的Kconfig文件
  • config 字符串
  • 例如config ABC 我们会在顶层目录下的.config文件中寻找到CONFIG_ABC这个变量。同时CONFIG_ABC还有可能出现在Makefile文件中
  • bool "字符串" 这个字符串就是menuconfig中的一个选项名称,bool代表了选项[]
  • tristate "字符串" 代表了<>
  • string "字符串" 代表了(),这个小括号中只能存放字符串
  • int "字符串" 代表了(),这里存放十进制整数
  • hex "字符串" 代表了(),智力存放十六进制整数
  • menu,endmenu 这两个配对使用,当一个选项有子选项时使用
  • default y | n | m | 字符串 | 整数
  • depends on 字符串 当前选项的出现要依赖另一个选项是否选中,而另一个选项是谁?通过字符串来寻找的
假设需要操作一个设备。而且内核中已经有驱动来支持这个设备,但这个驱动相关选项没有选中,如何找到这个选项?
  • 1、确定用到哪个具体的驱动程序。假设这个驱动程序叫做test.c
  • 2、一旦找到驱动程序所在路径,进入这个路径下的Makefile中,寻找obj-$(CONFIG_ABC) += test.o
  • 3、还在当前目录下进入Kconfig文件,寻找ABC,找到ABC之后可以知道这个驱动用哪个选项了

编译

启动


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容