近来想尝试把新的Linux内核移植到tq2440的开发板上,瞧瞧能够不能顺利的跑上去。我的基础版本是买板子的时侯提供的2.6.30版本,编译器版本是4.3.3.。
下载源码和编译器
下载linux源码,源码的官方网站是TheLinuxKernelArchives,官方有多个git分支,可以依照自己的需求选择,我选择stable版本:
kernel/git/stable/linux.git-Linuxkernelstabletree,推荐这个版本,分支比较全。
也可以下载LinusTorvalds的分支:
kernel/git/torvalds/linux.git-Linuxkernelsourcetree。这个分支不多,tag多。
用git可以十分便捷的在各个版本之间切换,特别适宜实验。
下载编译器
随着内核版本的升级,编译器的版本也须要升级,写稿时最新的编译器版本是13.3。并且编译器版本也不是越高越好,太新的编译器和老的内核也会出现兼容性问题。
新的内核有个脚本./scripts/cc-version.sh可以检测编译器是否OK,
它调用了另一个脚本./scripts/min-tool-version.sh显示内核支持的最低编译器版本。
旧内核我没找到对应的工具,不过编译器还会提示的,例如版本过低都会出现找不到文件的错误
里面的错误就是我用13.3的编译器编译linux3.4的内核出现的,换成4.3.3的编译器就OK了。
配置环境变量
编译前须要配置好环境变量,将编译器的bin路径添加到PATH中,可以更改~/.bashrc或则/etc/profile,这些方法是常年生效的,开机即用,也可以直接在命令行窗口exportPATH=[编译器bin路径]:$PATH的形式配置,这些方法是针对此命令行窗口临时的,关闭后就失效了。关于环境变量更详尽的内容请自行搜索学习,我这儿就不再罗嗦了。
编译内核还须要下载一些必要的工具,
sudoaptinstallbcbinutilsbisondwarvesflexgccgitgnupg2gziplibelf-devlibncurses5-devlibssl-devmakeopensslpaholeperl-basersynctarxz-utils
这儿只是一个反例,随着内核的发展,似乎有些工具不须要了,毕竟版本不对,或则须要其他一些新的工具,不要担忧,编译的过程中若果缺少工具编译器会报错的,通过错误信息我们就晓得安装哪些了。
更改代码
前期工作做好了以后就可以步入linux源码目录了,交叉编译须要明晰给出两个环境变量ARCH和CROSS_COMPILE,否则会默认编译x86版本的内核。可以在make命令参数上给出:
也可以直接写入Makefile文件,我选择这些方法,比较便捷;
第二幅图的编译器是最新的,随着版本的更新,编译器也跟随升级arm linux内核移植,宏的具体值按照你自己版本的情况填入即可。
下边的更改是针对我的板子的,你的可能不须要更改,须要你按照你的板子自行判定,不能盲目仿效。
更改系统时钟,我的板子用的12M晶振,内核默认是16.9344M的,这儿不改会造成log输出乱码。更改的文件是arch/arm/mach-s3c/mach-smdk2440.c,老的版本是arch/arm/mach-s3c24xx/mach-smdk2440.c或arch/arm/mach-s3c2440/mach-smdk2440.c,须要灵活应对。
不同的版本这个函数也是有区别的,捉住关键2440和clocks就不会出错。
还有个地方须要更改,我的uboot将s3c2440的机器码改成了168linux操作系统界面,所以Linux那边也得改,这儿十分关键,内核之所以晓得跑那个芯片的那个平台就是通过这个机器码决定的。
想要晓得uboot传入的是那个机器码,可以在uboot的命令行输入bd或bdinfo查看
内核更改文件arch/arm/tools/mach-types,找到s3c2440,将362改成168
假如机器码不对,内核会提示下边的信息
列举的machine跟你的配置有关。
以上的更改对每位版本都要做,我之后就不非常强调了。
配置内核
接出来打算.config文件,这是内核编译依赖的配置文件,整个内核相关的宏都在这个文件中,我们menuconfig的操作就是在改变这个文件,假如你不确定你想要的配置是否生效或则关掉,就可以在.config中搜索查看。(注意config之前有个英语句号,默认是隐藏文件)
Linux内核提供了一些预定义文件,我们可以拿一个作为基础开始,执行下边的命令,复制预定义文件为.config:
此时早已可以编译了,我的目标是做最少的更改,内核能引导上去就行,也就是内核能运行上去,但是才能输出log。所以我先用默认配置编译,下载到板子看疗效,之后再依据情况做进一步的操作。下边我会根据版本述说不同版本遇见的问题和解决办法,以供你们参考。
(实际做移植肯定要尽可能裁切掉不须要的东西,否则编译费时间,编译下来的文件还大)
在开始之前arm linux内核移植,我们先通过命令makemenuconfig见一见linux内核的配置界面
最前面一行可以看见使用的配置文件、平台和内核版本,这儿就可以确认你的交叉编译环境是否配置正确。这个界面不同的版本会有所不同,须要你们灵活应对。
2.6.30-2.6.34
这几个版本用4.3.3编译须要额外更改kernel/timeconst.pl
编译通过后下载到板子可以直接引导运行,没哪些非常须要注意的,比较顺利。
2.6.35
到这个版本就出现问题了,跟前面通用的方式,此次运行卡在了bootingthekernel这儿
以后也没有任何输出,之后在网上找到了一个blog的这一段话
尝试后发觉真的可以了。可见,linux旧内核可以的行为在新内核不一定可以。其实这儿进一步的诱因我没有考量,由于上面linux的升级版本又恢复到不须要除去其他板子也可以运行的状态了。
(对于前面的文章是转载的,我没有找到原出处,我就不列举转载源了,感兴趣自己搜索吧)
3.4.y
这个版本更绝,上来就是未定义的指令,直接重启。
根据之前的思路去除其他不用的板子,之后成这样了
遇见这些情况不要慌,内核提供了调试信息,我们打开调试信息显然能获得线索,之前的版本其实也可以,不过我到这个版本才发觉这个配置,你若果是之前的版本可以试试。
编译下载
这儿可以看见码率是0linux系统,很显著有问题。我在uboot的bootargs传入了115200,然而这儿没有收到。不卖关子了,这个版本内核加入了设备树,uboot传参的方法早已发生了变化,而我的uboot是旧的,所以须要配置内核用旧的方法传参。
然后再度编译下载能够正常输出了,说明uboot的传参成功了
其实内核在这儿也提示这些方法过时了,赶忙升级uboot吧。
3.19
这个版本用默认预定义配置不会出现未定义指令,直接能输出乱码,那看来就是传参问题了。
开启旧方法传参,这个版本把这个选项放在了bootoptions下,
编译下载,此次启动就OK了。
到这儿可以发觉内核的兼容性又变好了,不须要过多的剪裁也可以正常运行,可见内核升级就是一个不断出现问题又改进问题的过程。
4.19.y
这个版本make时开始提示编译器太老了,须要升级。
换成最新的编译器
继续编译就OK了。
默认下载进去启动不了
然而之前早已确认传参有问题,先改成旧的方法,编译下载后可以了。
5.19.y
此次在s3c2410_defconfig的基础上直接开启用旧的方法传参,编译下载。
直接可以启动。注意看,此时内核的大小是4M,而最开始2.6.35的才2M,直接翻番了。从log也可以看下来内核结构发生了巨大的变化。
6.2.y
更改和配置同5.19,编译引导也正常。
Linux内核6.3之后就不支持s3c2440这颗芯片了。其实旧版本的内核也够用了,那么老的芯片好多都用旧内核,没有特殊需求没有升级新内核的必要,这显然也是新版本不再支持的诱因吧。