调试及调试工具
考试要求: 掌握     
知识路径:  > 嵌入式系统软件基础知识  > 嵌入式系统程序设计  > 嵌入式软件开发环境  > 编辑器、交叉工具链(编译器、链接器、调试器)、模拟器


 
       在开发嵌入式软件时,交叉调试是必不可少的一步。嵌入式软件的特点决定了其调试具有如下特点:
       (1)对于通用的计算机,调试器与被调试程序一般位于同一台计算机上,操作系统也相同,调试器进程通过操作系统提供的调用接口来控制被调试的进程。而在嵌入式系统中,由于目标机的资源有限,调试器和被调试程序运行在不同的机器上。调试器主要运行在宿主机上,而被调试程序则运行在目标机上。
       (2)调试器通过某种通信方式与目标机建立联系。通信方式可以是串口、并口、网络、JTAG或专用的通信方式。
       (3)在目标机上一般有调试器的某种代理,这种代理能配合调试器一起完成对目标机上所运行程序的调试。这种代理可以是某种软件,也可以是支持调试的某种硬件。
       总之,在交叉调试方式下,调试器和被调试程序运行在不同的机器上。调试器通过某种方式能控制目标机上被调试程序的运行方式,并能查看和修改目标机上的内存、寄存器以及被调试程序中的变量。在嵌入式软件的开发实践中,经常采用的调试方法有直接测试法、调试监控器法、ROM仿真器法、在线仿真器法、片上调试法及模拟器法。
       直接测试法
       直接测试法是嵌入式系统发展早期经常采用的一种调试方法。这种方法需要的调试工具非常简单,比较适合当时的实际情况。采用这种方式进行软件开发的基本步骤是:
       (1)在宿主机上编写程序的源代码。
       (2)在宿主机上反复地检查源代码,直到编译通过,生成可执行程序。
       (3)将可执行程序固化到目标机上的非易失性存储器(如EPROM、Flash等)中。
       (4)在目标机上启动程序运行,并观察程序的运行结果。
       (5)如果程序不能正常工作,则在宿主机上反复检查代码,查找问题的根源,然后修改代码,纠正错误,并重新编译。
       (6)重复执行(3)~(5),直到程序能正常工作。
       从这些开发步骤可以看出,这种调试方法基本上无法监测程序的运行。虽然也有人提出了一些调试的小窍门,例如,从目标机打印一些有用的提示信息(通过监视器、LCD或串口等输出信息),或者利用目标机上的LED指示灯来判断程序的运行状态。但这些窍门的作用有限,如果一个程序在运行时没有产生预想的效果,那么开发者只能通过检查源程序来发现问题。显然,这种调试方法的效率很低,难度很大,开发人员也很辛苦。但由于开发条件特别是开发工具的限制,在嵌入式系统的早期阶段,程序的开发只能采用这种方法。甚至目前在开发一些新的嵌入式产品时,也往往要采用这种方法。
       调试监控器法
       调试监控器法的工作原理如下图所示。在这种调试方式下,调试环境由三部分构成,即宿主机端的调试器、目标机端的监控器(监控程序)以及两者之间的连接(包括物理连接和逻辑连接)。
       
       调试监控器法的工作原理
       监控器是运行在目标机上的一段程序,它负责监视和控制目标机上被调试程序的运行,并与宿主机端的调试器一起,完成对应用程序的调试。监控器预先被固化到目标机的ROM空间中,在目标机复位后将被首先执行。它对目标机进行一些必要的初始化,然后初始化自己的程序空间,最后就等待宿主机端的命令。监控器能配合调试器完成被调程序的下载、目标机内存和寄存器的读/写、设置断点以及单步执行被调试程序等功能。一些高级的监控器能配合完成代码分析、系统分析、ROM空间的写操作等功能。
       利用监控器方式作为调试手段时,开发应用程序的步骤如下:
       (1)启动目标机,监控器掌握对目标机的控制,等待与调试器建立连接。
       (2)调试器启动,与监控器建立起通信连接。
       (3)调试器将应用程序下载到目标机上的RAM空间中。
       (4)开发人员使用调试器进行调试,发出各种调试命令。监控器解释并执行这些命令,并通过目标机上的各种异常来获得对目标机的控制,将命令执行结果回传给调试器。
       (5)如果程序有问题,则开发人员在调试器的帮助下定位错误。修改之后再重新编译链接并下载程序,开始新的调试。如此反复直到程序能正确运行为止。
       监控器方式明显地提高了程序调试的效率,降低了调试的难度,缩短了产品的开发周期,有效地降低了开发成本。而且这种方法的成本也比较低廉,基本上不需要专门的调试硬件支持。因此它是目前使用最为广泛的嵌入式软件调试方式之一,几乎所有的交叉调试器都支持这种方式。
       ROM仿真器法
       ROM仿真器可看作是一种用于替代目标机上ROM芯片的硬件设备。它一边和宿主机相连,一边通过ROM芯片的插座和目标机相连。对于嵌入式处理器,它就像一个只读存储芯片;而对于宿主机上的调试器,它又像一个调试监控器。由于仿真器上的地址可以实时地映射到目标机的ROM地址空间中,所以在目标机上可以没有ROM芯片,而是用仿真器提供的ROM空间来代替。
       实际上ROM仿真器是一种不完全的调试方式,它只是为目标机提供ROM芯片,并在目标机和宿主机之间建立了一条高速的通信通道。因此它经常和调试监控器法相结合,形成一种功能更强的调试方法。
       与简单的监控器方法相比,ROM仿真器的优点是:
       .在目标机上可以没有ROM芯片,因此也就不需要用其他的工具来向ROM中写入数据和程序。
       .省去了为目标机开发调试监控器的麻烦。
       .由于是通过ROM仿真器上的串行接口、并行接口或网络接口与宿主机相连,所以不必占用目标机上通常很有限的资源。
       在线仿真器法
       在线仿真器(In Circuit Emulator,ICE)是一种用于替代目标机CPU的设备。对目标机来说,在线仿真器就相当于它的CPU。事实上,ICE本身就是一个嵌入式系统,有自己的CPU、RAM、ROM和软件。它的CPU比较特殊,可以执行目标机CPU的所有指令,但有更多的引出线,能将内部信号输出到被控制的目标机上。在线仿真器的存储器也可以被映射到用户的程序空间。因此,即使没有目标机,仅用ICE也可以进行程序的调试。
       ICE和宿主机一般通过串口、并口或网络相连。在连接ICE和目标机时,需要先将目标机的CPU取出,然后将ICE的CPU引出线接到目标机的CPU插槽上。在使用ICE来调试程序时,在宿主机上也有一个调试器用户界面。在调试过程中,这个调试器将通过ICE来控制目标机上的程序。
       采用在线仿真器,可以完成如下的调试功能:
       .同时支持软件断点和硬件断点的设置。软件断点只能到指令级别,也就是说,只能指定程序在读取某一指令前停止运行。而在硬件断点方式下,多种事件的发生都可使程序在一个硬件断点上停止运行。这些事件不仅包括取指令,还包括内存读/写、I/O读/写以及中断等。
       .能够设置各种复杂的断点和触发器。例如,可以让程序在“当变量m等于100,同时AX寄存器等于0”时停止运行。
       .能实时跟踪目标程序的运行,并可实现选择性的跟踪。在ICE上有大块RAM,专门用来存储执行过的每个指令周期的信息,使用户可以得知各个事件发生的精确次序。
       .能在不中断被调试程序运行的情况下查看内存和变量,即非干扰的调试查询。
       在线仿真器特别适用于调试实时应用系统、设备驱动程序以及对硬件进行功能测试。它的主要缺点就是价格昂贵,一般都在几千美元,有的甚至要几万美元。这显然阻碍了团队的整体开发,因为不可能给每位开发人员都配备一套在线仿真器。所以,现在ICE一般都用于普通调试工具解决不了的问题,或者用它来做严格的实时性能分析。
       片上调试法
       片上调试(On Chip Debugging,OCD)是CPU芯片提供的一种调试功能,可以把它看成是一种廉价的ICE功能。OCD的价格只有ICE的20%,但却提供了80%的ICE功能。
       最初的OCD是一种仿调试监控器方式,即将监控器的功能以微码的形式来体现,如Motorola的CPU 32系列处理器。后来的OCD摒弃了这种结构,采用了两级模式的思路,即将CPU的工作模式分为正常模式和调试模式。
       当满足了特定的触发条件时,CPU就可进入调试模式。在调试模式下,CPU不再从内存读取指令,而是从调试端口读取指令,通过调试端口可以控制CPU进入和退出调试模式。这样在宿主机端的调试器就可以直接向目标机发送要执行的指令,通过这种形式调试器可以读/写目标机的内存和各种寄存器,控制目标程序的运行以及完成各种复杂的调试功能。
       OCD方式的主要优点是:不占用目标机上的通信端口等资源;调试环境和最终的程序运行环境基本一致;支持软硬件断点;提供跟踪功能,可以精确计量程序的执行时间;支持时序分析等功能。
       OCD方式的主要缺点是:调试的实时性不如ICE强;不支持非干扰的调试查询;使用范围受限,目标机上的CPU必须具有OCD功能。
       目前比较常用的OCD的实现有:后台调试模式(Background Debugging Mode,BDM)、连接测试存取组(Joint Test Access Group,JTAG)和片上仿真器(On Chip Emulation,OnCE)等,其中JTAG是主流的OCD方式,OnCE是BDM和JTAG的一种融合方式。
       模拟器法
       模拟器是一个运行在宿主机上的纯软件工具。它通过模拟目标机的指令系统或目标机操作系统的系统调用来达到在宿主机上运行和调试嵌入式程序的目的。
       模拟器主要有两种类型:一类是在宿主机上模拟目标机的指令系统,称为指令级的模拟器;另一类是在宿主机上模拟目标机操作系统的系统调用,称为系统调用级的模拟器。指令级模拟器相当于在宿主机上建立了一台虚拟的目标机,该目标机的CPU种类与宿主机不同。例如,宿主机的CPU是Intel Pentium,而虚拟机是ARM、Power PC或MIPS等。比较高级的指令级模拟器还可以模拟目标机的外部设备,如键盘、串口、网口和LCD等。系统调用级的模拟器相当于在宿主机上安装了目标机的操作系统,使得基于目标机操作系统的应用程序可以在宿主机上运行。两种类型的模拟器相比,指令级模拟器所提供的运行环境与实际的目标机更接近;而系统调用级的模拟器本身比较容易开发,也容易移植。
       使用模拟器的最大好处是:可以在实际的目标机环境并不存在的条件下开发其应用程序,并且在调试时可以利用宿主机的资源来提供更详细的错误诊断信息。但模拟器也有许多不足之处,包括:
       .模拟环境与实际的运行环境差别较大,无法保证在模拟条件下调试通过的程序就一定能在真实环境下顺利运行。
       .不能模拟所有的设备。嵌入式系统中经常包含许多外围设备,但除了一些比较常见的设备之外,多数设备是不能模拟的。
       .实时性差。在使用模拟器调试程序时,被调试程序的执行时间和在真实环境中的运行时间差别较大。
       尽管模拟器有许多不足,但是在项目开发的早期阶段,尤其是在还没有任何硬件可供使用时,模拟器还是非常有用的。对那些实时性不强,没有特殊外设,只需验证其逻辑的程序,用模拟器基本可以完成所有的调试工作。而且在使用模拟器调试程序时,不需要额外的硬件来协助,因此降低了开发成本。
 

更多复习资料
请登录电脑版软考在线 www.rkpass.cn

京B2-20210865 | 京ICP备2020040059号-5
京公网安备 11010502032051号 | 营业执照
 Copyright ©2000-2025 All Rights Reserved
软考在线版权所有