1、第11章 嵌入式系统的测试、模拟与调试技术11.1 测试嵌入式系统11.3 模拟器调试技术11.2 测试方法11.4 试验工具和目标硬件的调试11.5 GDB调试技术11.1测试嵌入式系统11.1.1在宿主机上进行测试集成和测试嵌入式系统过程中,我们有两个计算系统,它们具有不同的CPU或微控制器以及硬件体系结构。一个系统是宿主系统或宿主机,另一个是目标系统或目标机。宿主系统通常是PC、手提式个人电脑或者工作站;目标系统是嵌入式系统的实际硬件,它处于开发阶段。嵌入式系统含三类代码:宿主相关代码、目标无关代码和目标相关代码。图11.1展示了一种开发过程中的测试系统,包含宿主系统、目标系统以及中间连
2、接的电路内置仿真器(In-CircuitEmulator,ICE),进行嵌入式系统硬件测试与调试。开发过程中的测试系统11.1.1在宿主机上进行测试嵌入式系统需要进行系统集成与测试,把所有的相关模块整合成一个完整的系统,这个过程中必须进行相应的测试和调试。测试的初始阶段一般在宿主机上完成。宿主机可以用来测试与设备无关的代码,还可以用来运行模拟器,如PROTEUS等仿真软件进行。当前很多嵌入式系统软件开发通过UART串口或USB接口作为宿主机与目标机的通信手段,采用打印运行消息的方式进行软件测试与调试工作。11.1.2可测试性的设计嵌入式系统的开发人员需要设计硬件和软件的可测试性。硬件的可测试性
3、意味着在设计过程中配置输入端口和输出端口,使硬件可在组装好后检测故障。开发人员要考虑软件组件的可测试性和需求。可测试性是在测试过程中可以控制和观察组件的状态和输出的程度。软件的可测试性意味着一种设计,使软件可以使用数据集测试系统,或自动测试组件。该设计应该允许使用测试方法和测试资源。更高的可测试性使得测试的便利性好于较低程度的可测试性。嵌入式系统设计应该支持可测试性,满足系统验证的需要。11.1.3硬件检查在PCB电路完成印刷制板后,需要进行自动贴片或手动焊接元器件。因为,电路设计可能存在设计错误的问题,焊接或贴片过程中也可能存在漏焊、虚焊、错焊等各种问题。因此,我们都需要对电路板的硬件进行检
4、查。硬件检查可以进行静态检查和动态检查。静态检查是在不通电的情况下对线路板线路与元器件进行的检查。主要参照原理图与PCB,逐个模块检查各个元器件是否正确焊接,是否存在漏焊、虚焊等情况。同时一般需要测试线路板电源是否有对地短路等情况。动态检查是在通电后,通过万用表检测各个电源电压是否正常,使用示波器等硬件工具检查各类波形是否满足要求等。有时,也经常需要软件配合验证。最小系统法是测试和调试嵌入式系统问题的常用方法。硬件检查时,我们一般首先检测晶振、电源、主芯片与复位电路,而后逐步检测存储模块,再逐一展开检测各个外围接口与模块。11.1.4自测的设计嵌入式软件和硬件测试包含诸多内容,如硬件测试可能包
5、括目标硬件的调试,处理器的测试,外部设备的测试,存储器和闪存等测试内容,如软件测试可能包括测试GUI界面,测试任务的代码,测试与其他计算机系统通信的代码,测试显示等接口代码等测试内容。测试不仅是测试人员的事情,亦需要开发工程师的支持。实际在项目开发过程中,开发工程师始终在应用各种软硬件测试手段验证嵌入式开发代码的质量,进行自测的设计。测试嵌入式系统包括测试和调试嵌入式系统的硬件和软件,自测意味着对系统所有预期的功能执行测试。开发人员编写自测程序,自测程序可以测试系统的指定功能。有些测试程序会一同集成到嵌入式系统中,如打印机替换墨盒时启动自测程序打印一页测试页。11.1.5测试工具用于辅助嵌入式
6、系统测试的工具很多,如用于硬件调试的工具包括发光二极管、RS-232串口、仿真器、万用表、信号发生器、直流稳压电源、示波器和逻辑分析仪等。除此之外,下面对几类比较有用的有关嵌入式系统的测试工具加以介绍和分析。1、内存分析工具在嵌入式系统中,内存约束通常是有限的。内存分析工具用来处理在动态内存分配中存在的缺陷。当动态内存被错误地分配后,通常难以再现,这种失效难以追踪,使用内存分析工具可以避免这类缺陷进入功能测试阶段。目前有软件和硬件两类内存分析工具。基于软件的内存分析工具可能会对代码的性能造成很大的影响,从而严重影响实时操作。基于硬件的内存分析工具价格昂贵,而且只能在工具所限定的运行环境中使用。
7、11.1.5测试工具2、性能分析工具在嵌入式系统中,程序的性能通常是非常重要的。经常会有这样的要求,在特定时间内处理一个中断或生成具有特定定时要求的一帧。性能分析工具会提供有关的数据,从而可以决定如何优化软件,获得更好的时间性能。对于大多数应用来说,大部分执行时间用在相对少量的代码上,费时的代码估计占所有软件总量的5%20%,性能分析工具不仅能指出哪些例程花费时间,而且与调试工具联合使用可以引导开发人员查看需要优化的特定函数,性能分析工具还可以引导开发人员发现在系统调用中存在的错误及程序结构上的缺陷。11.1.5测试工具3、GUI测试工具很多嵌入式应用带有某种形式的图形用户界面进行交互,有些系
8、统性能测试根据用户输入响应时间进行。GUI测试工具可以作为脚本工具在开发环境中运行测试用例,其功能包括对操作的记录和回放、抓取屏幕显示供以后分析和比较、设置和管理测试过程等。4、覆盖分析工具在进行白盒测试时,可以使用代码覆盖分析工具追踪哪些代码被执行过,测试人员对结果数据加以总结,确定哪些代码被执行过,哪些代码被遗漏了。覆盖分析工具一般会提供功能覆盖、分支覆盖和条件覆盖的信息。11.2 测试方法系统的测试有两种方法:白盒测试和黑盒测试。白盒测试意味着使用测试数据集或用例来测试系统的内部。在集成或单独的系统中为每个单元执行测试。测试过程会测试数据流图、控制流图、每个决策块和线程的分支中语句的覆盖
9、面。白盒测试也称结构测试或逻辑驱动测试,它是按照程序内部的结构测试程序,通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进行,检验程序中的每条通路是否都能按预定要求正确工作。11.2 测试方法第二种方法是黑盒测试。这意味着在集成或单独的系统中通过测试数据集或用例,测试系统单元的功能。开发人员设计-组单元、线程或任务的测试用例和过程。给测试人员提供系统的测试设计技术。黑盒测试不考虑系统的内部,而考虑功能的更高层面。黑盒测试也称功能测试,它是通过测试来检测每个功能是否都能正常使用。在测试地,把程序看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,在程序接口进行测试,它
10、只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据而产生正确的输出信息。黑盒测试着眼于程序外部结构,不考虑内部逻辑结构,主要针对软件界面和软件功能进行测试。11.2.1错误跟踪开发人员设计了错误跟踪软件。这个软件记录了系统测试期间报告的软件错误。更新数据库,记录有关错误的信息。错误跟踪系统(BTS)是一个应用程序,在开发阶段负责追踪测试系统的过程中发现的所有错误。管理软件项目的应用程序可能集成了BTS,BTS可以加快无错软件的开发过程。11.2.2单元测试开发人员将软件划分为若干单元,以进行白盒测试。单元测试意味着测试程序的一个单元。一个单元可以是多任务系统中的任
11、务、线程或进程、方法、函数、过程、例程或中断服务例程。单元也可能是一个类、接口或对象。单元测试的好处1、单元测试不但会使你的工作完成得更轻松,而且会令你的设计会变得更好,甚至大大减少你花在调试上面的时间;2、提高代码质量;3、减少bug,快速定位bug;4、放心地修改、重构。11.2.2单元测试写单元测试要注意什么:1,不能只测试一条正确执行路径,要考虑到所有可能的情况;2,要确保所有测试都能够通过,避免间接损害;3,如果一个函数复杂到无法单测,那就说明模块的抽象有问题。间接损害:在整个系统中,当某一部分加入了新特性,或者修复了一个bug之后,给系统的其他部分引入了一个新的BUG(或者损害)。
12、如果无视这种损害并且继续开发的话,那么将可能带来一个很危险的问题,最后可能会导致整个系统崩溃,并且没人能够修复。11.2.3回归测试开发系统时,会保存测试,开发系统的一个新版本时,会应用以前保存的测试,这就是所谓的回归测试。回归测试允许跟踪开发早期版本时发现的错误。当新版本有了新规范时,回归测试仅有助于测试旧错误。新规范版本需要跟踪修改过程中因添加新规范而产生的错误。做回归测试的好处如下:1、自动回归测试将大幅度降低系统测试、维护升级等阶段的成本,回归测试作为软件生命周期的一个组成部分,在整个软件测试过程中占有很大的工作量比重,软件开发的各个阶段都可以进行多次回归测试。2、在渐进和快速迭代开发
13、中,新版本的连续发布使回归测试进行的更加频繁,而在极端编程方法中,更是要求每天都进行若干次回归测试;因此,通过选择正确的回归测试策略来改进回归测试的效率和有效性是非常有意义的。11.2.3回归测试做回归测试的测试用例的选择:1)对于一个软件开发项目来说,项目的测试组在实施测试的过程中会将所开发的测试用例保存到“测试用例库”中,并对其进行维护和管理。当得到一个软件的基线版本时,用于基线版本测试的所有测试用例就形成了基线测试用例库。在需要进行回归测试的时候,就可以根据所选择的回归测试策略,从基线测试用例库中提取合适的测试用例组成回归测试包,通过运行回归测试包来实现回归测试。保存在基线测试用例库中的
14、测试用例可能是自动测试脚本,也有可能是测试用例的手工实现过程。11.2.3回归测试2)同时测试用例的维护是一个不间断的过程,通常可以将软件开发的基线作为基准,维护的主要内容包括下述几个方面,(1)删除过时的测试用例:因为需求的改变等原因可能会使一个基线测试用例不再适合被测试系统,这些测试用例就会过时,例如,某个变量的界限发生了改变,原来针对边界值的测试就无法完成对新边界测试。所以,在软件的每次修改后都应进行相应的过时测试用例的删除。(2)改进不受控制的测试用例:随着软件项目的进展,测试用例库中的用例会不断增加,其中会出现一些对输入或运行状态十分敏感的测试用例,这些测试不容易重复且结果难以控制,
15、会影响回归测试的效率,需要进行改进,使其达到可重复和可控制的要求。11.2.3回归测试(3)删除冗余的测试用例:如果存在两个或者更多个测试用例针对一组相同的输入和输出进行测试,那么这些测试用例是冗余的。冗余测试用例的存在降低了回归测试的效率,所以需要定期的整理测试用例库,并将冗余的用例删除掉。(4)增添新的测试用例:如果某个程序段、构件或关键的接口在现有的测试中没有被测试,那么应该开发新测试用例重新对其进行测试,并将新开发的测试用例合并到基线测试包中,通过对测试用例库的维护不仅改善了测试用例的可用性,而且也提高了测试库的可信性,同时还可以将一个基线测试用例库的效率和效用保持在一个较高的级别上。
16、11.2.4选择测试用例测试用例是一组变量、条件或测试套件。开发人员使用测试测试用例是一组变量、条件或测试套件。开发人员使用测试用例来测试一个程序、系统或程序的单元。测试用例允许测试应用例来测试一个程序、系统或程序的单元。测试用例允许测试应用程序。测试用例有两种类型用程序。测试用例有两种类型:正式和非正式的。正式和非正式的。1.1.非正式的测试用例是没有任何正式需求的测试用例。接受类型非正式的测试用例是没有任何正式需求的测试用例。接受类型类似的程序中正常的操作,就构成了非正式测试用例的基础。非类似的程序中正常的操作,就构成了非正式测试用例的基础。非正式测试用例的一个例子是测试交付包和数据帧的网
17、络。正式测试用例的一个例子是测试交付包和数据帧的网络。2.2.正式的测试用例是有正式需求的测试用例。在程序的正常操作正式的测试用例是有正式需求的测试用例。在程序的正常操作中可接受的数据传输率和装配网络堆栈所需的时间,就构成了网中可接受的数据传输率和装配网络堆栈所需的时间,就构成了网络系统的正式测试用例的基础。络系统的正式测试用例的基础。11.2.5功能测试功能测试(功能测试(FunctionalTestingFunctionalTesting)是测试系统所需的功能。列)是测试系统所需的功能。列出所有功能,并逐一进行功能测试。出所有功能,并逐一进行功能测试。功能测试也称为行为测试(功能测试也称为
18、行为测试(BehavioralTestingBehavioralTesting),根据产品),根据产品特性、操作描述和用户方案,测试一个产品的特性和可操作行特性、操作描述和用户方案,测试一个产品的特性和可操作行为以确定它们满足设计需求。本地化软件的功能测试,用于验为以确定它们满足设计需求。本地化软件的功能测试,用于验证应用程序或网站对目标用户能正确工作。使用适当的平台、证应用程序或网站对目标用户能正确工作。使用适当的平台、浏览器和测试脚本,以保证目标用户的体验将足够好,就像应浏览器和测试脚本,以保证目标用户的体验将足够好,就像应用程序是专门为该市场开发的一样。功能测试是为了确保程序用程序是专门
19、为该市场开发的一样。功能测试是为了确保程序以期望的方式运行而按功能要求对软件进行的测试,通过对一以期望的方式运行而按功能要求对软件进行的测试,通过对一个系统的所有的特性和功能都进行测试确保符合需求和规范。个系统的所有的特性和功能都进行测试确保符合需求和规范。功能测试是一种黑盒测试或数据驱动测试,只需考虑需要功能测试是一种黑盒测试或数据驱动测试,只需考虑需要测试的各个功能,不需要考虑整个软件的内部结构及代码。一测试的各个功能,不需要考虑整个软件的内部结构及代码。一般从软件产品的界面、架构出发,按照需求编写出来的测试用般从软件产品的界面、架构出发,按照需求编写出来的测试用例,输入数据在预期结果和实
20、际结果之间进行评测,进而提出例,输入数据在预期结果和实际结果之间进行评测,进而提出更加使产品达到用户使用的要求。更加使产品达到用户使用的要求。11.2.6覆盖测试列出所有功能测试中的所有代码块、决策块或循环。功能测列出所有功能测试中的所有代码块、决策块或循环。功能测试的代码覆盖测试意味着找出已经测试过的、无错的代码块、决试的代码覆盖测试意味着找出已经测试过的、无错的代码块、决策块、循环或任务。代码覆盖的研究有助于消除特定应用程序不策块、循环或任务。代码覆盖的研究有助于消除特定应用程序不需要的多余代码和功能。它支持可扩展系统。需要的多余代码和功能。它支持可扩展系统。覆盖测试是衡量测试质量的一个重
21、要指标。在对一个软件产覆盖测试是衡量测试质量的一个重要指标。在对一个软件产品进行了单元测试、组装测试、集成测试以及接口测试等繁多的品进行了单元测试、组装测试、集成测试以及接口测试等繁多的测试之后,我们能不能就此对软件的质量产生一定的信心?这就测试之后,我们能不能就此对软件的质量产生一定的信心?这就需要我们对测试的质量进行考察。如果测试仅覆盖了代码的一小需要我们对测试的质量进行考察。如果测试仅覆盖了代码的一小部分,那么不管我们写了多少测试用例,我们也不能相信软件质部分,那么不管我们写了多少测试用例,我们也不能相信软件质量是有保证的。相反,如果测试覆盖到了软件的绝大部分代码,量是有保证的。相反,如
22、果测试覆盖到了软件的绝大部分代码,我们就能对软件的质量有一个合理的信心。我们就能对软件的质量有一个合理的信心。11.2.6覆盖测试覆盖面的度量方式覆盖面的度量方式函数覆盖函数覆盖函数覆盖(函数覆盖(FunctionCoverageFunctionCoverage),执行到程序中的每一个函数),执行到程序中的每一个函数(或副程式)。(或副程式)。语句覆盖语句覆盖这是最常用也是最常见的一种覆盖方式,就是度量被测代码中每这是最常用也是最常见的一种覆盖方式,就是度量被测代码中每个可执行语句是否被执行到了。这里说的是个可执行语句是否被执行到了。这里说的是“可执行语句可执行语句”,因,因此就不会包括像此就
23、不会包括像C+C+的头文件声明,代码注释,空行,等等。只的头文件声明,代码注释,空行,等等。只统计能够执行的代码被执行了多少行。需要注意的是,单独一行统计能够执行的代码被执行了多少行。需要注意的是,单独一行的花括号的花括号也常常被统计进去。语句覆盖常常被人指责为也常常被统计进去。语句覆盖常常被人指责为“最弱最弱的覆盖的覆盖”,它只管覆盖代码中的执行语句,却不考虑各种分支的,它只管覆盖代码中的执行语句,却不考虑各种分支的组合等等。假如你的上司只要求你达到语句覆盖,那么你可以省组合等等。假如你的上司只要求你达到语句覆盖,那么你可以省下很多功夫,但是,换来的确实测试效果的不明显,很难更多地下很多功夫
24、,但是,换来的确实测试效果的不明显,很难更多地发现代码中的问题。发现代码中的问题。11.2.6覆盖测试判断覆盖判断覆盖判断覆盖判断覆盖(DecisionCoverage)(DecisionCoverage),又称分支覆盖,又称分支覆盖(BranchCoverage)(BranchCoverage),所有边界覆盖所有边界覆盖(All-EdgesCoverage)(All-EdgesCoverage),基本路径覆盖,基本路径覆盖(BasicPath(BasicPathCoverage)Coverage),判定路径覆盖,判定路径覆盖(Decision-Decision-Path)(Decision-
25、Decision-Path)。它度量程序。它度量程序中每一个判定的分支是否都被测试到了。这句话是需要进一步理中每一个判定的分支是否都被测试到了。这句话是需要进一步理解的,应该非常容易和下面说到的条件覆盖混淆。因此我们直接解的,应该非常容易和下面说到的条件覆盖混淆。因此我们直接介绍第三种覆盖方式,然后和判定覆盖一起来对比,就明白两者介绍第三种覆盖方式,然后和判定覆盖一起来对比,就明白两者是怎么回事了。是怎么回事了。条件覆盖条件覆盖条件覆盖条件覆盖(ConditionCoverage)(ConditionCoverage),它度量判定中的每个子表达式结,它度量判定中的每个子表达式结果果truetr
26、ue和和falsefalse是否被测试到了。是否被测试到了。11.2.6覆盖测试路径覆盖路径覆盖路径覆盖路径覆盖(PathCoverage)(PathCoverage),又称断言覆盖,又称断言覆盖(PredicateCoverage)(PredicateCoverage)。它。它度量了是否函数的每一个分支都被执行了。这句话也非常好理解,度量了是否函数的每一个分支都被执行了。这句话也非常好理解,就是所有可能的分支都执行一遍,有多个分支嵌套时,需要对多就是所有可能的分支都执行一遍,有多个分支嵌套时,需要对多个分支进行排列组合,可想而知,测试路径随着分支的数量指数个分支进行排列组合,可想而知,测试路
27、径随着分支的数量指数级别增加。级别增加。11.2.7测试嵌入式软件IBM软件组指定了测试系统的6个方面:(1)软件单元测试(2)软件集成测试(3)软件验证测试(4)系统单元测试(5)系统集成测试(6)系统验证测试11.2.7测试嵌入式软件在开发阶段,会执行通用的测试迭代周期。其步骤如下在开发阶段,会执行通用的测试迭代周期。其步骤如下:1.1.称为颗粒单元测试称为颗粒单元测试(GUT)(GUT)的单元或子单元的单元或子单元:设计人员指定了设计人员指定了称为颗粒的子单元,用于测试。准备测试的颗粒时,要指称为颗粒的子单元,用于测试。准备测试的颗粒时,要指定输入点或控制点,输出控制点,来收集测试结果。
28、定输入点或控制点,输出控制点,来收集测试结果。2.2.测试用例的规范测试用例的规范:为每个为每个GUTGUT指定测试用例。指定测试用例。3.3.部署和执行测试部署和执行测试:测试部署在被测试的软件中,执行测试。测试部署在被测试的软件中,执行测试。4.4.观察测试结果观察测试结果:观察输出控制点的值、顺序、状态、变量观察输出控制点的值、顺序、状态、变量的时序,以收集测试结果。的时序,以收集测试结果。5.5.迭代迭代:迭代观察到的测试结果,以改善系统,使其正确无迭代观察到的测试结果,以改善系统,使其正确无误。误。11.2.8性能测试在系统中需要测试性能。开发人员定义了系统的性能指标,测试预期的在系
29、统中需要测试性能。开发人员定义了系统的性能指标,测试预期的性能是否匹配测量的结果。性能是否匹配测量的结果。1 1、性能测试分类:、性能测试分类:压力测试(压力测试(StressTestingStressTesting):对系统不断施加压力的测试,是通过确定一):对系统不断施加压力的测试,是通过确定一个系统的瓶颈或不能接收用户请求的性能点,来获得系统能够提供的最个系统的瓶颈或不能接收用户请求的性能点,来获得系统能够提供的最大服务级别的测试。大服务级别的测试。负载测试(负载测试(LoadTestLoadTest):通过在被测系统上增加压力,直到性能指标达):通过在被测系统上增加压力,直到性能指标达
30、到极限(响应时间超过预定指标或者某种资源利用率达到饱和),负载到极限(响应时间超过预定指标或者某种资源利用率达到饱和),负载测试可以用来找到系统的处理极限,为系统调优提供依据。测试可以用来找到系统的处理极限,为系统调优提供依据。并发测试:用来测试多用户同时访问系统(或模块,或数据,或做同一并发测试:用来测试多用户同时访问系统(或模块,或数据,或做同一种业务)时是否存在性能问题。种业务)时是否存在性能问题。大数据量测试:针对系统新建记录或统计查询等业务进行的大数据量测大数据量测试:针对系统新建记录或统计查询等业务进行的大数据量测试,或针对大量存量数据而进行的性能测试。试,或针对大量存量数据而进行
31、的性能测试。可靠性测试:测试系统在一定压力下长时间运行是否稳定可靠,用于验可靠性测试:测试系统在一定压力下长时间运行是否稳定可靠,用于验证系统是否可以长时间对外提供稳定可靠的服务。证系统是否可以长时间对外提供稳定可靠的服务。11.2.8性能测试2 2、性能调优基础:、性能调优基础:性能测试工程师的主要任务是发现并定位性能问题,对于问性能测试工程师的主要任务是发现并定位性能问题,对于问题解决,通常由性能测试工程师、开发人员、系统管理员和题解决,通常由性能测试工程师、开发人员、系统管理员和DBADBA等来共同完成。性能调优可以从以下一些方面考虑:等来共同完成。性能调优可以从以下一些方面考虑:应用程
32、序代码:很多性能问题由程序代码导致,所以可以检应用程序代码:很多性能问题由程序代码导致,所以可以检查相关模块代码,确认是否有性能瓶颈。查相关模块代码,确认是否有性能瓶颈。数据库配置:数据库配置可能会导致系统运行缓慢,对于数据库配置:数据库配置可能会导致系统运行缓慢,对于oracleoracle等大型数据库,可能需要等大型数据库,可能需要DBADBA进行正确的参数调整以进行正确的参数调整以提供更好服务。提供更好服务。硬件设置:磁盘硬件设置:磁盘I/OI/O速度、内存大小等都可能影响系统性能速度、内存大小等都可能影响系统性能网络:网络负载过重会导致网络延迟或网络冲突。网络:网络负载过重会导致网络延
33、迟或网络冲突。操作系统配置:操作系统配置不合理也可能引发性能问题。操作系统配置:操作系统配置不合理也可能引发性能问题。11.3模拟器调试技术11.3.1模拟器模拟器用到了目标处理器或微控制器,以及宿主处理器上的目标系统体系结构的知识。模拟器首先对代码进行交叉编译,并将代码加载到宿主系统的RAM中。目标系统处理器寄存器的行为也会在RAM中进行模拟。它使用链接器和定位器将经过交叉编译的代码移植到RAM中,并像在实际目标系统上一样运行代码。宿主系统是PC、手提式个人电脑或者工作站,通常工作在Windows下。模拟器软件也可以模拟硬件单元,如仿真器、外围设备、网络和宿主机(PC、工作站或手提式个人电脑
34、)上的输入/输出设备。模拟器与特定的目标系统保持独立。它在使用某种特殊处理器、微控制器或设备的系统的应用软件开发阶段非常有用,使得在宿主系统的RAM中就可以获得目标系统RAM、外围设备、网络和输入/输出设备的代码期望的结果。11.3.2模拟器的特性一般的模拟器大都运行在Windows环境的PC上。模拟器一般具有以下特性:(1)定义了用于目标系统的处理器或者处理设备系列及其不同型号。(2)监控执行过程进行到每一步时,源代码部分的详细信息(使用标签和符号参数表示)。(3)提供执行过程进行到每一步时,已定义目标系统中RAM和端口(模拟)状态的详细信息。(4)提供已定义系统中外围设备(模拟,假设即将连
35、接)状态的详细信息。(5)提供执行过程进行到每一步或者每一个模块时,寄存器的详细信息。它还监视系统响应并确定吞吐量。11.3.2模拟器的特性(6)显示屏上的窗口提供了以下内容:(a)已定义微控制器系统的堆栈、设备和端口(模拟)状态的详细信息。(b)执行过程中程序流程的跟踪信息。跟踪程序计数器和处理器寄存器的输出内容。它是汇编语言程序调试的重要工具。应用软件的跟踪是指函数逐步执行时所选变量的输出。跟踪示波器在程序执行时,显示X轴上的时间和Y轴上所选变量的变化关系(跟踪示波器是一个工具模块,用于跟踪随X轴时间的变化,模块和任务的变化。也可以根据期望的时间比例规范生成一个动作列表)。11.3.2模拟
36、器的特性(7)在显示屏上提供帮助窗口。帮助窗口给出了鼠标光标所指的当前命令的具体含义。(8)当从键盘输入,或者从菜单中选择模拟器命令时,监控这些命令的详细信息。(9)结合了用于C语言表达式和汇编语言助记符(表达式)的汇编器、反汇编器、用户定义的击键或者鼠标选择的宏和解释器。因此,它可以测试汇编代码。用户定义的击键宏非常有用。例如,定义击键为1,用于提供端口n上的一个特定的输入字节和特定的RAM地址字节。11.3.2模拟器的特性(10)支持条件(可达8、16或者32个条件)和非条件断点。它具有指令执行确定次数之后中止代码的功能。断点和跟踪都是重要的测试和调试工具(11)易于实现内部外围设备和延迟
37、的同步。(12)使用抢占式RTOS调度程序支持高优先级任务。(13)模拟来自中断、定时器、端口和外围设备的输入。从而可以使用它们来测试代码。(14)支持网络驱动器和设备驱动器。11.3.3模拟器的局限性模拟器无法解决时序问题和硬件相关问题。目标处理器的速度可能无法完全映射为宿主机处理器的速度,用于计算目标机上的时间响应、输出时刻和吞吐量。模拟器可能不会显示共享数据的错误,因为它们仅由某些特定情形下的中断引起。例如4个寄存器中的长字只部分加载,则会立即发生中断模拟器在模拟嵌入了IP或者ASIC的目标系统时可能会失效。这种情况下,ASIC或IP内核生产商通常会提供一种可选的调试工具。例如,用于AR
38、M7或ARM9处理器的ICE可在宿主处理器和系统上模拟ARM的功能11.3.3模拟器的局限性模拟器可能无法考虑到存在的内部设备。例如,目标系统可能使用了一个Java加速器,但是宿主系统却没有。模拟器无法考虑可移植性的问题。例如,目标系统的RAM和没有流水线的处理器之间可能使用8位的数据总线,而宿主系统具有流水线处理器和32位的总线。11.4试验工具和目标硬件的调试11.4.1电路内置仿真器(ICE)ICE可以代替目标电路,为在单一系统上(而不是多目标系统)开发不同的应用程序提供更大的灵活性和便利性。ICE是用于仿真目标系统的电路,它与特定的目标系统和处理器无关,可以在大多数目标系统的开发阶段中
39、使用,这些目标系统将来和特定的微控制器芯片结合。它可以独立工作,也可通过串行线连接到PC上工作。它是去掉了目标微处理器或微控制器的目标电路。ICE是目标电路中微处理器的一种仿真器,宿主系统可以通过串行线连接到ICE进行调试。它可以使用目标电路的其余部分在开发阶段仿真不同型号的微控制器系列。ICE和仿真器有何区别呢?目标系统使用由微控制器和处理器自身组成的电路。仿真器可以模拟具有扩展存储器的目标系统,并在编辑测试调试过程中具有代码下载能力。ICE仿真处理器或微控制器。它使用另外一个带卡的电路,这个卡通过插槽和目标处理器(或电路)相连。11.4.1电路内置仿真器(ICE)ICE和支持硬件包(bac
40、ksupporthardwarepackage)有许多子单元,下表将其列出并进行了解释。支持硬件包和ICE子单元11.4.1电路内置仿真器(ICE)ICE由以下部分组成:(1)带有扁平电缆的仿真器容器,它延伸到目标系统的处理器或微控制器插槽上。后面会将处理器IC插到该插槽上。然后,就可以测试目标系统(记住,该系统对最终的嵌入式系统是一对一的复制)。为避免由于电缆过长而产生的耦合电容的影响,使用的电缆必须尽可能短。该容器模仿了目标系统的微控制器或者处理器。(2)该容器串联到计算机的COMRS232C端口上。通过这个端口,该容器从计算机获得下载代码。用于仿真器的计算机程序对寄存器和存储单元进行完全
41、监控。该容器在它的基本电路和扁平电缆跳线之间存在一些卡。这些卡的相互替换使得将ICE用于其他型号的处理器成为可能。11.4.1电路内置仿真器(ICE)嵌入ICE的处理器自身有哪些特点?ARM7和ARM9处理器的一个特性是都有ICE子单元。这有助于调试目标硬件。ICE或者仿真器在开发阶段结束后就不再使用。通过复制使用ICB开发的代码构成实际电路。该电路在和目标处理器建立连接之后,由使用的处理器、必要的存储器芯片、按键和显示单元或者其他外设组成。它工作起来应该和我们在开发阶段后期,使用仿真器或者ICE完成的工作同样精确和完善。仿真器对于完成最终目标系统之前进行的系统开发非常有用。visionICE
42、I是一种具有网络性能的ICE。它结合了10/100MbpsEthernet的连接性。这使得ICB在局域网上也可以使用。这样做的好处是可以进行远程调试。它可以连接到目标系统的串口。ROM仿真器仅仿真了ROM。目标系统通过ROM插槽连接,同时连接到计算机。11.4.2逻辑分析仪使用了模拟器、ICE以及ROM中的调试代码之后,我们在调试的最后阶段使用故障检测硬件诊断工具,该工具可以记录(1)随时间变化的状态信息(2)随其他状态变化的状态信息。逻辑分析仪是一款功能强大的工具,它通过来自总线和端口的多个输入线路(例如,24或者48),可以收集多路信号,还可以记录多个总线事务(大约128个或者更多)。它在
43、监视器(屏幕)上显示这些内容,用来调试实时触发条件。由于指令执行关系到参考信号,它还可有助于顺序查找信号。总线信号或者时钟信号都可以作为参考信号。11.4.2逻辑分析仪第一种模式下,分析仪以时间函数的方式收集逻辑状态,将这些状态存储到存储器中,并在屏幕上显示。分析仪有多个输入线路(24、48或者更多),可以同步连续地跟踪多路信号。连接来自系统和IO总线、端口和外围设备的线路,同时收集多个总线事务(大约128个或者更多)的持续时间。稍后,它可以使用该工具在计算机显示器(屏)上显示每个线路的每个事务,也可以打印显示内容。每个输入线路的相位差也可以提供重要的信息。逻辑分析仪还可以调试实时触发条件。在
44、执行指令时,帮助顺序查找总线信号和端口信号状态。某些特殊的逻辑分析仪还可以在需要时提供模拟测量。11.4.2逻辑分析仪第二种模式下,将总线连接到逻辑分析仪的探测管脚,分析仪给出所有信号在时钟沿捕获的状态。用户可以定义捕获状态的触发点。观察到非法操作码、处理器位于某个特定的开始地址或者输出了某个端口字节都可以定义为触发点。11.5GDB调试技术11.5.1GDB调试应用程序概述GDB是GNU开源组织发布的一款调试器,提供了丰富的功能。gdb调试器不仅能调试普通的应用程序,还可以调试正在运行的进程和线程,甚至Linux内核。gdb是一个开源的调试器,不仅能调试C语言编写的代码,还可以调试Ada、C
45、+、Java、Pascal等语言编写的程序。GDB支持Linux、Windows等多种平台,可以非常方便地调试各种类型的程序。不过,GDB最大的不足是个命令行的工具,对初学者来说入门比较麻烦,尤其是用惯了VisualC+之类的图形化调试器的开发人员。11.5.1GDB调试应用程序概述它主要帮助你完成下面四个方面的功能:1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)3、当程序被停住时,可以检查此时你的程序中所发生的事。4、你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。11.5.2基本调试
46、技术本节通过一个实例来具体讲解GDB在Linux环境下的各种调试技术1、查看源代码查看源代码11.5.2基本调试技术本节通过一个实例来具体讲解GDB在Linux环境下的各种调试技术2、断点管理调试过程中最常用的就是断点。断点的意思是给程序代码某处调试过程中最常用的就是断点。断点的意思是给程序代码某处做个标记,当程序运行到此处的时候就会停下来,等待用户的操作。做个标记,当程序运行到此处的时候就会停下来,等待用户的操作。断点通常被设置在程序出错的前面几行,当程序运行到断点以后,断点通常被设置在程序出错的前面几行,当程序运行到断点以后,程序员通过单步运行程序,并且查看相关变量状态,可以定位错误。程序
47、员通过单步运行程序,并且查看相关变量状态,可以定位错误。看了程序的代码,感觉第6行代码可能有点问题,现在就需要设置一个断点,让程序停在第6行之前。说明我设置的这个断点是第一个断点,断点所在内存地址为0 x80484c8,它在文件test.c的第6行11.5.2基本调试技术本节通过一个实例来具体讲解GDB在Linux环境下的各种调试技术2、断点管理这个断点的含义是,如果n的值为6,则程序运行到第7行停止调试过程中需要显示设置的断点信息,可以使用infobreakpoints命令11.5.2基本调试技术本节通过一个实例来具体讲解GDB在Linux环境下的各种调试技术2、断点管理断点失效方法断点失效
48、方法可以看到,第一个断点的Enb变为n了,表示该断点已经无效了,如果需要恢复,可以使用enable命令。这里需要注意的是,disable后面的参数为断点的编号,而不是行号。11.5.2基本调试技术本节通过一个实例来具体讲解GDB在Linux环境下的各种调试技术2、断点管理断点删除方法断点删除方法clear命令后面的参数为设置断点的行号,clear后面参数还可以加设置断点的函数名。delete命令后面的参数为断点的编号;可以一次删除多个断点,断点编号之间用空格隔开;如果delete后没有参数,默认删除所有断点,会给出提示选择是否操作。11.5.2基本调试技术3、开始程序调试11.5.2基本调试技
49、术3、开始程序调试11.5.2基本调试技术3、开始程序调试还有nexti和stepi命令,这两个是单步执行一条机器指令,比如(i=0;in;i+)这条语句需要输入多个nexti才能执行完;两个的区别和上面相同。quit,退出gdb调试,如果调试中想要退出,可以直接输入该命令,会出现提示选择是否退出。kill命令,结束当前程序的调试,(不会退出gdb)。11.5.3printk打印调试信息printk()是内核提供的一个打印函数,作用是向终端打印信息,是一种最常用的Linux内核调试技术。通常内核使用printk()函数打印提示信息和出错信息。在内核调试中最普遍的办法是使用printk()函数在
50、可能出错的地方打印,帮助调试。内核使用printk()函数而不使用printf()函数,原因是printf()函数是由glibc库提供的,Linux内核的函数是不能依赖任何程序库的,否则制作出的映像文件就无法被加载。printk()函数的用法与printf()函数一致。不同的是,printf()函数是可被中断的,而printk()函数不会被中断。实际使用的效果是,printk()函数输出的内容不会被其他程序打断,保证了输出的完整性。11.5.3printk打印调试信息printk()函数提供了打印内容的优先级管理,在Linux内核中定义了几种优先级:11.5.3printk打印调试信息这几种事