当前位置:首页 > 嵌入式 > 嵌入式硬件
[导读]引言嵌入式软件开发往往缺乏必要的调试工具和调试手段,同时需要有较高的容错处理能力,程序正常运行过程中尽量不因为出现异常而导致系统停止。一旦发生错误或异常,开发人

引言

嵌入式软件开发往往缺乏必要的调试工具和调试手段,同时需要有较高的容错处理能力,程序正常运行过程中尽量不因为出现异常而导致系统停止。一旦发生错误或异常,开发人员需要尽量多的错误环境信息来查找问题的原因。从程序编写的角度来讲,一般嵌入式软件都采用C语言开发。C语言本身的特点决定了无法利用语言本身的功能实现对异常的跟踪与处理,只能通过良好的编程模型与习惯,以及后期的大量测试,来发现和解决异常。因此,如何进一步提升程序开发中的可调试性,对于运行中的异常如何保存现场,从而方便进行异常追踪等,是开发者需要考虑的重要问题。本文针对嵌入式C语言开发的特点,提出一种基于堆栈模式的异常追踪编程模型,能够实现有效的异常现场保存与恢复,并为后期的问题分析与解决打好基础。同时,本文所提出的思路亦可作为实际运行阶段提升可调试性的一种手段应用于嵌入式软件编程中,最大限度实现对于异常发生环境的保存与定位,提升系统的可维护性。

1 建立全局错误代码表

对于嵌入式软件来说,尽量节省内存资源、降低程序代码量是十分重要的。因此,将程序中所有错误、异常情况都进行了统一编码,提高了错误处理代码的规范化与可读性。设计8位整数编码格式如下:

 

每个错误代码在程序中仅需要1个字节进行存储。对于程序中每个可能异常的地方(如COM1没打开),都设定1个唯一编号,当出现错误或异常时根据该编号可以直接定位到源程序对应文件和程序段,并确定错误类型。

采用错误代码的形式存储错误信息,不仅可以精确描述错误的类型、位置等信息,还可以最大限度地节省宝贵的可执行内存资源,降低程序对内存的需求。

2 建立全局异常堆栈

在一个复杂的嵌入式实时系统中,程序处理流程复杂,不同资源之间往往在操作上存在着交叉。当出现程序错误或异常时,不能简单地退出程序,而是应当尽量将错误处理掉,实在无法处理的错误应进行记录,但整个程序的运行不应当中断。对此,使用1个错误堆栈来保存错误信息。该栈用下面数组定义:

 

ERROR_STACK为全局错误栈类型定义,MainErrStack为全局栈实例,其元素个数由ERR_STACK_SIZE确定。 ErrorParm为字符数组,当错误发生时可以依次保存函数的人口参数以及异常发生之前局部变量的值等。实际数组长度ERR_ENV_LEN可以根据情况调整,一般情况下开发阶段可以设置大一些,保证存放更多的错误信息用于调试;进入实际运行阶段可以适当缩小该错误环境栈长度,减少内存空间的占用。

为了确保错误处理机制本身不会给程序引入新的异常,因此将堆栈的操作完全封装为Push和Pop两个函数,并引入当前堆栈指针stackCu- rrentPos(初始为一1表示堆栈为空,有效取值范围为一1~ERR_STlACK_SIZE一1,该指针始终指向栈顶元素)。算法说明如下:

 

3 建立统一的错误描述字典表

为了进一步提高代码规范化程度并降低内存需求,可以将每种类型的错误定义一个错误描述保存在单独的文件或缓冲区中。当发生错误时,系统根据错误代码取出该错误的详细描述并显示给用户。以上操作可以封装为ShowErrorMessage函数,定义为Char*ShowErrorMessage(int errorId)。在错误发生位置并不直接描述错误信息的方法,不仅可以降低可执行内存需求,而且避免了由于不同开发者对错误文字描述的差异而导致对用户的提示信息不统一。例如错误提示“数组越下界!代码:53017010”,530即表示数组越下界异常,17表示编号为“17”的C源程序文件,010表示文件中第10个错误位置。部分错误代码描述示例如表1所列。

 

4 应用说明

下面以1个简单的例子来说明本文方法的运行。假设程序需要提供1个通过GPRS发送数据的函数 GprsSendData(char*ip,char*buf,int size),实现将buf缓冲区指定长度为size的字符串通过TCP方式发送到给定IP地址。示例代码如下:

 

由上面可以看出,可能出现错误的位置都加入了错误压栈操作,当GprsSendData函数的返回值为假时,上级调用函数会继续将其异常时的运行状态(局部变量、参数等)继续压栈,以此类推直到需要处理该异常的最顶级。开发人员后期调试时可以将栈顶元素依次出栈,构成一条完整的函数调用链,比较容易找出上述产生ip为空串的根本原因。

在软件开发阶段及运行的初期阶段,适当加大错误堆栈容量,可以储存更多信息辅助调试。随着设备软件可靠性、稳定性的增加,在正式投入运行后可以将异常栈设定为较小的容量,以降低存储需求。

可以设想,若整个嵌入式软件在开发中严格按照本文思路处理异常,应当可以很方便地进行异常的查找与处理。当嵌入式设备投入运行后,定期对该设备的错误栈进行分析,对于栈中存储的错误信息进行及时处理,可以迅速有效地增加设备软件的运行可靠性。一个经过严格测试的设备在绝大多数情况下错误栈应为空。

结语

本文对于基于C语言的嵌入式软件开发中的错误追踪机制进行了详细描述。该机制可以有效地降低软件异常发生的概率,提升软件的可靠性,减少开发成本。同时,该机制亦可以用于正常开发阶段的辅助调试中,在关键程序段将环境信息压栈实现后期分析,也为改进嵌入式软件的调试手段提供了新的辅助思路。文中所述机制已经在作者主持的电力GPRS集抄终端的软件设计中得到了实际应用,取得了良好的效果。[!--empirenews.page--]

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭