查看完整版本: 复杂器件内部的实时可视性的实现方法

liyf 发表于 2014-10-5 11:52:33

复杂器件内部的实时可视性的实现方法

复杂器件内部的实时可视性的实现方法


如果在一个系统中拥有几个处理器和外设,要开发具有成本效益、可靠的产品,尤其是在今天很短的产品开发时间的条件下,了解所有这些芯片的实时动态特性将变得非常重要。实时嵌入式系统越来越多地在多内核ASIC或系统级芯片(SoC)上实现,以利用这些器件所具有的低功耗、低成本和更高集成度的优点。
开发者所拥有的很多这些标准设计工具是依赖于了解老的技术产品的内部运行情况来实现的,已经不适用于这些新型的、功能强大的多功能设计了。通过集成,SoC架构在单个硅片上拥有多个处理器、存储器、外设、控制器和其它重要的子系统组件。高速内部总线连接这些不同的组件,整体的性能决定于他们之间的数据流的高效管理。瓶颈、延迟和对于像总线和存储器等共享资源的竞争这些问题,对于实时数据传输来说是致命的。为了获得最佳性能,开发者应比以前更需要了解芯片内部运行的具体情况。
然而,对系统组件之间的事务处理的监控不再是像以前那样连接一个逻辑分析仪或者总线分析仪那么简单了,因为很多感兴趣的信号深“埋”在芯片内部。对SoC的可视性需要一套硬件和软件相混合的装置来采集SoC本身内部的数据,并由特征描述以及关联工具提供支持,这些工具能帮助开发者分析所采集的数据。
当然可以通过不同的方式实现可视性。在很多情况下,可以观察许多组件(如存储器、系统总线和I/O端口)来采集信息。换言之,当评估过程本身影响到结果的时候,要评估总线利用率和存储器竞争情况就很难。挑战在于在不影响系统性能的情况下采集和上载数据点。
回到现实情况
传统上,当没有逻辑分析仪可用,或者太难于设置时,开发者使用软件测试工具来获得对他们设计的可视性。他们会向目标对象增加调试代码来采集、处理和上载调试数据。例如,在进入和离开一个函数时打开和关闭某个计时器,无论是过去还是现在,对于通过软件分析器来对函数进行描述来说,这种方法都是一种的简捷方法。
尽管这只需要增加很少的C语言printf指令到测试代码中,对采集的数据进行格式化,并输出到一个标准的I/O器件,但此时这些代码对代码的大小、存储器利用、缓冲器性能、时序和系统资源竞争都有很大的影响。这些缺点使得printf只适合于测试非实时的控制代码。对于实时的或者确定性代码,例如,用在消费媒体播放器和录制设备、手持无线通信设备、电信、机器人技术或汽车上的应用,需要采用其它的对系统影响较小的技术,以避免干扰目标程序的执行或错失实时期限。
减少干扰
有很多方法可以在增加可视性的同时减少干扰。从概念上来说,对一个系统进行监测涉及到数据采集、数据缓冲、上载来自目标器件的数据、后续处理以及进行显示等。认真安排这些活动在什么时候以及哪里发生,可以将它们对系统性能的影响减到最小。减少与测试代码以及数据采集设备相关的存储器区域,可以采集到更多的数据,并增加对系统实时行为测试的精度或广度。
一般需要数据点几倍大小的存储空间来记录关联信息,这些关联信息用于更准确地对其进行理解。例如,除了在采集时的数据值,可能还需要标记数据相关联的变量名字,获得一个数据采集时间的时间戳,并注意当在获得时间戳时正在执行的函数等。有几种方法用于获得和组织这种关联信息,并且不需要依赖于printf和其字符串格式化功能。通常在数据中包含pattern,如果用某种方式来采集数据,那么可以推断出一些额外的特性,而不需要将它们包含到缓冲器中。增加可视性的一些方法包括:
1. 记录格式
如果在缓冲器中采集一个变量,则不再需要对所采集的什么变量进行标记。如果需要采集多个值,就可以创建一种记录格式,每一个值对应一个给定的位置,这样避免了不得不对采集的内容再次进行标注的情况。
2. 多个缓冲器
通过将相似的数据点分组在一起,可以简化循环缓冲管理,减少对每个数据点的采集延时。同样地,如果按照优先级来对数据采集进行隔离,那么当系统在100%的利用状态时,可能使循环缓冲器抓取到非关键信息的溢出,而不是用一个非实时的上载来弄乱了实时系统的时限要求。在任何情况下,都需要用来标记溢出的机制。并且如果缓冲器存在一些前提条件,例如需要重构的时间戳,则可能追踪丢失了多少数据。
3. 采样数据
配置硬件计数器并使其运行对系统的影响很小。无论如何,读取一个计数器并上载其值都是具有干扰性的。对计数器的记录越频繁,记录就越准确,但采集和上载的干扰就越大。在确定确实需要更准确的信息之前,保持较低的记录频率。例如,一个记录当前哪个函数在执行的周期性分析器能确保得到一个非常准确的代码使用百分比情况。这样的分析器仅收集了在每个函数调用的记录期间所采集的信息的一部分,于是干扰很小。也可以按低优先级任务来对数据点采样,尽管这样可能使得结果产生一些偏差。
4. 确定性的数据
如果数据采样获取的频率固定的话,不必要加入一个时间戳。作为一种替代选择,如果数据必须通过一组连续的运算块,只需记录数据值和时间戳,因为可以从时间戳的次序确定实际的程序块。如果获取了几个值,可能更有效率,以确保数据流能通过一系列的程序块,此时只需记录函数和时间戳,并采用数据记录格式。
5. 动态/智能记录
通常只在需要时采集数据(换言之,在对某些信息感兴趣的情况下),这样减少了数据采集产生的影响。利用几个调试标记,可以缩小采集的范围。这可以通过设置一个特定的标记来实现,这个标记只有在感兴趣的情况下才有效,通过这种方法,不会因为上载不需要的信息使系统过载。这也减少了捕获数据过程的开销,节约缓冲器空间。设置或检查一个标记只需要一个或者两个处理器周期,因此这是非常有用的方法,即使是对于基于硬件的计数器亦是如此。
6. 块状记录
在某些情况下,在不影响执行时(如没有实时运算时)有可能可以暂停对象。此时可以通过在能安全暂停的情况下触发一次暂停来“避免”缓冲期上载开销,然后在系统暂停的时候再对缓冲器上载。
7. 按块上载
如果任务比较空闲,可以在系统没有完全利用时用来上载缓冲器。尽管这不会减少上载开销,但却可以将上载的影响转移到一个对系统性能影响更小的时段。
8. RTOS监测
对于更复杂的监测,可以在实时操作系统上找到支持。很多操作系统具有内置的机制和库,能支持片上监测硬件,即易于配置又为管理循环缓冲器和向外发送数据流需要的基础架构提供基本代码,并提供用于自监测的Hook函数。通过对记录过程抽象化以及卸载数据,可以快速地对监测的对象、监测的方式、监测的频率、获取数据的位置以及卸载方式等进行重新配置。在创建自己的基础来测试代码之前,应首先检查RTOS提供的内容。
9. 避免访问存储器和其它系统资源
只有在硬件机制不足的情况下,才应该用软件手段作为补充,例如当需要非常大的缓冲器或者当有限的处理降低了整体的干扰时。理想的情况是,如果在不使用系统总线或存储器的情况下监测系统总线或存储器,将能得到更准确的结果。如果将采集的数据量控制到最小,就可以避免使用存储器中的缓冲器,只是通过JTAG或总线直接发送。
10. 连续采集
在过程中监测如果需要采集大量的数据,可以考虑连续采集。注意,因为在每次运行时会采集到不同的信息,将无法对结果进行关联,因为时间戳包含不同的测试延时。在考虑从什么地方开始发现问题时,这种方法最好。因为这样能降低概率,也能降低监测的等级。
11. 模块
如果通过JTAG或总线发送数据,则可以在目标和主机之间放置一个处理模块来处理时间戳的产生和有限的数据处理。通过将时间戳的工作卸载到该模块,可以释放测试总线的带宽,用来发送更多的信息。模块也是实现完全无干扰监测的非常有效的方法。例如,模块可以监测系统总线,监测测试总线上某个特定的存储器地址范围,或使用直接存储器访问(DMA)来触发一次准实时的数据块获取。
给定不同实时应用的特性,将希望测试不同的采集方案,来确定哪些组合能实现最小的干扰的最高可视性。例如,如果有多余的存储器,那么可以增加缓冲器大小。这取决于采集什么样的数据及采集多少数据。
硬件辅助监测
在某些情况下,测试代码可能要么对系统影响太大,要么不够准确,或者不能简单地获得理解流过复杂的SoC的数据流的动态特性所需要的信息。越来越多的SoC架构包含用于辅助监测器件的硬件运行的功能,以满足这些需求:
1. 事件计数器
用软件监测一个事件时,很多细微的细节不容易被发现。例如,记录某个特定的CPU内核在等待访问共享资源(如外部存储器)时停止的次数,采用软件就无法实现。包含一些设置很好的计数器的硬件设计,可以以很低的额外成本实现对系统动态特性的深入了解。数据可以通过调试器的JTAG接口读出,或被周期性地读出,例如,由软件中的背景任务读出并写入到缓冲器中,以便在稍后的时间进行查询。
2. 高水印计数器
通常,开发者需要理解器件会运行的极限恶劣状况,例如,服务中断的最大时间或输入数据中的最小和最大抖动。高水印计数器提供硬件,这些硬件能被配置用于监测特定总线事件,并锁存最大的(高水印)或者最小的(低水印)的时间参数。在不需要太大的开销情况下,他们能提供非常宝贵的统计数据,否则需要用目标软件来实现,或采集数据并发送到片外以作后续处理。
3. 跟踪
一种成本很高但非常有用的硬件辅助监测方法是跟踪。在这种方法中,总线事务被记录在专用的片上存储器中,这样一来,可以捕获导致产生一个事件的最后的N个总线事务。
上载捕获的数据
一般来说,你会上载数据到一个开发系统中(如电脑),或者上载到一个监控模块作进一步分析。一旦确定需要采集什么样的调试信息,以及如何采集以尽量减少干扰,那么必须决定如何从芯片向外发送数据-理想的情况是在应用程序还在运行时能够发送。
应该做的是缓冲器深度和上载频率之间的折衷。你调试数据缓冲器越小,上载数据的频率越高。频繁上载将对系统性能产生持续的影响。如果有一个大的存储器池用于缓存调试数据,那么采集数据对系统性能的影响就会较小。然而,更大缓冲器则需要更多的目标存储器,在器件运行期间上载数据对系统性能的影响将更显著。
在应用现场,通过像串行总线、TCP/IP连接或者USB端口等系统端口上载数据可能非常有用。增加的数据吞吐量不仅消耗这些端口的带宽,但也占用处理器周期,来处理协议并完成数据传输。
当采集比芯片上能实时提供的还多的数据时,将不可避免地在获取的数据中引入空隙。在这些情况中,有必要周期性地插入足够的关联信息,以确保数据在最终从片上捕获后能被成功解码。对数据打包或者引入周期性的“同步点”是在数据流中提供这种额外信息的两种方法。可以作为数据上载过程的一部分来完成这个工作,这样冗余的信息就不必存储在片上。
如果在一个SoC中多个CPU内核共同工作,常常需要并行地对每个内核上载获取的信息,以便体现一个系统的完整情况。如果多个上载路径不可用,要么在上载之前将来自多个内核的数据结合起来放到一个缓冲器中,要么将它们按照某种方式复用起来以共享上载路径。同样的,在决定处理这些问题的最佳方法时,需要考虑系统的动态特性和数据的相对重要性。如果有很多相对不重要的数据来自其中的一个内核,而另外一个内核偶尔会发送一些重要信息,你需要采用一种方法确保重要的信息能优先于非重要的信息。
可视化及分析
将从SoC器件中产生的原始信息转换成一种易于理解的格式对SoC本身提出了许多挑战。能采集到的数据种类、用于采集这些数据需要的特定硬件机制以及各类不同的应用,用户需要解决所有这些特殊的问题,这就使得创建一个通用的可视化工具非常具有挑战性。模块和定制化工具能进行定制,使其能用于特定的硬件、软件和要解决的问题领域,这通常是克服这些挑战所需的灵活性的最佳方法。使用一种模块化的框架使其很容易将来自不同的数据流的数据进行关联,针对特定类型的信息分析关联的数据,并以一种易于理解的形式显示这些从数据中得到的信息。这里描述了这种框架应该提供的一些功能类型实例:
1. 关联数据点
在解决一个多处理器SoC中的瓶颈、竞争或负载均衡这类系统级问题时,可能需要从多个处理器和加速器采集数据。在这种情况下,重构系统行为需要将多个记录关联到一个时间线。在某些系统上,系统时钟的实用性较高,从而可以使这个问题简单化。而对于另外一些系统,可能需要通过利用像DMA这样的系统资源,从其它内核来访问的方式利用时钟。如果公共时钟不可行,可以使用其他机制来周期性地同步多个内核的时间。其中的一个方法是使用中断来将一个同步时间戳通过共享存储器传递。理想情况时,可视化工具能适应这些不同的记录关联方法。
2. 分析基础架构
一种模块框架能够将常见的分析活动制作成模块,这些模块能用来实现很多不同的分析和可视化工具,例如,一种普通的可定制数据转换器和表格,可以很容易用于创建一种消息记录浏览器;一种能够将基于一事件或时间戳的多个数据流关联起来的分析模块,可以被用作为一个构建块,来构造送往其它分析模块的数据;一种用来分析过去一段时间的高水位标志的模块能为特定应用的Dashboard、带宽利用率监测器等提供一些基本依据。
3. 可扩展性
尽管可以用一些普通组件来评估所采集的大量数据,但最好是能够构造定制组件来扩展工具的环境。
4. 可配置性
可视化工具对于从大的缓冲器上载中提取有意义的信息非常关键,开发者需要能配置工具来强调特殊的差异性和数据峰值以发现一般的行为和异常的行为。为了从目标对象上卸载数据处理,所用工具应该提供允许将智能特性构建到工具中的可编程基本功能,并减少需要采集的数据量。还应该提供足够的控制以确定在任何给定的时间,来规定应该采集什么样的数据。
看看现实 获得对实时SoC系统内部的可视性的挑战当然并不是微不足道的小事。采集到足够的信息来产生不需要校正的有意义的结果,需要一种系统级的方法。通过使用软件工具库,利用硬件辅助监测以及对数据如何从芯片上发送出来的管理,增加准确性、宽度、深度和采集数据的粒度,使得开发者能采集更多的可靠信息。新的灵活工具套件和软件开发策略将帮助开发者来应对测试和调试用于具有高精度和高置信度的实时应用的复杂SoC架构的挑战。

李小路 发表于 2022-5-28 08:42:54

谢谢分享!:D
页: [1]
查看完整版本: 复杂器件内部的实时可视性的实现方法