嵌入式软件调试的发展历程

2023-05-15 10:26:59 digiproto
调试在软件领域泛指重现软件缺陷问题,通过定位并查找问题根源,最终解决问题的过程。嵌入式系统从20世纪70年代单片机的出现发展至今,其开发环境、调试器和调试软件都在不断优化,硬件的体积也在不断缩小,性能也得到了大幅提升。调试作为嵌入式软件开发人员的日常,其流程与方法也在随之不断发展,但其基本方法并未改变。


20世纪90年代存在两种不同的基于工具的嵌入式软件调试方法:

1. 调试器监视软件:在嵌入式系统内存中进行编程并响应外部调试器请求,价格低廉且具备基本调试功能。


2. 硬件仿真器:一种大型硬件,用于适配替换和模拟目标硬件中的微控制器或处理器。当时的硬件仿真器已具备定时测量和代码覆盖率分析等功能,可使开发人员获得访问微控制器或处理器的所有总线的权限,但其非常昂贵、复杂、不稳定且易出错。为控制总体成本,半导体制造商必须开发一种特殊的、附带引脚的仿真芯片。


随着半导体的体积不断缩小和片上调试接口的引入,作为开发工具的调试器本身的体系结构受到了很大的影响,原本需要通过硬件实现的调试功能如今都可在软件中实现,带宽和执行速度方面的性能也都有所提高。然而,调试的使用场景仍然是相同的,在研究调试发展历程时应聚焦于调试本身。


聚焦于调试本身

调试的方法不外乎增加“printf”辅助输出信息、烧写到目标版卡、增加断点、增加实时监视或单步执行。原则上,调试通常用于嵌入式程序开发和故障排除,包括但不限于将软件烧写到目标硬件上,通过调试器进行调试,在代码的执行到某个断点时检查内存、寄存器、读取函数调用堆栈等操作。


就应用程序而言,调试的步骤非常简单且易于理解。原则上大多数开发人员都能通过调试器来完成调试,但往往很少有人能花时间去研究调试器本身,从而发掘出更好用、可以节省调试和测试时间的功能——比如可在不影响软件运行情况下进行数据记录、使开发人员更深入了解软件执行情况的数据追踪功能。


发展助力:微控制器、处理器和SoCs(片上系统)带来的新挑战

在过去的15年中,嵌入式产业,尤其是汽车产业的产品引入了许多用以满足新需求(如减少汽车事故)的额外功能,汽车制造商摒弃以往按功能开发专用电子控制单元(Electronic Control Unit,ECU)的高成本开发模式,开始更多地通过在多个ECU之间分配功能来更有效地开发汽车软件。


为了实现这个目标,汽车半导体制造商需要生产封装体积更小、性能更高的微控制器来满足汽车客户的要求,拥有两个或多个核心的嵌入式多核微控制器由此诞生,新的挑战也随之出现。嵌入式软件工具供应商面临着新的问题,例如如何轻松访问多核ECU的所有核心、如何在不同核心上进行嵌入式软件的分发从而使其在保持高性能的同时能够有效运行等。传统的嵌入式软件开发流程已无法满足这些需求。


随着高性能的计算平台和多核系统的引入,更复杂的处理器架构被应用于高度复杂的程序中,调试的需求也随之增加。除了标准的调试功能外,诸如时间分析、功能剖析或CPU(Central Processing Unit,中央处理器)负载测量等分析功能也越来越多地被使用。当然,这些功能被用到的先决条件是所使用的半导体有可用的调试接口,以及相应的调试器和调试软件需要具备获取这些数据的能力。


软件开发过程标准化

考虑到分布式开发团队的工作方式、日益增长的功能需求、日益复杂的代码、标准化要求和时间压力,嵌入式软件的开发需要在尽可能短的时间内将可靠和安全的产品推向市场。形成高度抽象化和自动化的软件开发过程迫在眉睫。


首先,开发工具必须更加通用。调试器以前只被微控制器工程师用作为硬件相关的开发工具,现在也越来越多地出现在各种软件开发环境中。调试器仍然通过标准的调试接口连接到实际目标硬件以便进行嵌入式开发和测试。


除了简单地与目标硬件接口之外,调试器还提供了更高级的调试功能,甚至一些测试功能。开发人员可以跟踪正在运行的软件的执行情况。同时还可以随时暂停程序的执行来检查系统当前的状态。除此之外,有些专业的调试器还可以跟踪记录软件中的进程,在时钟周期范围内记录执行时间,以及评估与测试相关的软件代码覆盖率。


为了使使用人员灵活使用这些功能,调试器制造商提供了通用的接口(API,Application Programming Interface,应用程序编程接口)),允许将这些调试辅助功能通过API集成到开发或测试过程中,如下图所示:

调试器提供的API实现了开发和测试过程的平滑和自动化的工具转换.png

▲图1:调试器提供的API可实现开发和测试过程的平滑和自动化的工具转换


这些接口必须适合于解决各种各样的任务(如开发、测试、验证软硬件等),通常也支持编程或支持脚本语言,以便使用人员将开发和测试期间完成自动化。


除此之外,如今的调试器也提供了所谓的“mini-HIL”功能(用于测试的硬件在环,数据激励和数据监视)以生成或测量数据和模拟信号,同时进行记录和协调程序执行,从而尽早在软件开发进程中进行接近实际硬件的测试。


使用自动化接口的典型应用场景就是近期频繁被提及的持续集成(Continuous Integration,CI)。持续集成通过将开发人员编写或更改的代码集成到团队的共享库中,可在短时间内实现敏捷/分布式软件的开发和测试。通过集成,将一些自动化的步骤组成为流水线并通过本地或云端托管的持续集成软件(如Jenkins、GitLab-CI、TeamCity、CircleCI或GitHub Actions)触发。持续集成流水线通常包含了构建、静态分析、单元测试和系统测试。


持续集成基础架构的流水线,包括构建、静态分析、单元测试、系统测试,最后到产品交付.png

▲图2:持续集成基础架构的流水线


一般来说,软件可以在PC(Personal Computer,个人计算机)机上进行独立于目标硬件的SIL(Software in-the-loop,软件在环)测试。然而,并非所有潜在的错误都能通过SIL测试和仿真环境监测到:比如硬件的外围设备的物理环境、时序行为。交叉编译器生成特定硬件的目标代码和SIL环境所生成的代码也不同。


综上,在早期阶段尽可能接近实际硬件进行PIL(Processor in-the-loop,处理器在环)测试是很有必要的,以确保最终产品的功能和时序行为符合预期。


ISO26262和DO-178C等安全标准为工具提供了更加严格的认证,为此,工具制造商必须创建和特定用例相关的工具正确性验证,上述使用调试器进行自动化测试过程的方法非常适合此类工具的验证过程。


结论:调试复杂化带来了业务模式的变化

经过漫长的演变,大多数调试器的通用功能相同,并且附带了强大的分析功能。在“软件定义一切”的世界里,软件开发本身需要大量的软件和硬件工具,工具之间也有着互相依赖性,这促使工具制造商、芯片制造商和用户之间需要进行知识共享,“工具+知识+咨询”的业务模式成为了嵌入式软件领域的全球化趋势。



SkyEye,中文全称天目全数字实时仿真软件,是基于可视化建模的硬件行为级仿真平台,为嵌入式软件开发、测试和验证提供了虚拟运行环境,目标程序可以不加修改在SkyEye仿真环境中运行,其动态特性及执行过程都与真实硬件中一致。SkyEye可以代替真实硬件和调试器对目标系统进行PIL测试,解决硬件资源稀缺、硬件环境搭建困难、硬件测试环境难以管理等问题。其丰富的自动化测试接口和命令行控制也可以很好地和CI/CD工具进行集成,助力嵌入式DevOps实践。

SkyEye宣发.png



首页
产品
新闻
联系