嵌入式Linux编译内核步骤 / 重点解决机器码问题 / 三星2451

2019-07-13 07:54发布

嵌入式系统更新内核

1. 前言

手里有一块Friendly ARM的MINI2451的板子,这周试着编译内核,然后更新一下这个板子的Linux内核,想要更新Linux Kernel 4.1版本,但是种种原因实在是没有更新成功;于是使用Friendly ARM板子提供的3.6版本的内核,但是他们的内核全都配置好了,你只需要按照常规的方法进行编译就好了,貌似不能更深入的理解内核, 后来我从kernel.org官网上下载原版内核,然后一点点的把2451这个板子需要文件移植过去,可谓是问题百出啊,也学习到了很多东西。

2. 准备材料

  • FriendlyARM 的mini2451板子一块
  • 使用的bootloader是FriendARM提供的闭源Superboot2451.bin
  • Linux3.6内核源代码(在官网下的,纯净的)
  • mini2451提供的.config文件

3. 烧写内核的几个重点

3.1 拿到全新内核的几个步骤

我们拿到全新内核的时候,一定要注意几个步骤,好像并没有几个书上由我写的这么详细的,基本上都是给一个大体的思路,但是到了真刀真枪上场的时候,真的是问题百出。以下讲围绕这几个方面进行讨论。 a) 修改顶层Makefile b) Machine ID的处理( 在arch/arm/ 的mach中增加C文件 -> 修改Kconfig -> 修改Makefile文件 ) c) 在arch/arm/tools/mach-types 文件中增加Machine ID

3.1.1 修改顶层的Makefile

Makefile一共要修改2个地方即可:
  • 修改arch架构: ARCH ?= arm 注意,arm这几个后面不要打空格啊,要不然make的时候不识别。
    • 修改cross_compile 路径:CROSS_COMPILE?= /home/user/toolchian/arm-linux-
    注意1,CROSS_COMPILE的表述,我这里给的是全路径,而不是像书籍和网络博客上给的 arm-linux- ,这里为什么呢?因为你的电脑里面可能装了不是一个交叉编译环境的工具链,所以这里强烈推荐使用交叉编译环境的绝对路径,绝对不会出错,可以放心大胆的使用。 注意2,arm-linux- 后面不要加空格,否则不会识别的,和ARCH那个选项一样,都不要有空格。 否则就会抛出:“ make: ** /home/delvis/work/linux-3.6/arch/arm: 是一个目录。 停止。”的错误。
Makefile只需要改这两个位置就可以了,大可保存。

3.1.2 为了Machine ID准备之修改C文件

路径就是 -> ./arch/arm/ 里面关于mach-"各种型号",你在教学视频或者书上经常看见如下的说明:
找一个和你板子型号相近的c文件然后复制一份出来。
我使用的是Linux3.2内核且,我的板子的型号是S3C2451的,所以很理所应当的找到mach-s3c24xx这个文件夹, ! 但是我发现在Linux4.1和Linux2.4版本的内核中没有mach-s3c24xx这个文件夹,其实没有什么关系,只要找到和你板子芯片型号相近的就可以的。 我这里是复制FriendlyARM提供的mach-mini2451.c这个文件,在这个文件需要注意几个地方,我现在还不是很明白这个文件是做什么的,看里面很多初始化的程序包括GPIO、时钟、定时器、中断等等,应该是对2451板子进行初始化的。暂时我还不会写,靠移植吧。
  • 文件末尾MACHINE_START( USER_DEFINE_STRING, "USER_DEFINE_STRING" ) { .... } 这个就是MACHINE id 的位置
  • 还有其中定义的函数,需要依赖很多头文件,原生内核里面没有,缺什么我就从FriendlyARM里面拷贝到相应的目录。
文件末尾的MACHINE_START传递的参数的USER_DEFINE_STRING就是我们一会儿要写入machine id的宏定义,我这里宏定义的字符串是MACH_MINI2451

3.1.3 修改mach-xxxx中的Kconfig文件

刚才刚刚添加了新的mach-mini2451.c的文件,就要在和这个文件同一个目录下的Kconfig中加入这个的配置项,我给出我的配置项: config MACH_MINI2451 bool "MINI2451BYDELVIS" #select S3C24XX_SMDK select S3C_DEV_FB select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_NAND select S3C_DEV_USB_HOST select S3C2416_SETUP_SDHCI select WIRELESS_EXT select WEXT_SPY select WEXT_PRIV select AVERAGE help Say Y here if you are using an FriendlyARM MINI2451 在Kconfig中增加这个字符串,在顶层进行make menuconfig的时候,这个选项就会出来,我们在make menuconfig的时候,最先应该的就是选择板子的架构
1) System Type --> ARM sytem type( Samsung S3C24XX Socs ) --> Samsung S3C24XX SoCs 选择后返回上一层 2)SASUNG S3C24XX SoCs Support ---> 先选上 SASUNG S3C2416/S3C2450 ---> 下面自动出 MINI2451BYDELVIS 一会儿说这个菜单的显示逻辑如何的 3)Exit 并且 Save 成为.config
这些菜单的逻辑和归属主要是Kconfig决定的,我们的config MACH_MINI2451这个条目要放到正确的位置,不是随便放一个位置就行,我们的每一个子菜单对于.config来说都是一项配置。 Kconfig中config MACH_MINI2451的位置 看图,首先注意两个画红圈的位置,我们讲config MACH_MINI2451这一坨放在了 if CPU_S3C2416 ..... endif这个里面,也就是说我们在make menuconfig中选择了”MINI2451BYDELVIS“这个选项的时候,MACH_MINI2451默认在.config文件CPU为S3C2416,(也可见,我们的mach-mini2451.c文件是复制mach-s3c2416.c文件改装而来了) 在make menuconfig菜单中,也只有选择S3C2416这个CPU型号,我们的这个选项才会出现

3.1.3 修改mach-s3c24xx文件下的Makefile文件

我们平白无故的增加了mach-mini2451.c文件,如果进行全局编译的时候,是不会进行编译的,因为没有makefile进行指导编译,所以我们需要修改这一层的Makefile,当我进行全局编译的时候,就有规则指导编译器进行编译。 # add by Carlos 2017.12.6 obj-$(CONFIG_MACH_MINI2451) += mach-mini2451.o mini2451-lcds.o 在这一层的Makefile文件中随便找一个位置,然后按照这个格式输出文件。

3.1.4 增加机器码

说到机器码,我真的不得不吐槽一下Friendly ARM,在购买Friendly ARM的时候,购买的宣传界面,大篇幅的说他们花了重金开发了Superboot2451.bin企业级的bootloader,重点是闭源,bootloader还是不错的,从SD卡引导,支持串口,驱动支持的挺全的,还有一个他们独创的可视化界面miniTools的USBMODE一键安装系统,一键下载程序。但是好歹闭源的同时,把bootloader的关键参数给出啊!!!!我找了他们的Wiki,找了官网,手册,就是没有知道Superboot2451.bin的Machine ID,好歹把ID值给出来啊。 恩,后来经过实验输出,得到强大的闭源Superboot2451.bin的 机器码 machine id 是: 0x00000695 好了,吐槽到此为止,我还是建议自己开发uboot,这样方便。
只有bootloader和kernel中的机器码一样,内核才能正常启动,否则将会抛出: Error: unrecognized/unsupported machine ID (r1 = 0x33f60264). 我们要么改正uboot中的ID,要么改正kernel中的ID,总之,无论数字是什么,要一样。
好了,Superboot2451.bin的既然是闭源的就没办法进行改正了,那么我们只能改正Kernel中的ID了,那么Kernel中的ID该怎么改正呢? 切换到: arch/arm/tools/文件夹,里面有个mach-types文件,我们在后面追加一个: mini2451 MACH_MINI2451 MINI2451 0x695 细心的朋友已经发现了,在上面的章节中,零零散散的文件用的也是这些字符,也就是mini2451、MACH_MINI2451、MINI2451这个宏定义都是这个ID值。 到此我们的的内核配置完毕了。

3.2 make menuconfig配置

切换到最后一步,进行make menuconfig进行.config的配置,在韦东山老师的视频里面,提到这个.config文件来源于三个部分
  1. 进行make menuconfig配置后的,你需要一条条的进行配置。
  2. 使用默认配置,在上面修改
  3. 使用厂家提供的
我这里,使用厂家提供的mini2451_linux_config文件,在上面进行修改,首先就把运行把这个config文件复制过来,并且名字改为.config覆盖原有的.config文件,然后进行make menucofig,在system type中如同上面讲述的选择正确的板子的型号。如果你没有选择,就会出现这样的异常,在内核编译到最后的时候,出现编译kernel出现no machine record defined 错误。然后一些鬼一样的网站给出馊主意,还被大量的博客转载,简直就是误导人,你经过google或者百度,会有一个这样的解决方案这里给一个!反!面!教!材!:
放狗搜后,按照如下方法可以解决。将arch/arm/kernel/vmlinux.lds的最后两行(如下),给注释起来,但都没说是为了什么
ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support"),
ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") 反面教材来源:uncompressing linux .................................................后没反应解决办法 前半部分
简直是神一样的操作,出错了,注释起来就可以维持了,什么逻辑,简直是对技术的侮辱!!!我尝试过了,的确内核编译通过了,可以把内核传输到ARM上面,到Load Kernel的下一步,就抛出了Error: unrecognized/unsupported machine ID (r1 = 0x33f60264). 的异常,显然是没有机器码没有定义。 注释这个鬼方法根本就不能用好吗?谁出的馊主意!! 正确的解法是: 按照我们上面的章节进行配置,顺理成章的解决Machine ID的问题: -> 1) Machine ID的处理( 在arch/arm/ 的mach中增加C文件 -> 修改Kconfig -> 修改Makefile文件 ) 2) 在arch/arm/tools/mach-types 文件中增加Machine ID 3) 在make menuconfig的menu中选择system type,选择正确的型号,会自动配置到.config

3.3 make

然后开始make就可以了,编译内核,我一般都喜欢用make -j8 多线程编程,速度快,但是很烧CPU。。。 810200-20171207134607222-695612859.png 基本上都是这样的状态。。。看温度。 编译完成之后,按照Friendly ARM提供的文档,把zImage文件拷到SD卡正确的路径,然后从SD卡启动正常烧写就好了。

4 总结

看到这样的输出的时候,真的很激动,终于内核开始正常解压了。磨了人好几天。 810200-20171207134828175-1804933181.png
第15周主要搞内核的搞完了,最近要忙着复习考试,内核事情可能要稍微缓缓了。以后再慢慢研究。

参考文献:

[1] 贵气的博客著.Error: unrecognized/unsupported machine ID (r1 = 0x33f60264)..新浪博客.2011-03-20. [2]韦东山著.《嵌入式Linux完全开发手册-应用开发》书籍. [3]FriendlyARM著.2451开发手册. 用户手册.

版权声明:

1. 本文为MULTIBEANS团队研发跟随文章,未经允许不得转载。 2· 文中涉及的内容若有侵权行为,请与本人联系,本人会及时删除。 3· 尊重成果,本文将用的参考文献全部给出,向无私的工程师,爱好者致敬。