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

嵌入式系统更新内核

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来说都是一项配置。

看图,首先注意两个画红圈的位置,我们讲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。。。

基本上都是这样的状态。。。看温度。

编译完成之后,按照Friendly ARM提供的文档,把zImage文件拷到SD卡正确的路径,然后从SD卡启动正常烧写就好了。

4 总结

看到这样的输出的时候,真的很激动,终于内核开始正常解压了。磨了人好几天。

第15周主要搞内核的搞完了,最近要忙着复习考试,内核事情可能要稍微缓缓了。以后再慢慢研究。

参考文献:

[1] 贵气的博客著.Error: unrecognized/unsupported machine ID (r1 = 0x33f60264)..新浪博客.2011-03-20.

[2]韦东山著.《嵌入式Linux完全开发手册-应用开发》书籍.

[3]FriendlyARM著.2451开发手册. 用户手册.


版权声明:

1. 本文为MULTIBEANS团队研发跟随文章,未经允许不得转载。

2· 文中涉及的内容若有侵权行为,请与本人联系,本人会及时删除。

3· 尊重成果,本文将用的参考文献全部给出,向无私的工程师,爱好者致敬。


时间: 2024-10-13 22:22:50

嵌入式Linux编译内核步骤 / 重点解决机器码问题的相关文章

linux编译内核步骤与错误解决

1.查看内核版本 实验环境 [[email protected] src]# uname -r 2.6.32-358.el6.x86_64 2.安装图形依赖包 yum install -y ncurses ncurses-devel 3.下载内核 [[email protected] src]# wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.16.2.tar.xz 解压 [[email protected] src]# tar

linux编译内核make menuconfig报错Unable to find the ncurses libraries解决办法

在 linux 编译内核时 make menuconfig 报了下面的错误. *** Unable to find the ncurses libraries or the *** required header files. *** 'make menuconfig' requires the ncurses libraries. *** Install ncurses (ncurses-devel) and try again. 这是因为系统中缺少 ncurses-devel,安装一下就可以

Linux 编译内核

编译内核步骤: 1.先查看自己OS使用的内核版本 [email protected]:~$ uname -r4.4.0-51-generic[email protected]:~$ 2.如果安装系统时,自动安装了源码.在 /usr/src 目录下有对应的使用的版本目录(ubuntu安装完一般没有源码需要自己下载).如下: 后缀generic表示通用版. [email protected]:/usr/src$ lslinux-headers-4.4.0-21  linux-headers-4.4.

linux编译内核2.6.32.67

上传linux内核至主机,linux内核文件格式为tar.xz. [[email protected] home]# xz -d linux-2.6.32.67.tar.xz    [[email protected] home]# ls     linux-2.6.32.67.tar xz -d解压后,会删除tar.xz文件,仅留下tar包 [[email protected] home]# tar xvf linux-2.6.32.67.tar -C /usr/src 展开归档文件至/usr

Linux编译内核

查看内核: #uname [OPTION] [OPTION] -r 显示内核版本和release号. 用户空间访问.监控内核的方式: /proc /sys 伪文件系统: /proc/sys 目录中很多文件是可读写的. /sys 某些文件可写 设定内核参数值的方法: 临时生效,重启后失效: #echo VALUE > /proc/sys/FILE #sysctl -w DIR.FILE=VALUE 在/proc/sys目录下可以忽略/proc/sys,剩余路径用DIR.FILE表示. 例如: #e

linux 编译内核 /boot空间不足?

/boot空间一般分配100M的空间,本来是够用的,由于频繁的更新导致旧的不再使用的内核文件也保留在boot空间里,占着位置,所以把这些不用的内核文件下载掉boot空间就能释放出一部分, 具体做法为 1.使用dpkg --get-selections | grep linux查看内核的安装状况,凡是带image都是旧的内核 2.使用uname -a 查看当前的内核版本 3.一般当前版本之前的版本都可以删除,我自己习惯把当前版本的前一个版本保留下来 4.删除的指令是 sudo apt-get re

opencv3.0在嵌入式linux编译过程中报错的处理方法。

http://m.blog.csdn.net/blog/wanghao225225/39252757 上边链接中的文章介绍了opencv3.0的编译方法,但是编译过程中会报错. 错误1:undefined reference to `parallel_pthreads_set_threads_num(int)' ../../lib/libopencv_core.so.3.0.0: undefined reference to `parallel_pthreads_set_threads_num(

【原创】Linux编译内核

前面的添加必备库,编译软件什么请自行百度.. 拷贝至user/src sudo cp linux-4.0.6.tar.xz /usr/src 进入src目录: cd /usr/src 接下来解压 先解压 tar.xz文件 我们先输入 sudo xz –d linux-4.0.6.tar.xz 得到tar后缀文件 在键入sudo tar –xvf  linux-4.0.6.tar 解压完成. 进入目录: cd linux-4.0.6/ 做净化:make mrproper   然后是配置内核.我们保

14、linux编译内核安装介绍

1.linux内核的组成部分: kernel文件: kernel object:内核模块 ramdisk:辅助性文件,用来驱动rootfs所在硬件设备. 2.linux启动流程: POST--->BOOT Sequence(bios中设定的启动顺序)--->从启动设备的mbr中引导grub第一阶段--->kernel(有时会借助于ramdisk文件)--->rootfs(根切换)--->/sbin/init(用户空间的第一个程序,它的配置文件存放于:/etc/inittab;