关闭

关闭

关闭

封号提示

内容

首页 c与c++嵌入式系统编程.pdf

c与c++嵌入式系统编程.pdf

c与c++嵌入式系统编程.pdf

上传者: 小宇 2011-10-10 评分 0 0 0 0 0 0 暂无简介 简介 举报

简介:本文档为《c与c++嵌入式系统编程pdf》,可适用于IT/计算机领域,主题内容包含CC嵌入式系统编程MicbaelBarr著于志宏译作者简介MichaelBarr是Netrino公司(一个嵌入式系统共享软件和软件工程服务提供商)的符等。

CC嵌入式系统编程MicbaelBarr著于志宏译作者简介MichaelBarr是Netrino公司(一个嵌入式系统共享软件和软件工程服务提供商)的创始人兼总裁。Netrino公司鼓励所有职员通过为杂志撰稿和在业界会议演讲来分享自己的专业知识。这些资料可以在公司的网站http:wwwnetrinocom找到。Michael拥有马里兰大学的电机工程学士和硕士学位。他的大部分时间都用在嵌入式软件、设备驱动和实时操作系统的开发上了。他还喜欢写作、教书并期待着开始下一部著作的创作。目前他有好几个计划其中包括一部小说。前言首先需要弄清楚你为什么希望你的学生学习某个主题以及你希望他们学到什么那么一般来说你授课的方法或多或少就有了。-RichardFeynman今天几乎所有电子设备里面部包含了嵌人式的软件系统。这些软件隐藏在我们的手表里、录像机里、蜂窝电话里甚至可能在烤面包机里面。军事上会使用嵌入式软件来引导导弹。侦测敌方的飞行物。外太空探测器和许多医疗仪器离开嵌人式软件几乎不可能工作。设计人员不得不写所有的代码实际上成千上万的电子工程师计算机科学家和其他专业人员正在这样做。我也是其中的一员从我的个人经验来说我很清楚掌握这门技术是多么的困难。学校军从未开设有关嵌入式系统的课程。而我也没能从哪个图书馆里找到一本有关这个题目的像样的书。每一个嵌入式系统都是独特的其硬件部分对它的应用目标来说是高度专用的。这就导致了嵌入式系统编程的涉及面很广而且可能会需要很多年才能掌握它。不过几乎所有的嵌入式软件开发都使用了C语言。这本书就是要教你怎样在嵌入式系统中使用C和C的派生语言C。即使你已经知道如问编写嵌入式软件你还是可以从这本书里学到很多东西。除了了解如何更有效地使用C和C你还将会从本书中对常见的嵌人式软件问题的详细解释并从本书所提供的源代码中得到益处。本书中包含的高级主题有存储器检测和验证、设备驱动程序的设计和实现.实时操作系统的内部机理还有代码优化技术。我为什么写这本书我曾经听到一个统计数字在美国平均下来大概每个人拥有八个微处理器。我当时很惊讶怎么可能呢?难道我们周围真的有这么多计算机吗?后来.当我有更多时间来想这个问题的时候我开始把我用过的并且可能含有一个微处理器的东西逐一列出来。短短三分钟内我的清单已经包含了十样物品了它们是:电视机、录音机、咖啡机、报时闹钟、录像机、微波炉、洗碗机、遥控器、烤面包机、还有数字式手表。这还只是我的个人物品我很快就可以拿出我工作中用到的另外十样东西。进一步的发现是很自然的。那些产品里的每一个都不仅仅包含一个处理器。还有软件在里面。最终我知道在我一生里我想做些什么了。我希望能用我的编程技能来开发这种嵌入式的什算机系统。但是我如问能得到必要的知识呢?当时我正在该大学的最后一年而学校里迄今为止没有关干嵌入式系统编程的课程。幸运的是、虽然我那时还处在学习的过程中但当我毕业的时候我还是找到了一家公司从事编写嵌人式软件的工作。不过在这里我必须要靠自己的努力因为为数不多的了解嵌人式软件的几个人通常都非常的忙以至于很少有时间来解答我的问题所以找到处找能给我教益的书、最后。才发现我必须自学所有的东西因为我从没有找到这么一本书并且我很奇怪为什么会没有人来写这么一本书。现在我决定自己来写这样一本书了。在此过程中我也发现了为什么以前没有人做这件事。关于这个题目最困难的是决定什么时候可以收笔封稿了。每一个嵌八式系统都是独一无二的并且就我所知每一条法则同时都会存在例外倩况。不过我已经尝试着提取出这个主题的本质的东西并且仅仅讲述嵌人式系统程序员们必须要了解的那些部分。面向的读者这是一本关于使用C和C来进行嵌人式系统编程的书。同样这里假定读者已经有了一些编程经验并且至少熟悉这两种语言的语法。如果你比较熟悉基本的数据结构例如链表等也会有些帮助。这本书并不要求你在计算机硬件方面了解很多但是希望你愿意由这本书而学一点有关硬件的知识。这毕竟是一个嵌入式程序员工作的一部分。写这本书的时候在我的脑海里有两类读者。第一类是初学者正像我刚从大学毕业的时候那样。她会何一些计算机科学或工程的背景并有几年编程经验。初学者感兴趣的是如何为一个既有的设备写嵌人式程序却不能肯定该如问着手去做。看完前五章后她就能够用她的编程技术来开发简单的嵌入式程序了。本书的其他部分可以作为她在以后的职业生涯里遇到更高级的主题时的参考。第二类读者已经是嵌入式系统程序员了。她熟悉嵌入式硬件并目知道怎样来为此编写软件。但是她正在寻找一本参考书来解释一些关键问题。出许这位嵌入式系统用序员一直在用汇编语言编程并且刚接触C和C不久。这样的话这本书会教给她如问在嵌入式系统里使用这些语言。后面的章节还会提供她所需要的更高级的材料。不论你是否属丁上述两种读者之一我还是希望这本书能够以一种友好和方便的形式给你一些帮助。本书的组织本书包括十章、一个俘虏、一个词汇表还有一个带注释的参考书目列表。这十章恰好可以分为两个部分。第一部分包含第一到第五章主要面向嵌人式系统的初学者。这些章节应该按照它们出现的次序完整地读一下这将快速地带给你有关嵌入式软件开发的基础知识。结束了第五章之后你就可以独立开发一些小的嵌入式软件了。第二部分包括第六到第十章讨论了不论有没有经验的嵌入式程序员都很感兴趣的一些高级主题。这些章节基本上各自独立可以按照随意的次序来读。另外第六到第九章包含的示例程序可能会对你将来的嵌人式系统项目有所帮助。z第一章“引言”。介绍嵌入式系统。其中定义了若干术语给出了一些例子并且说明了为什么选择C和C来作为本书的编程语言。z第二章“你的第一个嵌人式程序”。引导你尝试用C语言编写一个简单的嵌入式程序的全过程。这比较类似于其他很多编程书籍里的“HelloWorld”的例子。z第三章“编译、链接和定址”。介绍了一些软件工具。你将用它们来为一个嵌人式处理器生成可执行文件。z第四章“下载和调试”。介绍将可执行程序调人一个嵌入式系统的各种技术手段同时也描述了你可以使用的调试工具和技术。z第五章“接触硬件”。描述了学习一个不熟悉的硬件平台的简单过程。结束本章后你已经能够书写和调试简单的嵌人式程序了。z第六章“存储器”。讲解了关于嵌人式系统内的存储器作所需要知道的全部知识。这一章还包括了存储器测试和闪速存储器驱动程序的源代码实现。z第七章“外围设备”。说明了设备驱动程序的设计和实现技术同时包含了一个通用外围设备(定时器)的示范驱动程序。z第八章“操作系统”。包含了一个可以用在任何嵌入式系统中的很简单的操作系统。这有助于你决定你是否需要这么一个操作系统如果需要的话是买一个还是干脆自己写一个。z第九章“合成一个整体’。进一步拓展前面章节学到的关于设备驱动程序和操作系统的知识。本章讲解了如何控制更复杂的外设同时引入了一个完整的示范应用来把你学过的东西综合到一起。z第十章“优化你的代码”。描述了如何在增加代码运行速度的同时减少你的嵌入式软件对存储器的需求。这包括使用一些技巧来刊用最有效的C特性而不导致显著的性能损失。在整本书里我一直在努力在特定的例子和通用的知识之间保持平衡也就是尽可能地消除微小的细节使这本书更加易读。像我一样通过阅读示例你会从这本书里得到最大的收获但是应该只把它们作为理解重要概念的工具。记住不要的在任问一个电路板或芯片的细节里面。在理解了全面的概念以后你将能够把它应用在你所碰到的任何嵌人式系统中。在排版和其他方面的约定本书使用了如下的一些印刷约定:斜体{italic}当文件、函数、程序、方法、例程和选项出现在段落中的时候用来表示它们的名宇。斜体也用来强调或引人新的术语。等宽(constantwidth)用来显示文件的内容和命令的输出。在段落体中.这种字体用来表示关键字、变量名、类、对象、参数和其他代码片断。等宽祖体(constantwidthbold)用来在示例里表示你输人的命令和选项。其他约定是和性别与角色有关的。关于性别我有意在全书区分使用了“他”和“她”。“他”代表奇数章节而“她”代表偶数章节。关于角色我偶尔会在我的讨论中区对一下硬件工程师、嵌人式软件工程师和应用程序员的不同任务。但是这些称谓只是工程师个体的角色需要注意到的是一个人充当多个角色是常有的事。在线取得示例这本书包含很多示例源计码除了最小的单行代码以外都可以在线获得。这些示例按照章节来组织、并包含了build指令(makefile)来帮助你重建每个可执行文件、完整的文件可以通过FTP得到在ftp:ftporeillycomexamplesnutshellembeddedc。建议与评论我们已尽全力保证本书内容的正确性但你仍可能发现有些内容不对(甚至可能是我们出了错误!)。你的建议将帮助我们使下一版更加完美请告诉我们你找到的错误以及你的建议写信到:美国:O'ReillyAssociates,IncMorrisStreetSebastopolCA中国:北京市海淀区知春路号希格玛公寓B座室奥莱理软件(北京)有限公司询问技术问题或对本书的评论请发电子邮件到:infomailoreillycomcn最后你可以在WWW找到我们:http:wwworeillycomhttp:wwworeillycomcn个人说明和致谢我曾经很想写一两本书但是现在我这么做了以后我必须承认我开始的时候非常的天真。我甚至不知道要做多少工作、另外还会有多少人被牵扯进来。不过令我吃惊的是找一个愿意出版我的书的出版社是如此容易我原以为这会是很困难的一件事。从提议写书到出版这个计划花了两年才完成。这是因为我一直在全时工作并且希望尽可能保持我的社会生活所致。要是我早知道我会熬夜到很晚来为最后的底稿而苦恼的话我也许会放弃我的工作来早点交付这本书。但过继续工作对这本书很有好处(同时对我的银行账户也有好处)。这使我有机会对以和很多嵌入式硬件和软件的专家进行广泛的讨论他们巾的很多人通过审阅部分成全部的书稿为这本书做出了直接的贡献。我非常感或以下诸位与我分享了他们的知识并且一直在帮助我的工作:TonyBennet、PaulCabler(和其他来自Arcom的很棒的人们)MikeCorish、KevinD'Souza、DonDavis、SteveEdwards、MikeFicco、BarbaraFlanngan、JackGanssle、StephenHarpster(他在看完早期书稿后管我叫“断句王”)、JonathanHarris、JimJesen、MarkKohler、AndyKollegger、JeffMallory、IanMiller、HenryNeugauss、ChrisSchanck、BrianSilverman、JohnSnyder、JasonSteinhorn(正是他的流畅的语法素养和技术批评的眼光使这个书值得一读)、IanTaylar、LindseyWereen、JeffWhipple和GregYoung。我还要感谢我的编辑AndyOram。要是没有对我最初建议的巨大热情、超乎寻常的耐心和持续的鼓励这本书将永远不会完成。最后我要感谢AplaDharla感谢她在这个漫长的过程中给予我的支持和鼓励。MichaelBarrmbarrnetrinocom第一章引言我想全世界计算机市场也许会有五台。ThomasWatson(托马斯沃森)IBM公司主席没有人会想在家里放一台计算机。KenOlson(肯奥尔森)DEC公司总裁最近几十年里最令人惊讶的事莫过于计算机逐渐占据了人类生活的主要地位。今天在我们的家里和办公室里计算机的数量要比使用它们来生活和工作的人还要多只是这些计算机里有很大一部分我们没有意识到它们的存在罢了。在这一章里我将说明什么是嵌人式系统以及可以在哪里找到它们。同附会介绍一下嵌人式编程的主题说明一下为什么本书采用C和C语言讲述另外简单介绍一下示例中所用到的硬件环境。什么是嵌入式系统一个嵌入式系统(embeddedsystem)就是一个计算机硬件和软件的集合体也许还包括其他一些机械部件它是为完成某种特定的功能而设计的。一个很好的例子就是微波炉。几乎每个家庭都有一台并且每天都有上千万台微波炉在被人们使用着但是很少有人意识到有处理器和软件在帮助他们做饭。这和家里的个人计算机形成了鲜明的对比。同样是由计算机硬件和软件还有机械部件(比如硬盘)组成的个人计算机却不是用来完成某个特定功能的。相反它可以做各种不同的事情。很多人用通用计算机(generalpurposecomputer)来区分这一点。在发货的时候通用计算机就像一块没有字的黑板制造商并不知道用户要拿它来做什么。一个用户可能会用它来做文件服务器。另一个只用来玩游戏还有一位可能会用它来写下一部伟大的美国小说。本章内容:z什么是嵌入式系统z各种实现间的差异zC:最基本的必需品z关于硬件的一些说明而嵌入式系统常常是一些更大的系统中的一个组成部分。比如现代的轿车或卡车里就包含了很多嵌人式系统。一个嵌人式系统会被用来控制防刹车锁死另一个监控车辆的气体排放情况还有一个用来在仪表板上显示信息。虽然不是必需的但在某些情况下这些嵌人式系统会通过某种通信网络互相连起来。为了不至于混淆你的思路有必要指出通用计算机本身就是由很多嵌入式系统组成的。比如我的电脑包含了键盘、鼠标、显示卡、调制解调器、硬盘、软盘和声卡它们中的每一样都是一个嵌入式系统。每个设备都包含处理器和相应的软件来完成特定的功能。比如凋制解调器就是用来在模拟电话线上收发数字信号用的。正是如此所有其他的设备也都能归纳出这么一句话来。如果一个嵌入式系统设计得很完善那么它的使用者完全可以忽略它内部的处理器和软件的存在。微波炉、录像机和报时闹钟就是很好的例子。在某些情况下用同样的功能的定制集成电路硬件来代替上面所说的处理器和软件也能做出具有同样功能的设备来。不过如果真是这样用纯粹的硬件来设计的话在灵活性上就会丧失不少了改几行软件怎么说也要比重新设计一块硬件电路来得方便和便宜。过去和将来本章开头定义的嵌人式系统的第一个产品直到年以后才出现。这一年Intel发布了世界上第一块微处理器主要被日本的Busicom公司用来生产商用计算器。年Busicom请Intel为他们的每一种新式计算器分别设计一种定制的集成电路Intel则拿出了。Intel没有为每一种计算器分别进行设计而是设计了一种可以用在所有型号上的通用电路。这个通用处理器被设计来读取存在外部存储芯片里的一系列指令(软件)。Intel的想法是通过软件的设计可以为每一种计算器提供各自的特性。这种微处理器在一夜之间就成功了并且在以后的十年中获得了广泛的应用。早期的嵌入式应用包括无人空间探测器、计算机控制的交通信号灯以及航空灯光控制系统。在整个年代嵌人式系统静悄悄地统治着微处理器时代并把微处理器带人了我们个人和职业生活的每一个角落。装有嵌人式系统的电子设备已经充斥了我们的厨房(烤面包机、食物处理机、微波炉)、卧室(电视、音响、遥控器)和工作场所(传真机、寻呼机、激光打印机、点钞机和信用卡读卡机)。嵌入式系统的数量看起来肯定会继续迅速增长。已经有很多具有巨大市场潜力的新的嵌入式设备了:可以被中央计算机控制的调光器和恒温器、当小孩子或矮个子的人在的时候不会充气的智能气囊、掌上电子记事簿和个人数字助理(PDA)、数码照相机和仪表导航系统。很明显掌握一定技能并且愿意从事下一代嵌入式系统设计的人将会获得很多的机会。实时系统现在很有必要介绍一下嵌入式系统的一个子集。按照通常的定义实时系统(realtimesystem)就是有一定时间约束的计算机系统。换句话说实时系统可以部分地从及时完成计算或判断的能力来辨别。这些重要的计算有完成的明确期限并且对实际应用来说一个延期的反应就像一个错误的结果一样糟糕。如果一旦延期会产生什么结果是至关重要的问题。例如如果一个实时系统是飞机飞行控制系统的一部分那么一个延期的计算就可能会使乘客和机组人员的生命受到威胁。而把这个系统用在卫星通信环境下危害也许可以限制在仅仅一个损坏的数据包。在更严格的情况下很可能这个时间期限是“硬性”需求的也就是说这个系统是个“硬”实时系统和它对应的就有“软”实时系统了。本书中所有的主题和示例都可以应用到实时系统中。不过一个实时系统的设计者必须更加细心他必须保证软件和硬件在所有可能的情况下都能可靠工作。同时根据人们生活对该系统可靠执行的依赖程度这种保证一定要有工程计算和描述性的论文加以支持。各种实现间的差异与为通用计算机设计的软件不同嵌人式软件通常无法在不做显著修改的情况下在其他嵌入式系统中运行。这主要是由底层硬件之间的明显不同所致。每个嵌人式系统的硬件都是为特定的应用专门调整过的这样才能使系统的成本保持很低。所以不必要的电路就被省去了硬件资源也尽可能地共享使用。在这一节里你会学到哪些硬件特性是所有嵌人式系统共有的以及其他方面为什么又会有如此多的不同之处。通过定义我们知道所有的嵌入式系统都包含处理器和软件那么还有哪些特性是它们共有的呢?当然要想执行软件就一定要有存储执行代码的地方和管理运行时数据的临时存储区这就分别要用到ROM和RAM任何嵌入式系统都会有一些存储区。如果只要求很少的存储量也许就使用与处理器在同一芯片里的存储器否则就需要使用外部存储芯片来实现。所有嵌人式系统都包含其种输入和输出。例如一个微波炉的输人就是前面板上的按钮和温度探测器输出就是人可阅读的显示信息和微波射线。嵌入式系统的输出几乎总是它的输入和其他一些因素的函数、包括花费的时间、当前的温度等等。输入常见的形式有传感器和探测器。通信信号或物理世界的某些变化。图给出了嵌入式系统的一个常见的例子。图一个基本的嵌入式系统除了上述几个共同点嵌入式系统的其他部分通常是互不相同的。实现之间的差异是由不同的设计侧重导致的。每个系统都是面向完全不同的一整套需求这些需求的折中考虑直接影响了产品的开发过程。例如如果一个系统要求成本低于美元,那么就有可能要牺牲一些处理性能或可靠性才能达到要求。当然生产成本只是嵌入式硬件开发人员需要考虑的一个可能的限制而已。其他要考虑的设计需要还包括:处理能力要完成目标所需的运算能力。一个常用来衡量运算能力的指标是MIPS(以百万计算的每秒可执行的指令数量)。如果两个处理器的指标分别是MIPS和MIPS那么就说后者的运算能力更强一些。但是还需要考虑处理器的其他一些重要特性。其中之一是寄存器字长一般会是到位。现在的通用计算机一般使用位或位的处理器但是嵌入式系统通常仍使用更老、更便宜的位和位处理器。存储器用来保存执行代码和操作数据的存储器的容量。硬件设计人员必须事先做出估计并且在软件开发完成之后增加或减少实际的容量。存储容量也会影响处理器的选择通常寄存器的字长构成了处理器可存取的存储容量的限制例如一个位的寻址寄存器可以确定个存储位置之一(注)。开发费用硬件软件开发过程所需的费用。这是一个确定的、一次性的花费所以这也许无关紧要(通常对于大批量产品)也许需要仔细衡量(在只生产少量产品的情况下)。批量生产费用和开发费用的折中考虑主要由期望的生产批量和销量所决定。例如通常不会选择为一个小批量产品开发自己的专用硬件模块。预计的生命周期系统必须延续多久(平均估算)?一个月、一年、或者十年?这影响到从硬件的选择到开发和生产费用方面的各种设计决策。可靠性最终产品应具有什么程度的可靠性?如果只是一个儿童玩具那么不需要总是工作正常但是如果是航天飞机或小轿车的一部分那就最好在任何时间都要工作正常。除了这些常见的要求之外系统还有自己详细的功能要求。正是这些要求赋予了嵌人式系统不同的特性比如微波炉、起搏器或寻呼机。注:当然寄存器的字长越小处理器就更可能需要采取一些策略如多个地址空间以支持更大的内存。几百字节是不足以做太多事情的。即使对位处理器而言几千个字节也可能只是最低要求。表说明了前面谈到的设计要求的可能的取值范围。这些只是估计数字并不需要严格采用。在某些情况下几个标准是联系在一起的。比如处理能力的增加也会导致产品成本的增加。同时我们也可以设想同样是增加处理能力也会通过减少硬件和软件设计的复杂性来降低开发成本。所以每一列的数值并不是一定要同时满足。表嵌入式系统常见的设计需求分类低中高处理器或位位或位存储器<KBKB-MB>MB开发费用<$$,~$,,>$生产成本<$$~$>$批量<~>预计的生命周期几日、几周或几月几年十年可靠性可以偶尔故障必须可靠工作必须无故障运行为了同时说明两个嵌人式系统之间的差异以及这些设计需求对开发过程的影响我会比较详细地介绍三个嵌入式系统。我的想法是在具体讨论嵌人式软件开发之前先从系统设计人员的角度考虑一下问题。数字手表计时工具从日、滴漏、沙漏一路发展而来就是数字化手表。它的特性包括显示日期和时间(通常精确到秒)以百分秒计时还有在每个整点发出烦人的响声。正如它所表现的那样这些都是非常简单的功能并不需要很多的处理能力或存储器。实际上采用处理器的唯一原因只是为了使硬件设计可以支持一系列的型号。典型的数字表包含一片简单、便宜的位处理器。因为这种处理器不能寻址较多的存储器所以这类处理器一般都自带了片上ROM。如果有足够的寄存器的话那这个产品连RAM也用不着了。实际上所有电子部件处理器、存储器、计数器和实时时钟几乎都做在同一个芯片上这块表还剩下的硬件就包括输人(按钮)和输出(LCD或扬声器)了。数字手表的设计者的目标是用超低的生产成本来提供一个相对可靠的产品。如果在生产后发现部分手表比其他大多数要更精确些那么这些手表就会被冠以某个品牌以更高的价格出售。或者也可以通过折扣分销渠道来获得利润。对于低价品种则可以把停止按钮和杨声器去掉。这虽然会失去一些功能却几乎不需要改动软件。当然所有这些开发的花费可能会相当高但随着成千上万只表卖出去收入会源源不断地增加。视频游戏机当你从娱乐中心取出任天堂Nintendo或者SONYPlayStation(PS)的时候你就将要使用一个嵌人式的系统。有时候这些机器比同级别的个人计算机的性能还要好不过面向家用市场的视频游戏机同个人计算机比起来还是要便宜一些。正是高的处理能力和低的生产成本这两个相抵触的要求使得视频游戏机的设计师们经常熬夜工作(当然他们的孩子可就过得不错喽)。只要最终产品的生产成本能比较低一般在美元左右。生产视频游戏机的公司一般不去关心系统的开发费用。他们甚至鼓励他们的工程师们设计专用的处理器因而每一次开发费用都比较高昂。所以尽管在你的视频游戏机里会有一个位的处理器它和一个位个人计算机里的处理器可不一定是一样的。一般来说这个处理器是专门用来满足它要运行的视频游戏的要求的。因为在家用视频游戏市场上生产成本是如此重要设计人员也会用一些手段来分摊成本。比如一个常用的技巧是尽可能把存储器和其他外围电路从主电路板上挪到游戏上。这样就会在降低游戏机的成本同时增加了每一个游戏的价格。这样一个系统也许会配备一个强劲的位处理器但主板却只带了几兆内存。这些内存只够启动机器让它可以存取游戏卡上的存储器。火星探测器年两个无人飞船抵达火星。它们的任务是采集火星表面的岩石样本并在分析其化学成分后把结果传回给地球上的科学家们。那个“海盗船”的任务使我感到颇为吃惊。因为我现在被一些几乎每天都要重新启动的个人计算机包围着所以我发现对多年前的这些科学家和工程师真是很伟大他们成功地设计了两台计算机井且使它们在五年里经过了万英里的旅程依然工作正常。很明显在这些系统中可靠性是最重要的要求。如果存储芯片损坏或者软件存在缺陷以至于导致运行崩溃或者一个电连接在碰撞之下断开结果会如何呢?根本没有办法防止这些问题的发生。所以必须通过增加冗余电路或额外的功能来消除这些隐患:使用额外的处理器、特殊的存储器检验、当软件死锁后用一个硬件定时器来复位系统等等各种手段不一而足。最近美国宇航局启动了“探路者”计划主要的目标就是论证一下以有限的预算到达火星的可行性。当然随着年代中期以来技术的极大发展设计者并不需要为这个目标费太多脑筋了。他们可以在给予“探路者”比“海盗船”更强大的处理能力和更多的存储量的同时减少相当一部分冗余设计。“火星探路者”实际包含两个嵌入式系统:着陆艇和漫游车。着陆艇有一个位处理器和MB的RAM漫游车只有一个位处理器和KB的存储量。这种选择也许反映出了两个系统不同的功能需求的考虑不过我可以保证生产成本不是问题。C:最基本的必需品这些系统下多的几个共同点之一是都使用了C语言。和其他语言相比C已经成为嵌人式程序员的语言了情况当然不全总是这样事情总会变的。不过起码现在C是嵌入式世界里最接近标准的东西。这一节里我会说明为什么C会变得如此普遍我又为什么选择C和C作为这本书的主要语言。因为对于一个给定的项目来说选择一种语言对成功的开发是如此的重要所以当一种语言被证明同时适合于位和位处理器适用于字节、千字节甚至兆字节的系统适用于从一个人到很多人的开发团队。是很令人吃惊的。而C语言做到了。当然C是有很多优势的。它小而易学今天每一种处理器都有C的编译器同时有相当多的有经验的C程序员。另外C是和处理器无关的这就让程序员可以着眼于算法和应用而不用考虑特定处理器结构的细节。可是很多其他的高级语言也具备这些优点为什么只有C语言取得了成功呢?也许C语言最具威力的地方也正是把它和其他语言比如Pascal和FORTRAN区别开的地方是它是一个非常“低级”的高级语言。正如我们将在整本书里看到的C给予嵌入式程序员很大程度的直接控制硬件的能力却不会失去高级语言带来的好处。“低级”的内在本质是这个语言的创建者的明显目的。实际上。Kernighan和Ritchie在他们的书《CProgrammingLanguage》的开头有这么一段话:C是一种相对“低级”的语言。这个特征并没有什么不好的含义它只是说明C语言可以处理大多数计算机可以处理的事情。这些事情通常和实际机器实现的技学和逻辑运算结合在一起。很少有其他高级语言可以像C一样为几乎所有处理器生成紧凑的、高效的代码。同时只有C允许程序员方便地和底层硬件打交道。其他嵌入式语言当然C井不是嵌人式程序员使用的唯一语言。至少还有其他三种值得详细说一下.即汇编语言、C语言和Ada语言。在早期的时候嵌人式软件只用目标处理器的汇编语言来书写。这样做使程序员可以完全控制处理器和其他硬件当然也是有代价的。除了更高的软件开发费用和缺乏可移植性汇编语言还有很多缺点同时最近几年找一个有经验的汇编语言程序员也变得越来越难。汇编语言现在只用作高级语言的附件通常只用在那些必须要求极高效率或非常紧凑或其他方式无法编写的小段代码里面。C是C语言的面向对象的超集正在嵌入式程序员中变得越来越流行。它的核心语言特性和C完全一样但是C提供了更好的数据抽象和面向对象形式的编程功能。这些新的特性对软件开发人员非常有帮助但是部分特性会降低可执行程序的性能所以C在大的开发队伍里用的最为普遍在那里只程序员的帮助要比程序效率的损失更为重要。Ada也是一种面向对象的语言。不过和C完全不同。Ada开始是美国国防部为了开发面向任务的军用软件而设计的。尽管它曾两次被接纳为国际标准(Ada和Ada)但Ada从没有在防务和航空工业领域之外获得足够的应用。即使是这些领地这几年也在逐渐丧失这是很不幸的事因为与C比起来Ada有很多特性可以简化嵌人式软件的开发工作。为这本书选择一种语言类似本书的同类书的作者面临的主要问题是采用哪一种语言来开展讨论。同时使用太多的语言只会使读者犯晕或者偏离更重要的问题。另一方面着眼点太窄又会使讨论变得不必要的学术化或者(对作者和出版商都很糟糕)限制了这本书的潜在市场。很明显C是所有关于嵌入式编程的书的核心这本书也不例外。超过一半的例子是用C编写的同时讨论也主要集中在和C有关的编程问题上。当然所有关于C编程的问题同样适用于C。另外我会在后面的例子里使用那些对嵌人式软件开发最有用的C特性。汇编语言在特定的环境下会加以讨论但是会尽量避免。换句话说我只在用别的方法无法完成一个特定的编程任务时才会考虑用汇编语言。我觉得这种混合使用C、C和汇编语言的安排方式更能反映现在的嵌入式软件开发过程并且在不久的将来还会是这样。我希望这种选择会使讨论能比较清晰可以提供给开发实际系统的人有用的信息并尽可能地适合更多的潜在的读者。关于硬件的一些说明关于编程的书籍必须要给出实际的例子。通常这些例子要能很容易地被感兴趣的读者试验。这就是说读者必须可以接触和作者完全一样的软件开发了具和硬件平台。很不幸在嵌入式编程的情况下这是不现实的。在大多数读者的平台上比如PC、Mac和Unix工作站上来运行任何示范程序都是没意义的。即使要选择一个标准的嵌入式平台地是很困难的。正如你已经知道的沿有“典型的”嵌人式系统这么一种东西。不管选了哪种硬件大多数读者都没办法接触到。但是尽管有这个相当重要的问题.我还是觉得选择一个参考平台来使用示例是很重要的。通过这样做我希望可以使所有的例子保持一致性以此来使整个讨论更加清楚。为了只使用一个硬件来说明尽可能多的问题我发现有必要选择一个中档的平台。这个硬件包含一个位处理器(Intel的EB注)、适量的存储器(KB的RAM和KB的ROM)还有一些常见的输入、输出和外设部件。我选用的电路板是Arcom控制系统公司制造的TargetEB。关于这块电路板和如何获取的信息可以参看附录“Arcom的TargetEB”。如果你可以接触到这个参考硬件的话。你将能原封不动地使用本书里的例子。否则你需要把示例代码移植到你能用到的嵌人式平台上面。为了这个目的我尽可能地使示例程序易于移植。可是读者必须要知道每一种嵌入式系统的硬件都是不一样的可能一些例子对地的硬件来说一点意义也没有比如把第六章“存储器”里提到的快闪存储器驱动程序移植到一个不带闪存的板子上就很没意义。不管怎样在第五章“接触硬件”里面我还会讲很多东西。但是首先我们还有很多软件问题需要讨论这就开始吧。注:Intel的EB处理器是专门为嵌入式系统修改了设计的的特殊版本原来的I是IBM的第一台个人计算机(PCXT)使用的处理器的一个继承者。它从来没有被实际使用。因为当IBM设计下一个型号(PCAT)的时候选择的是。尽管早期是失败的近几年来自Intel和AMD的却在嵌入式系统里面取得了巨大的成功。第二章你的第一个嵌入式程序注意!此机器不能摸也不能拿。它的内部在飞速地转动而且不断发出火花。它不是傻瓜摆弄的玩意儿。请把手放在口袋里站得远远地放松些看那闪烁的火花。KenOlson(肯奥尔森)DECC公司总裁在这一章里我们将通过一个例子直接进入嵌入式编程。这个例子看起来和其他大多数编程书籍开头的“Helloworld!”例子差不多。在讨论代码的时候我会说明选择特定代码段的理由并会指出依赖目标硬件的部分。本章只包含这第一个程序的源码在接下来的两章里我们会讨论如何创建可执行代码并运行它。HelloWorld!好像所有讲述编程的书都用同一个例子来开始就是在用户的屏幕上显示出“HelloWorld!”。总是使用这个例子可能有一点叫人厌烦可是它确实可以帮助读者迅速地接触到在编程环境中书写简单程序时的简便方法和可能的困难。就这个意义来说“HelloWorld!”可以作为检验编程语言和计算机平台的一个基准。不幸的是如果按照这个标准来说嵌入式系统可能是程序员工作中碰到的最难的计算机平台了。甚至在某些嵌入式系统中根本无法实现“HelloWorld!”程序。即使在那些可以实现这个程序的嵌入式系统里面文本字符串的输出也更像是目标的一部分而不是开始的一部分。本章内容:zHelloWorld!z闪烁程序z无限循环的作用你看“HelloWorld!”示例隐含的假设就是有一个可以打印字符串的输出设备。通常使用的是用户显示器上的一个窗口来完成这个功能。但是大多数的嵌入式系统并没有一个显示器或者类似的输出设备。即使是对那些有显示器的系统通常也需要用一小段嵌入式程序通过调用显示驱动程序来实现这个功能。这对一个嵌入式编程者来说绝对是一个相当具有挑战性的开端。看起来我们还是最好以一个小的容易实现并且高度可移植的联人式程序来开始这样的程序也不太会有编程错误。归根到底我这本书继续选用“HelloWorld!”。这个例子的原因是实现这个程序实在太简单了。这起码在读者的程序第一次就运行不起来的时候会去掉一个可能的原因即:错误不是因为代码里的缺陷:相反问题出在开发工具或者创建可执行程序的过程里面。嵌人式程序员在很大程度上必须要依靠自己的力量来工作。在开始一个新项目的时候除了他所熟悉的编程语言的语法他必须首先假定什么东西都没有运转起来甚至连标准库都没有就是类似printf()和scanf()的那些程序员常常依赖的辅助函数。实际上库例程常常作为编程语言的基本语法出现。可是这部分标准很难支持所有可能的计算平台并且常常被嵌入式系统编译器的制造商们所忽略。所以在这一章里你实际上将找不到一个真正的”HelloWorld!”程序相反我们假定在第一个例子中只可以使用最基本的C语言语法。随着本书的进一步深人我们会逐步向我们的指令系统里添加C的语法、标准库例程和一个等效的字符输出设备。然后在第九章“综合所学的知识”里面。我们才最终实现一个“HelloWorld!”程序。到那时候你将顺利地走上成为一个嵌入式系统编程专家的道路。闪烁程序(译注)在我的职业生涯中所进到的嵌入式系统都至少有一个可以被软件控制的注:当然闪烁的频率的选择完全是任意的、我选择Hz的原因是这可以根容易地用一个秒表来核对。简单地启动秒表计几次闪烁燃后停下秒表看嵌闪烁的次数是不是和经过的秒数相同如果需要更精确的话简单地多计几次闪烁就行了。译注:原文为德语。LED(发光二极管)。所以我用一个以Hz(注)频率闪烁LED(发光二极管)的程序来替代“HelloWorld!”。Hz就是每秒完整地开关一次。典型的情况是用来开关一个LED的代码通常只有几行C或汇编代码所以发生错误的机会也就很少。同时因为几平所有的嵌入式系统都有LED所以潜在的概念是非常容易移植的。LED闪烁程序的高层部分如下所示。这部分程序是与硬件无关的。不过它还要依赖分别使用和硬件有关的toggleLed()和delay()来改变LED的状态和控制计时。*******************************************************************Functionmain()*Description:BlinkthegreenLEDonceasecond*Notes:ThisouterloopishardwareindependentHowever*itdependsontwohardwaredependentfunctions*Returns:Thisroutinecontainsaninfiniteloop******************************************************************voidmain(void){while(){toggleLed(LEDGREEN)*ChangethestateoftheLED*delay()*Pauseformillisenconds*}}*main()*toggleLed在Arcom的电路板上有两个LED:一红一绿。每个LED的状态都被一个叫做端口IO锁存寄存器(缩写是PLTCH)的一个位来控制。这个寄存器和CPU在同一个芯片里它实际上包含了芯片外围的个IO引脚的锁存状态。这个引脚合在一起叫做端口。PLTCH寄存器里的每一位都和相应的IO引脚的电压联系到一起。比如第位控制送到绿色LED的电压:#defineLEDGREENX*ThegreenLEDiscontrolledbybit*通过修改这一位就可以改变相应外部引脚的电压从而改变了绿色LED的状态。如图所示当PLTCH的第位是的时候LED关第位是则LED打开。图Arcom电路板上的LEDPLTCH寄存器位于IO空间的一块特定内存里偏移为OxFFE。不幸的是x处理器的IO空间里的寄存器只能使用汇编语言指令in和out来操作。C语言没有内嵌的类似操作。最接近的替换函数是定义在面向PC平台的头文件dosh里的inport()和outport()。理想情况下我们可以包含这个头文件并从我们的嵌人式程序里调用这两个库函数。不过因为它们是DOS编程库的一部分我们必须要考虑到最坏的情况:它们在我们的系统上不工作。最起码的是我们在第一个程序里不应该依赖它们。下面列出了面向Arcom电路板并且不依赖库例程的toggleLed例程的实现。实际的算法是很简单的:读PLTCH寄存器的内容切换要控制的LED的相应位再把新的值写回寄存器。你会注意到尽管这个例程是用C书写的而实际的控制部分是用汇编语言实现的。这种简便的方法叫内嵌汇编语言(inlineassembly)。它一方面使程序员避开了复杂的C函数凋用和参数的传递和转换过程同时使她可以随意地使用汇编语言来工作(注)。#definePLTCHxFEE*TheoffsetthePLTCHregiser*注:不幸的是各种编译器的内嵌汇编语法是不一样的。我在示例中使用的是BorlandC编译器的格式。Borland的内嵌汇编格式非常好它主持在汇编行里引用用C代码定义的变量和常数。*******************************************************************FunctiontoggleLed()*Description:TogglethestateofoneorbothLEDs*Notes:ThisfunctionisspecifictoArcom’sTargetEBboard*Returns:Nonedefined******************************************************************voidtoggleLed(unsignedcharledMask){asm{movdx,PLTCH*Loadtheaddressoftheregister*inal,dx*Readthecontentoftheregister*movah,ledMask*MovetheledMaskintoaregister*xora,ah*Toggletherequestedbits*outdx,al*Writethenewregistercontents*}}*toggleLed()*delay()我们也需要在切换LED的动作之间实现一个半秒(ms)的延时。这是通过在如下所示的delay例程里使用忙等待技术实现的。这个例程接受以毫秒计的参数作为请求的延迟时间然后用这个参数和常数CYCLESPREMS相乘来得到为了延迟制定时间需要的while循环重复次数。*******************************************************************Functiondelay()*Description:Busywaitfortherequestednumberofmilliseconds*Notes:Thenumberofdecrementandtestcyclespermillisecond*wasdeterminedthroughtrialanderrorThisvalueis*dependentupontheprocessortypeandspeed*Returns:Nonedefined******************************************************************voiddelay(unsignedintnMilliseconds){#defineCYCLESPERMS*Numberofdecrementandtestcycles*unsignedlongnCycles=nMilliseconds*CYCLESPERMSwhile(nCycles)}}*delay()*与硬件相关的常数CYCLESPERMS

用户评论(0)

0/200

精彩专题

上传我的资料

每篇奖励 +2积分

资料评价:

/38
仅支持在线阅读

意见
反馈

立即扫码关注

爱问共享资料微信公众号

返回
顶部