laihama https://bbs.21ic.com/?277955 [收藏] [复制] [RSS]

日志

备受煎熬的一个月——ARM Linux开发阶段性总结zz

热度 12已有 5792 次阅读2015-1-1 14:15 |系统分类:嵌入式系统| 嵌入式, Linux

这一个月来,我一直投身于Linux内核移植的伟大而光荣的事业,相当的痛苦了……


不过收获也是很大的,昨天晚上,哦应该是今天凌晨1200,终于我的板子上出现了Busybox启动的好消息。Linux内核的移植终于取得了阶段性的成果,虽然后面的路还很长。



从我开始搞Linux,我就一直在网上或者图书馆中寻找“HOWTO”性质的文章,遗憾的是还真少。我也希望我的Blog成为我做的这块板子的“HOWTO”大全,呵呵。但是今天我不写“HOWTO”,对我的工作来个概括性的总结。



如果你是猎人的QQ群里过来看这个Blog,而且想获得与SBC2410X自带的VIVIMIZI Linux的相关信息的,我很抱歉。我认为猎人板子里提供的资料实在是比较垃圾(实际上是友善之臂公司的资料),应该说是一些仅仅针对SBC2410X一种方式应用的“HOWTO”,而且没有提供其他方式应用的任何说明(呵呵,当然我没有责怪猎人的意思,这块板子硬件还是相当不错的,价钱也非常公道)。嵌入式系统的一个很大的特点就是其针对不同应用的可裁减性。举个例子,我希望把ARM用在机器人上,不需要网卡、声卡、USB,只需一个串口,用友善之臂给的资料能做什么?甚至连mkyaffsimage这个制作yaffs文件系统映像工具的源码都没有。其实其他厂家的也一样,可能这些所谓的开发板仅仅是一种技术垄断,尤其是那些动辄好几千块钱的。猎人提供的廉价开发板,我希望能通过我提供的这些开发资料,像开源工程一样,让更多的人受益。



作为一个初学者,最关心的是怎么下手。我先简要说明一下:



首先必须明确你需要的是什么样的系统



ARM Linux应该归类为一种非抢占式的分时多任务操作系统(相关术语可以Google一下),它不适合用来做伺服控制、图像处理等对系统实时性要求较高的控制。uCOS-IIVxWork可以胜任那样的工作。Linux的优点在于开源(Open Source)、网络支持和跨平台支持。其中我最看重的是跨平台支持。因为我的实验室经常使用DSP、单片机控制机器人,而这些程序不具有平台移植性,所以每届硕士做机器人的控制都是从学习DSP或单片机做起,相当浪费时间。我的工作的目的就是利用ARMLinuxuCOS-II,设计ARM-DSP双核系统,搭建一个控制平台。



然后必须建立开发环境。包括硬件环境和软件环境。



硬件环境就是必须购买一个ARM开发板,推荐买猎人的,这个与三星的SMDK2410这块“大众型”开发板完全兼容。搞嵌入式开发和普通的DSP、单片机开发不同,需要最多的是代码的移植,一个与“大众”系统兼容的开发板,可以节约移植别人编写的针对“大众”系统代码的时间。软件环境指的是需要有一台可以运行LinuxPC,以及PC的软件。这些软件包括gcc编译器、gcc交叉编译器(在PC平台编译非PC平台程序的编译器)、Linux NFS支持(用于网络下载内核到开发板)、Linux SMB支持(Linux访问Windows网络共享)、代码察看软件(例如Source Navigator)、Bootloader和内核源代码。其中前四项在安装Linux时候就必须选定,后几项从网络上获得。推荐在Windows下使用虚拟机建立开发系统,可以带来非常大的方便。具体的软硬件系统建立步骤“HOWTO”请看515我写的文章。Linux内核和相应的编译器的下载地址我后面的文章会写出来。另外,有一定硬件电路开发经验的人会有需不需要仿真器的疑问,答案是:根本不需要也不可能用仿真器来调试,一个烧写电缆足以,除非你搞ARM7TDMI-S这种经过裁剪的ARM CPU的程序。主要的调试信息显示渠道是串口,主要的代码下载渠道是串口或者以太网——这由你的Bootloader决定,一个好的Bootloader可以大大减少内核调试的时间。我调试内核使用的是U-Boot的网络下载功能,800kB的内核只需要5~6秒就可以下载结束,我的开发板原配的VIVI的串口需要3分钟多,效率的差距显而易见,更不用说内核之后动辄几个或者几十个MB的文件系统了。



接下来就可以进行开发了,首先是Bootloader



Bootloader是系统上电以后执行的第一段程序,它主要的功能和作用有:初始化硬件,复制Linux内核和Ramdisk文件(如果使用的话)到内存中,把预先设定的内核参数传递给内核并启动,提供硬件诊断、Flash烧写、网络连接等功能。推荐使用U-BootU-Boot的下载地址http://sourceforge.net/projects/u-bootU-Boot的“HOWTO”可以看我52330日写的文章。



还必须说明的是,通常从开源工程网站下来的都是软件的源码,需要自己进行编译。编译由源码目录下的“Makefile”这个文件决定,其中包含有关于编译的配置和操作类型的信息。一般用于多平台的源码,Makefile中都有CROSS_COMPILE这一项,在编译之前必须将它指定到交叉编译器。对于arm-linux-gcc这个交叉编译器,如果设置了指向arm-linux-gcc的缺省路径,可以填写CROSS_COMPILE=arm-linux-,注意,后面的“-”不可以少。通常由于开源代码的编译器兼容性太差,你需要在你的电脑里安装多个版本的交叉编译器,例如我的U-Boot2.95.3编译器编译,而Linux内核用的是3.4.1,我设置2.95.3为默认编译器。对于使用非默认路径编译器的代码,可以填写CROSS_COMPILE到绝对路径,例如CROSS_COMPILE=/usr/local/arm/3.4.1/bin/arm-linux-。另外,Linux内核的Makefile还有一个ARCH选项要修改,以后说。



编译开源代码的一般步骤为:清除之前编译结果(clean)、设定编译配置(config)、编译(make



1.清除之前编译结果


一般可以用:


# make clean


或者


# make distclean


2种写法的区别在于,distclean不仅仅清除编译生成的*.o文件,而且还清除已经设定的编译配置。


2.设定编译配置


主要作用是将繁杂的代码进行组织,屏蔽所需编译目标不需用到的源代码文件,并将这个组织的结果保存下来。设定编译配置命令例如:


Linux内核编译的:


# make menuconfig


# make config


# make smdk2410_defconfig


U-Boot编译的:


# make smdk2410_config


menuconfig是最常用的一种方式,它将调用本机编译器(HOSTCC)产生一个交互的文本菜单式界面,对内核的编译选项、驱动支持、文件系统、调试、外设等进行设置。config是一个提问式的配置方式,很麻烦,不推荐使用。smdk2410_defconfig是针对三星的SMDK2410开发板的基本硬件进行配置,这可以节约一些配置内核的时间。类似这种xxxx_config的配置,体现了购买“大众”型开发板的优势,可以用最短的时间,建立起一套有效的嵌入式系统。



3.最后是编译


一般可以直接输入make。但是对于Linux2.4内核,之前还必须输入


# make dep


用以产生源代码之间的关联信息,2.6版本的内核不再需要这个步骤。


对于Linux内核,编译可以生成不同格式的映像文件,例如:


# make zImage


# make uImage



zImageARM Linux常用的一种压缩映像文件,uImageU-boot专用的映像文件,它是在zImage之前加上一个长度为0x40的“头”,说明这个映像文件的类型、加载位置、生成时间、大小等信息。换句话说,如果直接从uImage0x40位置开始执行,zImageuImage没有任何区别。另外,Linux2.4内核不支持uImageLinux2.6内核加入了很多对嵌入式系统的支持,但是uImage的生成也需要设置,这个以后我会介绍。


另外,我假设内核不采用任何模块。没有编译模块这一步。



然后是内核



内核的移植和调试是整个嵌入式系统开发中最麻烦的一步,建议如果没有良好的硬件和C语言基础,以及健壮的神经和充裕的时间,不要涉足内核的开发,尽可能采用网络上例如我的Blog
提供的现成方法,包括所有细节都要一一仿制,完成内核的移植。其实,这是考验你运气的一个环节,可能有的人一次就移植成功,可能有的人因为一些小小环节的
问题,例如编译器版本问题、内核版本问题、代码修改输入错误之类的,遇到一些稀奇古怪的错误,卡住你的工作而无法继续。同时,这对你的耐心和毅力也是一个
考验。呵呵,我被考验了一个月,也算是比较倒霉吧。内核修改和编译需要做的工作很多,由于
Linux设备的驱动是集成在内核里的(当然还可以作为模块挂载,但是我不讨论模块问题),需要对内核代码进行修改。以后我会专门介绍。内核实现的功能是对硬件资源如内存、串口、液晶控制器的管理,以及对操作系统执行的任务程序的调度。



最后是文件系统



内核不能包括一个嵌入式系统所需的所有东西,例如程序,资料等,而且如果没有文件系统,对嵌入式系统工作过程产生信息的纪录也会成问题,所以一般的嵌入式Linux系统需要文件系统。当然没有文件系统内核也不是不能工作,这我就不太懂了,毕竟是个高深的问题……以我的跟踪内核运行认识来看,只要把你所需要执行的任务编译进内核,然后对初始化部分进行修改,让其在没有root文件系统的时侯继续下去,对你的任务进行调度也许就可以。



嵌入式LinuxPCLinux不同,一般嵌入式系统没有硬盘,所以传统的Linux文件系统如ext2hpfs之类的不能用在嵌入式Linux上。常见的嵌入式文件系统有:romfscramfsjffsyaffs等,当然也可以通过Ramdisk使用ext2。这些文件系统的特性可以自己Google一下。



我最初接触到文件系统的时候,曾经有个很纯朴的想法,既然电脑硬盘上有文件系统,需要分区后格式化,那么嵌入式系统的Flash是不是也必须进行这样的操作呢,而且,分区表纪录在那里呢?在嵌入式Linux中,对Flash并不需要进行分区,目前我的解决方法是把“分区表”信息写入内核,然后直接在内核中分区表信息对应的Flash区域读写,这在内核中叫做MTD支持(Memomry Techonlogy Device),Flash同样需要擦除后写入相应内容——这可以通过Bootloader来完成,不像PC中用的是安装程序。



关于文件系统的建立,我还没有完全研究完,我仅仅是利用了从我的开发板原始文件系统中剥离的一个文件系统,还有很多错误,以后我会补充上文件系统建立的详细文章。


在这些总结背后,我做了许多工作,包括跟踪U-Boot启动Linux部分的代码,内核启动代码,内核初始化代码等。我利用了内核的一些汇编的接口,用以在内核启动过程中输出调试信息。如下:


这是保存寄存器的宏:


/*


* Lu Xianzi's Kernel debugging macro


*/


#define LXZ_LL_DEBUG 1


.macro lxz_save_regs


stmfd sp!, {r0-r12}


.endm



.macro lxz_restore_regs


ldmfd sp!, {r0-r12}


.endm



这是一个调用的例子:


/* =============================================================== *


* Tracing code added by Lu Xianzi


*/



#ifdef LXZ_LL_DEBUG


lxz_save_regs


adr r0, lxz_str_into_creat_pt


bl printascii


adr r0, lxz_str_page_tbl_addr


bl printascii


mov r0, r4


bl printhex8


mov r0, #'/n'


bl printch


lxz_restore_regs


b 1f


lxz_str_into_creat_pt:


.asciz "/nInto create page table section!/n"


.align


lxz_str_page_tbl_addr:


.asciz "Page table address = "


.align


1:


#endif


/* =============================================================== */



需要提醒的是,printasciiprinthexprintch这几个函数只是使用了r0~r3这几个寄存器。



跟踪内核的运行是一件非常痛苦的事情,但真能解决问题,而且学到很多东西。


路过

鸡蛋
5

鲜花

握手

雷人

刚表态过的朋友 (5 人)

发表评论 评论 (10 个评论)

回复 zhixiaoyuhong 2015-1-9 19:13
想问问楼主,你写的东西都是从哪里学到的?是从视频还是从书中?有什么合适的书籍推荐呢?正在学习嵌入式,多谢多谢~
回复 laihama 2015-1-10 16:20
zhixiaoyuhong: 想问问楼主,你写的东西都是从哪里学到的?是从视频还是从书中?有什么合适的书籍推荐呢?正在学习嵌入式,多谢多谢~ ...
转载的。。。。看看书,做实际项目才能锻炼自己。
回复 ares_lan 2015-1-14 16:49
一定要坚持下去啊。加油
回复 HORSE7812 2015-1-14 22:27
加油
回复 wuxing1106 2015-1-19 09:44
好东西,楼主加油
回复 hyunfei2009 2015-1-20 09:32
值得赞
回复 muxb 2015-3-3 18:15
楼主总结的很好。
回复 city520boy 2015-4-2 09:52
总结的很好啊
回复 刘蒋123 2015-4-9 21:30
正在学习这方面的知识,希望可以加你一下