当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 讲师博文 > 自己动手嵌入式Linux开发工具

自己动手嵌入式Linux开发工具 时间:2020-05-27      来源:原创

开发工具很重要。它们节省了开发和调试时间。但最重要的是,它们通过使许多例行,无聊和耗时的任务自动化来使开发人员更加快乐和高效。看到程序员将大量宝贵的时间花在诸如将代码下载到嵌入式目标这样的例行任务上,真是令人痛苦。即使在传统的嵌入式系统中,这种情况也不少见,但对于嵌入式Linux而言,情况却更加糟糕,因为嵌入式Linux显然缺乏良好的开发工具。

没有好的嵌入式Linux工具的看法并不完全正确。首先,有一些值得考虑的商业工具。但是,与传统的嵌入式系统开发世界相反,商业工具并不是唯一的选择。使用免费提供的开放源代码工具,可以相对轻松地完成很多工作。实际上,我认为自己动手开发环境可以远远优于任何商业产品,因为它可以为您提供定制产品,灵活性和敏捷性水平,而这是任何现成产品都无法匹敌的。

商业工具

嵌入式Linux集成开发环境(IDE)软件套件通常可从销售嵌入式Linux的同一家公司获得。风河,MontaVista,TimeSys,LynuxWorks和其他十几家供应商浮现在脑海。尽管这些公司会尝试向您出售操作系统和随附的IDE,但此IDE可能会或可能不会与该特定发行版绑定。这些工具大多数都是基于Eclipse的,并且提供类似的功能,仔细观察发现它们仅仅是笨拙的编辑器,编译器包装器和调试器。我知道的唯一例外是Wind River Workbench,它实际上是一种商业级产品,考虑到Wind River在Tornado IDE for VxWorks中的使用经验,这不足为奇。

现成的IDE套件的主要问题不是软件本身,而是嵌入式系统开发的本质。要释放IDE的全部功能,必须在目标嵌入式平台上运行代理,如图1所示。但是,如果您正在使用客户系统,则此代理可能不可用,或者如果您正在进行相对短期的项目,则可能没有足够的时间来集成它。但是,此代理通常无法运行,因为它依赖于某些可能无法使用的内核功能,因为所有嵌入式平台都不相同,并且嵌入式系统程序员喜欢调整系统内部,经常破坏IDE代理所依赖的某些功能。

自己动手

做自己动手的方法有很多优点,例如生成的工具是免费的,不依赖于任何特定的Linux发行版,可以根据您的需求进行自定义,最重要的是,它是模块化的。这使您可以仅将真正需要的功能快速移植到新平台。

现在,让我们看一下最常见的开发任务,并了解如何使用开源工具将其自动化和简化。我们也将尝试将所有内容绑定在一起以形成类似于IDE的东西,尽管这并不是必须的,这里描述的每个工具都可以单独使用。请注意,所有与网络相关的示例均假定所有网络组件都位于具有192.168.0.0/24子网的同一LAN中。假定192.168.0.9是主机地址,而192.168.0.10是目标地址。

主机平台

尽管我将介绍的所有内容也可以在Windows主机上完成,但我建议使用Linux。它更加方便,并且提供了更多的工具和实用程序。而且,如果您依靠Word和Outlook等一些Windows应用程序,则仍可以使用VirtualBox,Wine或其他商业软件包在Linux上运行它们以进行仿真。如果您不熟悉Linux,那么使用Linux主机也将迫使您更快地学习新平台。

编写代码

许多开发人员对于编程编辑器都有一定的偏好,并且有许多开源和商业Linux软件包可供选择。我最喜欢Emacs,因为它具有所有必需的功能(还有更多功能),并且很可能会安装在每台Linux主机上。

Emacs是一个功能强大的编辑器,但需要一些配置才能释放其功能。我建议至少启用以下选项:用于突出显示语法的全局字体锁定模式,imenu-add-menubar-index以将当前文件中定义的C函数列表显示为下拉菜单,以及cscope(这是一个带有Emacs集成支持的独立软件包)标签以进行快速搜索和代码浏览。您可以通过Emacs的“选项”菜单更改各个选项,也可以将清单1中的示例剪切并粘贴 到.emacs文件中。

我建议在Emacs中运行编译过程。使用以下键盘快捷键将使其更加方便:

(global-set-key 'f5 'compile)   

Emacs具有程序员可以使用的许多其他功能,例如版本控制集成,自动完成,匹配括号,自动缩进,C宏扩展,gdb调试器集成和代码折叠(有关进一步阅读,我建议使用“ Emacs for程序员”,www.linuxjournal.com / article / 2821 和“使用Cscope和SilentBob分析源代码”,www.linux.com / article.pl?sid = 07/03/05/1715201 )。并且不要忘记打印Emacs安装随附的Emacs参考卡(refcard.ps)。

运行您的应用程序

在嵌入式目标上下载和运行代码可能是您执行的最常见的操作之一,因此使此过程尽可能快速和简便很重要。通常使用TFTP或JTAG完成此操作,但是网络文件系统(NFS)可使此过程变得简单透明。通过在主机上运行NFS服务器并使用makefile规则将编译结果复制到NFS根目录,然后通过NFS从嵌入式目标安装此目录,可以使用NFS。这样,已编译的应用程序将立即出现在目标位置,而无需程序员的任何干预,如图2所示。

实施主机配置时,请确保已安装NFS服务器,并将以下行添加到/ etc / exports中(在修改IP和目录之后):

/home/user/nfsroot 192.168.0.*    (rw, no_root_squash, sync)   

然后重新启动NFS服务器。这使来自192.168.0.0/24子网的NFS客户端可以完全访问nfsroot目录。

在目标配置中,确保使用NFS支持编译内核。换句话说,启用了CONFIG_NFS_FS,CONFIG_NFS_V3和CONFIG_NFS_V4选项,并且mount命令支持NFS(如果您正在使用busybox,请检查是否已启用CONFIG_FEATURE_MOUNT _NFS选项)。您必须在目标计算机上发出以下命令(可能作为初始化脚本的一部分):

mount 192.168.0.9:/home/user/     nfsroot /mnt/nfs.   

如果您不能使用NFS,无论是因为您不能修改内核,还是因为您的短期项目不能证明配置它的努力是合理的,那么您仍然不必手动将应用程序从主机复制到目标。可以使用Expect或minicom脚本自动执行此任务,如下所示。

自动化

许多任务可以使用Shell脚本自动化。请注意,您既可以在主机上也可以在嵌入式目标上运行脚本(大多数嵌入式Linux发行版都包含具有脚本功能的Shell,尽管它受到的限制更大)。可以在www.linuxjournal.com/article/1299 上找到有关bash脚本的介绍,但是请记住,您将无法在嵌入式目标上使用许多高级脚本选项,因为它可能具有以下一种不太强大的(和更少的内存消耗)shell,例如BusyBox ash。

假设您有能力编写一个简单的bash脚本,我们将深入探讨一个更复杂但有用的主题,交互式脚本。使用交互式Expect(1)脚本,您可以自动执行诸如图像下载和Flash编程之类的任务。但是由于分支和计时问题,您不能使用简单的bash脚本来自动化交互式任务。

基本的Expect(1)脚本由执行需要交互式自动化的实用程序(例如telnet或minicom)的“ spawn”命令以及一系列“ expect”和“ send”命令组成,如清单2中的示例所示。

的期望 命令等待,直到图案中的一个衍生的进程的输出相匹配。发送 将字符串发送到当前进程。清单2中的脚本下载并复制一个新的引导加载程序映像到Flash。它是为Das U-Boot编写的,但是可以很容易地针对任何其他引导程序或其他环境进行修改。大多数Expect(1)发行版都包含一个方便的自动预期脚本,该脚本会自动记住您键入的命令并为您创建一个期望脚本。但是,我建议您将自动生成的脚本仅用作编写自己的模板的模板,这样可以提高可读性和维护性。

调试

调试嵌入式Linux很棘手,因为根据您调试的是应用程序,驱动程序还是内核代码,该技术可能有所不同。唯一常见的元素是gdb客户端前端,因此我们将从此处开始。gdb客户端通常将在主机平台上运行,尽管从技术上讲,您也可以在目标平台上运行它。它可以通过串行端口或tcp / udp协议连接到目标服务器上运行的gdb服务器(稍后再介绍)。请注意,您不能使用Linux发行版随附的x86 gdb客户端。您将需要来自交叉编译器工具链的嵌入式CPU。

简单的gdb调试会话如下所示:

gdb>file vmlinuxtarget remote 192.168.0.10:2828Ctrl-Cbt   

此示例加载vmlinux映像符号,连接到远程目标,中断正在运行的代码并打印回溯(有关gdb命令的更多信息,请参见gdb用户手册,位于sourceware.org/gdb/current/onlinedocs/gdb_toc.html)。对于快速任务,使用命令行界面很方便,但是对于认真的调试,大多数用户更喜欢图形界面。我建议使用两个图形化gdb包装器:DDD和Insight。

Insight具有流畅的用户界面,但是由于它包含gdb,因此您需要为每个使用的嵌入式CPU体系结构使用不同的二进制文件。DDD有点笨拙,因为它是GUI包装程序,但是它可以与外部gdb可执行文件一起使用(使用-debugger 参数),从而使您可以使用交叉编译器工具链中的gdb二进制文件。gdb服务器将根据您要调试的内容而有所不同。对于应用程序,您需要通过以下方式在目标上运行gdbserver可执行文件:

gdbserver 192.168.0.10:2828     your_application   

gdbserver 将运行 要调试的二进制 your_application ,并等待gdb客户端在指定端口上连接。如果使用 -attach 命令行参数执行,它还可以附加到正在运行的进程。

出于各种原因,内核调试非常棘手,其中最重要的一个事实是kgdb(等效于内核gdbserver)可能未集成到内核中,因此您可能需要从kgdb.linsyssoft.com下载kgdb补丁,应用补丁,然后重新编译内核。这样做将允许您通过串行端口或通过以太网调试内核。使用kgdb版本1.8及更早版本调试内核可加载模块时,您必须使用loadmodule.sh脚本或add-symbol-file gdb命令将模块对象文件手动加载到gdb中,以便gdb知道模块的符号表。

如果要创建板级支持包或进行一些底层内核编程,则可能需要JTAG探针。选择探针时,请确保它支持Linux,尽管当今大多数探针都支持。一个对Linux友好的JTAG探针应该支持Linux目标和主机。支持远程gdb协议进行调试;支持调试内核代码,应用程序和可动态加载的模块;并支持Linux MMU。

后者比较棘手,因为在调试过程中,您可能需要访问当前未映射的虚拟内存页面。探针必须知道如何从Linux内部数据结构中提取此映射信息,或者使Linux重新映射此虚拟地址。Linux主机和远程gdb支持不是必需的,但它很方便,因为它使您可以使用相同的gdb客户端前端使用JTAG进行调试。

跟踪

调试允许您捕获简单的错误,但是不幸的是,困难的错误通常会受到定时的影响,并且可能不会出现在调试器中。在这种情况下,您考虑使用Linux跟踪工具包(LLT),可以从www.opersys.com/LTT下载该工具。。它允许跟踪多个进程和内核本身的各种事件类型,并且可以以图形方式显示此信息,以帮助调试复杂的多进程系统。要使用LTT,您必须修补内核并安装LTT守护程序和实用程序。请注意,LTT守护程序需要读写文件系统访问权限才能存储跟踪文件。我不建议使用jffs2文件系统将此类信息存储在Flash中,因为这会严重影响系统性能和时序。如果您有足够的内存,RAM磁盘是最佳选择。如果不是这种情况,我建议使用NFS。

最简单的LTT会话如下所示:

trace 60 trace_filetraceview trace_file   

这两个命令都是辅助脚本。第一个启用跟踪60秒钟,并使用trace_file 作为跟踪结果文件的基本名称。第二个工具执行图形化的跟踪可视化工具(有关更多信息,请阅读LTT参考手册,网址为www.opersys.com/LTT/ dox / ltt-online-help / index.html )。

概要分析

最终,所有嵌入式系统项目都进入了优化阶段,在此阶段,可以使用良好的Profiler。OProfile是Linux的系统级分析器,能够分析用户空间应用程序,内核代码和可加载模块。OProfile软件包包含内核代码,用户空间守护程序和实用程序。幸运的是,由于OProfile是库存的Linux 2.6内核的一部分,因此不需要内核修补。

典型的OProfile会话如下所示:

opcontrol --vmlinux     =/path/to/vmlinuxopcontrol --start#execute your codeopreport -l /path/to/mybinaryopcontrol --reset   

前两个命令启动事件探查器,opreport打印结果,最后一个命令重置数据。OProfile是功能强大的探查器,具有许多功能,所有这些功能均不在本文讨论范围之内,但是我建议您在oprofile.sourceforge.net/doc/in dex.html中阅读更多内容。

嵌入式开发人员的一个重要提示是,他们可以按模块过滤分析结果,这些模块可以是驱动程序,应用程序或内核本身。请注意,OProfile是统计分析器,这意味着它在中断(通常是定时器中断)时对程序计数器的值进行采样,因此您必须在一段最小的时间内运行代码以获得有意义的结果。

如果您的硬件与大多数硬件一样,并且具有可以在诸如高速缓存未命中之类的事件上产生中断的性能计数器,则不仅可以找到占用CPU最多的代码段,而且可以找到效率最高的缓存。除非您使用外部CPU,否则OProfile将已经支持该CPU的性能计数器。

将所有内容绑定在一起

尽管这不是必需的,甚至可以使事情变得更复杂,但是如果您对可以使用键盘快捷键和菜单执行所有日常任务的类似IDE的整体软件包更满意,则最简单的方法是创建一个名为“ Embedded”的新Emacs菜单,并将所有脚本添加到该菜单。清单3中的示例 (应该添加到.emacs文件中的Emacs Lisp代码)说明了这一点。

对此代码的完整说明需要一些Lisp知识(并且不在本文的讨论范围之内),但是将给出每个命令的简短描述,因此您可以自定义代码并添加新功能,而无需完全了解Lisp和Emacs内部。第一组命令创建“嵌入式”下拉菜单。第二个菜单在执行“ program-flash” Lisp功能的菜单中添加了一个新条目“ Program flash”。第三组将该命令绑定到“ Ctrl-c”,然后是“ pf”组合键。最后一个是Lisp函数,该函数执行“ program-flash.sh” shell脚本,将其输出重定向到新创建的Emacs缓冲区。

自己创建嵌入式Linux开发环境可能看起来很艰巨。但是请记住,这是一项不错的投资。可以轻松地将此任务外包给嵌入式Linux顾问,在这种情况下,它的成本可能会比现成的嵌入式Linux IDE低。

上一篇:传感器融合带来多重好处

下一篇:虚拟化嵌入式Linux

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部