历史上的今天
返回首页

历史上的今天

今天是:2025年04月22日(星期二)

正在发生

2021年04月22日 | ARM Linux开发阶段性总结

2021-04-22 来源:eefocus

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

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


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


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


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


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


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


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


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


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


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


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


还必须说明的是,通常从开源工程网站下来的都是软件的源码,需要自己进行编译。编译由源码目录下的“Makefile”这个文件决定,其中包含有关于编译的配置和操作类型的信息。一般用于多平台的源码,Makefile中都有CROSS_COMPILE这一项,在编译之前必须将它指定到交叉编译器。对于arm-linux-gcc这个交叉编译器,如果设置了指向arm-linux-gcc的缺省路径,可以填写CROSS_COMPILE=arm-linux-,注意,后面的“-”不可以少。通常由于开源代码的编译器兼容性太差,你需要在你的电脑里安装多个版本的交叉编译器,例如我的U-Boot用2.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


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


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


然后是内核


内核的移植和调试是整个嵌入式系统开发中最麻烦的一步,建议如果没有良好的硬件和C语言基础,以及健壮的神经和充裕的时间,不要涉足内核的开发,尽可能采用网络上例如我的Blog中


提供的现成方法,包括所有细节都要一一仿制,完成内核的移植。其实,这是考验你运气的一个环节,可能有的人一次就移植成功,可能有的人因为一些小小环节的


问题,例如编译器版本问题、内核版本问题、代码修改输入错误之类的,遇到一些稀奇古怪的错误,卡住你的工作而无法继续。同时,这对你的耐心和毅力也是一个


考验。呵呵,我被考验了一个月,也算是比较倒霉吧。内核修改和编译需要做的工作很多,由于Linux设备的驱动是集成在内核里的(当然还可以作为模块挂载,但是我不讨论模块问题),需要对内核代码进行修改。以后我会专门介绍。内核实现的功能是对硬件资源如内存、串口、液晶控制器的管理,以及对操作系统执行的任务程序的调度。


最后是文件系统


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


嵌入式Linux和PCLinux不同,一般嵌入式系统没有硬盘,所以传统的Linux文件系统如ext2,hpfs之类的不能用在嵌入式Linux上。常见的嵌入式文件系统有:romfs,cramfs,jffs,yaffs等,当然也可以通过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


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


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


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


推荐阅读

史海拾趣

Block USA Inc.公司的发展小趣事

除了支付业务外,Block USA Inc.还积极投身于软件SAAS服务的研发与创新。公司推出了一系列针对餐厅、薪资发放和预约等领域的软件解决方案,帮助商家提升运营效率和管理水平。这些软件服务的推出,不仅进一步丰富了Block的产品线,也为其在电子行业中树立了创新者的形象。

Hartmann Codier GmbH公司的发展小趣事

在发展过程中,Block USA Inc.也面临着来自竞争对手和行业变化的挑战。然而,公司始终保持着创新精神,不断调整和优化产品与服务,以适应市场的变化。例如,面对数据安全和隐私保护的日益严格要求,Block加强了其数据保护措施,并公开承认了数据泄露事件并积极采取措施进行补救。同时,公司还继续拓展其业务边界,探索新的增长点,以保持其在电子行业中的竞争优势。

这些故事只是Block USA Inc.在电子行业发展历程中的一部分,它们展示了公司如何通过不断创新和拓展业务领域,逐步成为一家具有影响力的综合性电子企业。然而,随着市场的不断变化和竞争的加剧,Block仍需保持警惕并持续努力,以应对未来的挑战和机遇。

Delphi Connection Systems公司的发展小趣事

Delphi Connection Systems公司深知产品质量是企业生存和发展的基石。因此,公司始终坚持严格的质量控制标准,从原材料采购到产品制造、检测等各个环节都进行严格把关。这种对质量的执着追求赢得了客户的信任和口碑,使公司在电子行业中树立了良好的品牌形象。

Gennum ( Semtech )公司的发展小趣事
作为输入设备,用于触发电路的不同状态。
Everbuild公司的发展小趣事

Everbuild公司成立于2005年,创始人李明是一位对电子技术充满热情的年轻人。在创业初期,公司只有几个员工和一间狭小的办公室。李明带领团队日夜兼程地研发电子元器件,但由于资金短缺和市场竞争激烈,产品销量并不理想。然而,他们并没有放弃,通过不断的技术创新和成本控制,终于在一年后推出了一款具有竞争力的电源管理芯片,赢得了市场的认可。

Akustica(Bosch)公司的发展小趣事

随着全球对环保和可持续发展的重视,Everbuild也将绿色环保理念融入到产品设计和生产过程中。公司采用环保材料和节能技术,减少生产过程中的污染和能源消耗。同时,Everbuild还积极参与环保公益活动,倡导绿色生活方式。这些举措不仅提高了公司的社会责任感,也为公司的可持续发展奠定了基础。

问答坊 | AI 解惑

一个按钮通过SetWindowPos( )函数移动了位置,通过ShowWindow(SW_HIDE)却隐藏不了,怪事!

一个按钮通过SetWindowPos( )函数移动了位置,通过ShowWindow(SW_HIDE)却隐藏不了,怪事!…

查看全部问答>

关于对数据总线操作的问题

最近写了个应用程序对数据总线上的数据进行操作,关于物理地址和虚拟地址的映射我知道 假设*vi_adress为映射好的虚拟地址 先是写操作 *vi_adress=tmp  (tmp是数据) 这个操作是成功的 现在我想读取外面从过来的数据 tmp=*vi_adress& ...…

查看全部问答>

准备PCB打样还有5CM*6CM的空白位置,有需要的联系我,仅限今日20:00之前

已经有人联系 [ 本帖最后由 rogerangel 于 2011-6-29 22:49 编辑 ]…

查看全部问答>

DDR测试内容与规范

DDR测试内容与规范,不错的资料:  …

查看全部问答>

TI m3 IO的状态

看datasheet上说All GPIO pins are tri-stated by default。请问这个tri-stated是一个什么状态?…

查看全部问答>

小功率LED驱动电源

   保险丝,压敏电阻,热敏电阻,EMI,EMC,整流,PFC,漏极尖峰吸收,IC,电流检测,频率设定,反馈(TL431,光耦,运放),输出.  我现在是在弄电焊机相关方面的工作,可以感觉工作不怎么给力,后听个同学介绍说LED方面还行,这样就自己去学习了下LED ...…

查看全部问答>

[视频分享] Stellaris LaunchPad入门讲座第一课——实验一:LaunchPad内置程序演示

欢迎参加 Stellaris EK-LM4F120XL LaunchPad 入门讲座的在线培训。本次的在线培训将分为多个部分,包括视频讲解和实际的调试操作。第一课介绍了 TI 的 Stellaris LM4F 系列微控制器及其外设和工具。在本章中,您将了解 Stellaris 线路图以及更多 ...…

查看全部问答>

关于DRV8833驱动振动电机的问题

大家好,最近在做一个振动电机实验,选用的是扁平电机(手机振动电机)和空心杯电机,驱动芯片选用的是TI的有刷直流电机驱动器DRV8833,按照官方的电路搭了一个电路,外接电压5V,逻辑控制3.3V,发现接上电机毫无反应,测试电压发现电机没接上时,输 ...…

查看全部问答>

STc单片机外扩RAM具体怎么确定端口地址的,

我想要STC15F2K32S2单片机连接CH372,具体的这个端口地址到底是如何确定的啊?哪位大侠能跟我讲一下,有资料更好,谢谢咯!感激不尽哪!…

查看全部问答>

跪求PLL问题

大神有没有关于74HC4046组成的锁相环电路啊,求原理图啊,,,有的话分享一下哈,不胜感激,我也分享一点资料哈。。。 …

查看全部问答>