在引导Linux开机之前需要先清楚Linux启动的必要或者说是先决条件,这里就是提到了u-boot的作用了引用百度云---主要用于嵌入式系统的引导加载,其实在我调试下来总结一下就是初始化硬件这里的硬件包括必要部分和不必要的部分,比如SOC的时钟,外部RAM(DDR内存),栈等。因为linux的内核相对于SOC内部的RAM而言还是比较庞大的,并且运行Linux的SOC的主频普遍是比较高的,受限于flash的访问速度,Linux肯定是不能像单片机的程序一样放在片上flash运行的,毕竟在48M以上的时候常见的单片机都是需要加wait以匹配CPU和flash的速度差距了。所以u-boot一定的需要先初始化好RAM(DDR)然后将linux拷贝到RAM内来运行。所以Linux启动的硬件环境和一些必须的软件环境由u-boot负责配置好,最后也是u-boot将Linux内核放到DDR中最后把运行权交由Linux的代码的。引导linux运行除了u-boot准备好的部分工作后剩下还有几个分两种情况。必须和设备树配合的较新的内核版本和不需要设备树的老内核。这两种情况都需要根文件系统,设备树则不一定。所以这里简单记录一下根文件系统的构建。
根文件件系统的构建
根文件系统是Linux启动必须的,主要就是使用busybox进行配置和编译后得到,除此之外如果不使用静态连接的方式还需要交叉编译工具的库。首先下载busybox的源码,然后解压后开始配置。
1、添加编译器
这里的套路和u-boot和linux的编译之前相同就是修改顶层的makefile脚本的CORSS_COMOLIE为你自己的编译工具,ARCH为你的目标架构。
2、增加中文支持这里参考开源电子网的修改
修改目录libbb/printable_string.c文件
const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str) { char *dst; const char *s; s = str; while (1) { ...... if (c < ‘ ‘) break; /* 注释掉下面这个两行代码 */ /* if (c >= 0x7f) break; */ s++; }
继续修改/libbb/unicode.c
static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t*stats, const char *src, unsigned width, int flags)
{ char *dst; unsigned dst_len; unsigned uni_count; unsigned uni_width; if (unicode_status != UNICODE_ON) { char *d; if (flags & UNI_FLAG_PAD) { d = dst = xmalloc(width + 1); ...... /* 修改下面一行代码 */ /* *d++ = (c >= ‘ ‘ && c < 0x7f) ? c : ‘?‘; */ *d++ = (c >= ‘ ‘) ? c : ‘?‘; src++; } *d = ‘\0‘; } else { d = dst = xstrndup(src, width); while (*d) { unsigned char c = *d; /* 修改下面一行代码 */ /* if (c < ‘ ‘ || c >= 0x7f) */ if(c < ‘ ‘) *d = ‘?‘; d++; } } ...... return dst; }
3、配置busybox 这里同u-boot的配置一样,busybox共有三个预先的配置文件defconfig、allyesconfig、allnoconfig见文知意不啰嗦了,这里我选择make defconfig 。当然他也支持图形界面配置。
之后再在图形界面上选中uniconde支持和非静态连接编译就可以编译了,这里选择非静态我也只是参考未究其原理。
4、执行make install CONFIG_PREFIX=/xxx 这里如果xxx目录不存在需要提前建好。最后就是得到根文件系统了。
引导LInux开机
这里就是简单的测试引导开机所以就直接找打Linux内支持本芯片的配置文件配置之后直接编译得到uimage。这里我是使用SD卡作为启动介质。在这里提醒自己以后linux的相关东西一定不要在windows上操作了,不然坑把自己填进去可能都平不了。在ubantu上SD卡分成两个分区一共8G的卡我第一个分区分1G的大小用来放linux内核镜像,第二个分区给力6个G,需要注意的时SD卡的前面还按默认预留了2048个block,这里主要是预留给u-boot的。之后按网上的方法把u-boot写到SD卡的无分区扇区,然后拷贝Linux镜像uiamge到分区1,在拷贝根文件系统到分区二。接下来就是启动测试了(开始填坑。。。)
第一个问题
u-boot的两个环境变量没有关心这个是必须的,bootargs和bootcmd,第一个环境变量是u-boot引导Linux后传给他的参数,相当与main(argc,argv),所以很重要,具体怎么设置根据启动方式的配置不同需要更具体的设置,其次是bootcmd这个其实只是u-boot倒计时结束后默认执行的命令,但是如果你是手动引导的话就可以不设置,这里也是具体情况具体配置。
第二个问题
前面我移植u-boot时选择的是新增加一个SOC的方式,所以arch_number也是我自己自定义的,但是内核支持我这个芯片所以他有自己的的arch_number,这个是决定Linux启动之后执行什么操作的,也是编译好的内核特定支持的。所以前面自己随便指定的soc编号这里启动时内核就不认了。
第三个问题
linux 3.0.8的内核引导不了,为什么时这个版本捏,主要是友善之臂的版本就是这个所以一开始就说拿这个试试,想不到这个还是个坑,具体就是打印Starting kenel。。。。后就没有动静了,问题不清楚。
第四个问题
根文件系统的文件系统我是ext4内核编译的时候默认没选择支持,所以挂载根文件系统时失败了好久,中间还尝试NFS 的方式,却因为网络的问题最后放弃又回来搞SD卡,最后还是从NFS得到了启发,因为NFS时候需要选择支持网络文件系统,而且需要配置网络的和具体的网卡设备,最后使能了ext4文件系统支持后才成功挂载根文件系统。
第五个问题
不要用windows干分区的活,最后挂载一定会发现根文件系统分区损坏无法挂载。
这次就是简单记录下自己这个过程遇到的坑,没由详细的过程。后续有心思了在整理下详细的过程吧,主要是Linux现在可以启动了先暂时记录下。
Linux驱动开发---》路漫漫其修远兮,苦其心志,劳其体肤啊!