高级调试动态系统mC/Probe (转载)
0赞作者:Micrium 公司总裁 Jean J.Labrosse 2008-04-14 来源: 电子产品世界
前言
随着低成本的在线调试能力的增强,通过指令单步调试变得更容易,成本也比较低。这种方式可以查看和修改变量值,显示寄存器的内容,查看内存块,但通常只有在目标系统停止运行时使用。然而,很多实时系统是不能停止的。因此,在不设置断点的情况下,如何查看系统正在做什么?如何在不妨碍和影响系统动态性能的前提下,实时查看和监测系统的行为?
当我们试图测试实时系统的动态行为时,传统的调试技术功能很快就变得有限了。自从第一片微处理器诞生以来,用于监控和调试动态系统的工具基本上没有发生什么变化。为了解决这个问题,嵌入式工程师采用了诸如LED、测试端口、示波器、逻辑分析仪、仿真器、字符型LCD、图形显示等工具。事实上,上述的任何一种方式都可以从嵌入式系统中获取一些正在运行的信息,每种方式都可以提供嵌入式硬件操作的观察点,用以揭露系统内部发生的神秘事情。但是,其中许多技术需要额外的硬件和软件来记录和查看目标系统发生的信息。
下文首先简要评估在监控目标系统实时行为时,嵌入式工程师常用的一些初级技术,然后推荐一种便宜的、使用简单,但性能强大的新调试技术。
常用的初级调试工具
LED
很多嵌入式系统都会包含一个,在某些情况下会有多个发光二极管(LED)。LED被用来显示各种各样的动态信息。它们可以指示嵌入式系统是否在运行,某个条件是否发生,系统是否发生了错误,已经运行到了某个位置等等。
LED是一种简单、有效且比较便宜的器件,但同时它们也有局限性。首先,它们增加了成本,除非将它们进行组合,形成条形或其它更复杂的显示方式,否则它们不能传递变量值。其次,LED显示的数据量是有限的,并且显示方式也不够友好。必须承认,LED具有比较好的指示方式,显示系统正在运行或一个特定的事件已经发生,但在其它方面并不擅长。
使用printf()函数
嵌入式工程师可以在代码中使用printf()函数(假设采用C语言编程)设置断点来获得对象的动态行为。在调试过程中,printf()函数可以到处移动来显示目标的应用,以便在系统开发过程中获取信息。不难想象,过度使用printf()函数将导致应用程序臃肿。通常printf()函数会放在主机的终端输出窗口,由于这个原因,当连续获取数据时,工程师需要将各种数据流实时地重新分类。这些数据流一般是由整数或浮点数据转换得到的文本值,故迫使工程师读取每个值时,调整它的量级,理解它的重要性。大多数情况下,采用数据值曲线图或许比文本值更恰当。
由于printf()函数占用代码量,在一些系统中,特别是在8位微控制器中,不能简单地应用这种方法。即使在代码不受限制的情况下,printf()函数在格式化输入时也会引起延时。当通过串口传递信息时,产生的延时会更长,更不用说增加了系统的负载。况且新的PC机不再包含串行接口RS-232C,因此这个技术几乎要销声匿迹了。
LCD字符显示
有一些嵌入式处理器使用额外的I/O口与字符型LCD。这种方式相对费用比较昂贵,且需要写代码来显示希望得到的状态和变量值。这种设备可以显示的变量数是有限的,需要一次或几次完成所有的显示。此外,还需要实现一个用户接口来选择查看变量值。很明显,这种方式占用了嵌入式工程师开发实际产品精力。取决于产品本身的成本或其它原因,显示可能不会作为最终产品的一部分。
图形显示
那些拥有图形显示设备的嵌入式系统可以传递很多系统的实时信息,数值、图、列表、柱状图等都很容易显示出来。然而,这种显示手段会导致系统成本的增加,如电子显示设备和图形用户接口(GUI)软件,以及创建接口传递信息所占用时间。尽管在开发的初级阶段,显示设备可以被借用来帮助开发,事实上,很多嵌入式系统拥有的显示设备,通常是将其作为用户接口,而不是用于开发。
高级调试工具
我们需要的是监测目标系统,而不必负担额外的费用或增加设备的负载。有一种设备允许我们以图形方式显示从目标系统获取的任何信息,它就是普遍存在的PC机。
以上结论使得Micrium公司开发了mC/Probe高级调试系统。这个概念很简单,我们可以把大部分的负担转移到运行Microsoft Windows的PC机上,而将尽量少的代码放到目标系统中。
mC/Probe是一个基于Microsoft Windows的应用程序,可以实时显示产品中任何变量值、内存分配和I/O口值。mC/Probe通过逻辑图、数据指示器、温度计、柱状图、速度图、饼图、LED以及其他方式来显示变量值。而不需要在嵌入式产品中写入任何代码,不使用printf()函数,也不必在产品中增加用户接口。Micrium公司以源代码的方式提供了一个小且简单的stub(占位程序),在创建目标应用时需要PC机端的 stub,使用通用的UART、USB、TCP/IP、JTAG接口或其它目标系统接口。在开发产品的过程中,一旦stub与产品一起编译连接,即可开始查看嵌入式系统的实时行为。
mC/Probe可以用于任何编译器和处理器(8、16、32位CPU或DSP)。事实上,任何工具链(编译器、汇编器、连接器)都适用。如果系统中有RTOS,亦可以与RTOS结合使用。
mC/Probe工作流程如下:Windows应用程序分析由工具链的连接器产生的文件,确定目标板上每个全局变量的名称、类型和地址,并在符号浏览器中列出所有的变量。然后用户将图形组件(虚拟对象)拖拽到数据屏幕中的一个画面,并为每个对象指定符号浏览器中的一个变量。在目标系统接口允许的情况下,放在开放数据屏幕中的图形组件关联符号值将很快获得更新。如果工程师需要修改目标代码,则连接器将改变变量的地址,mC/Probe重新加载新的连接文件,调整数据屏幕中所有图形组件的信息。
事实上,目标系统只需要很少的代码,就足够响应如“发送0x40102030地址开始的12个字节”这样的要求。Windows应用程序在收到应答后,根据新的值更新数据屏幕中相关的组件。因为代码位于RTOS的空闲任务中,在与RTOS一起使用时,目标驻留代码通常不会插入。换句话说,因为在空闲任务中CPU不执行任何操作,它不占用应用程序的CPU周期。如果工程师希望仅仅更新某一段代码中的变量值,他可以将目标驻留代码放在那个位置上。结果是,与Windows应用程序通信所占用的时钟周期的百分比,可以通过简单地修改目标系统中调用驻留代码的频率(和调用的位置)来满足用户的需求。
采用mC/Probe可以显示温度、压强、湿度、过程变量、状态变量、定时器、计算结果、逻辑I/O、最大/最小值、执行时间、堆栈使用、I/O寄存器、I/O口、列表、数组、绘图变量随时间的变化等等。也可以显示布尔型、整数、浮点数据和字符串。
mC/Probe允许创建多个数据屏幕,通过逻辑分组来显示变量,查看目标的行为。如果设计一个发动机控制器,可以通过创建一个数据屏幕来显示控制器的实时数据,例如:制动位置、电流和每分钟最大转数、气缸温度、发动机运行时间、发动机油压和温度、空气压强和温度、停止时间、燃料数量等等。
mC/Probe提供了完整的图形对象,包括模拟LED、标签、标准尺、图、列表,增强了控制的灵活性。
标签用于显示变量值或者内容,如ASCII 字符串,但作为数字量则代表了一个整数或浮点数,或者用于简单地显示一个可配置长度的字符串。标准尺使用模拟尺或者仪表方式来显示数据。图形通过线图和柱状图来显示数据。列表是最灵活的,并且有一个电子数据表接口,允许包含其它数据单元的数据,或者目标系统中变量值的计算公式。极大增强了列表的扩展性和灵活性。以枚举类型为例,可以从整数值转换为逻辑字符串的形式表示,因为比数值更有意义。
应用级的调试
对于应用级别的调试来讲,高级调试工具,例如mC/Probe比初级的工具更合适。由实现相关功能的几个任务组成的嵌入式系统,不适合采用断点和LED的方式来调试。通过使用mC/Probe窗口接口,可以在一个观察点获取更广泛的信息,更适合应用级的调试工作。为某一个特定的模块,如RTOS、TCP/IP、USB协议等开发的数据屏幕,可以用于这些模块的任何嵌入式系统。与模块相对应的数据屏幕可以用于新的工作屏幕,与图形相关联的变量将被重新连接,这意味着变量地址将从新目标上运行的代码连接输出文件中自动获取。
认为“高级调试工具在对有问题的底层代码函数调试时缺乏洞察力”的评论也是正确的。对这种任务调试来说,断点和LED是不可替代的。应该指出,mC/Probe可以作为在所有产品的初期开发阶段使用的工具,对于高级特性的系统缺陷,如任务的性能、堆栈使用、或缓存使用等,在早期就提供一些警告信息。