一种DSP芯片程序死机软件方面的控制方法

发表时间:2020/7/1   来源:《工程管理前沿》2020年3月8期   作者:吕铁生
[导读] 在芯片运行过程中,会出现各种无法预料的情况,其中芯片死机最为严重。
        摘要:在芯片运行过程中,会出现各种无法预料的情况,其中芯片死机最为严重。本文介绍面对芯片死机情况,如何去分析原因,并在查到原因后提出了相应的解决方法。同时为了预防死机现象,在软件方面做了相应的处理方法,来保证死机时不会出现严重的事故等问题。

关键字:芯片死机,DSP

Abstract
In the process of chip operation,will appear all sorts of unforeseen situations,including chip crash is most serious.In this paper,in the face of the chip crash situation,how to analyze the reason,and after check the reason put forward the corresponding solutions.In order to prevent freezing,do the corresponding processing method in the aspect of software,to ensure that the crash when won’t appear such problems as serious accidents.

Key words: Chip crashed, DSP

1、 问题描述
在DSP程序运行中,可能出现很多意想不到的状况,其中死机现象是最严重的问题之一。下面列举几个由死机问题引起的故障。
故障一:7kw充电中跳枪,充电盒跳闸,故障lOmin后整车断电。之后40kw充电柜功 率只有6kw左右,车辆上电无法行驶,仪表显示请检查动力系统故障。读取故障码,发现电池管理器报严重漏电,故障件分析结果为单相充电接触器K7烧结。 经过大量分析实验后, 将问题点定位在数组溢出导致芯片中数据被修改,其中系统关键变量开关中断仲裁计数器被 篡改而无法进入中断,芯片死机,输出的PWM波不变,导致IGBT输出大电流烧坏接触器。
故障二:车辆在正常行驶中,踩刹车停车后,无法继续行驶。片刻后,车辆开始自动低速往后倒车。读取故障时,发现多个模块报与DSP2模块通讯超时,DSP2不响应。退电重新上电,车辆恢复正常。再次读取DSP2故障,发现DSP2 并无故障记录。经过实验分析得到,在有刹车时,由于某种频率的干扰和晶振管脚使用有误,引起晶振输出对地短路,最终导致芯片死机。
从上述故障可以看出,芯片死机时可能会引起很多严重故障。为了尽可能保证芯片正常运行,本文针对死机现象进行软件方面的原因分析,并提出一些预防措施,以保证程序可以更好更安全的运行 。
2、原因阐述
软件方面关于死机的主要原因有 :1、堆枝溢出;2、数组溢出;3、访问指向空地址的指针;4、未声明的函数调用跑飞;5、意外中断;6、中断变量处理不妥;7、无条件死循环;8、看门狗没有关闭等。
2.1堆栈溢出
堆枝溢出就是不顾堆栈中分配的局部数据块的大小 ,向该数据块写入了过多的数据,导致数据越界,结果覆盖了别的数据。可以理解为在长字符串中嵌入一段代码,并将过程的返回地址覆盖为这段代码的地址,这样当过程返回时,程序就转而开始执行这段自编的代码了,比如如下这段程序:
#include<std io. h>
Int  main ()
{
Char name [8] ;
Printf( “please   t ype  your  name :”) ;
gets (name) ;
pr intf( “He llo. %s !” ,name) ;
return  O ;
}
编译并且执行,输入
Ipxod iAAAAAAAAAAAAAAAA ,执行完gets (name)之后,堆栈如下:
内存底部 内存顶部
name EBP ret
〈一一一一一一一 [ ipxod iAA] [AAAA] [AAAA]………
?& name
堆栈顶部 堆栈底部
由于我们输入的 name 宇符串太长,name 数组容纳不下,只好向内存顶部继续写 ‘A’,如果提前申请动态内存就可以避免堆栈溢出。而此例由于堆栈的生长方向与内存的生长方向相反,这些‘A ’覆盖了堆栈的老的元素。‘EBP ret’都被‘A‘。在 main 返回的时候,就会把‘AAAA ’的 ASCII码:Ox41414141作为返回地址,CPU 会试图执行0x41414141处的指令,结果出现错误。这就是一次堆栈溢出。
程序运行的堆与栈的空间大小都是由软件开发人员自己定义分配大小的 。一般出现问题就是为DSP 软件运行设置的堆或栈的空间太小 ,而导致程序不能正常运行。堆或栈空间太小编译生成out文件时,是不会报错的。如果程序出现莫名的跑飞情况可以试着改变Stack、Size 、Heap  Si ze的参数值。
2.2数组溢出
数组溢出就是数组下标超出定义数组的下标大小。而通过数组下标访问时,下标超过了数组的边界,这样可能改写其他地址的数据,造成程序跑飞(一般伴随其他系统关键数据被 修改)。当数组溢出时,一般情况下,这个地址仍然指向 RAM。既然是RAM,当然是可读可写的。如果溢出数组的数据地址已经被程序分配做变量b的存储。对溢出数据进行操作时,会直接改变变量b的数值。因为b的数值被改变,所以会引起程序中数据混乱,如果b为系统关键变量,例如开关中断仲裁计数器,会导致中断无法打开,从而引起程序死机。
数组溢出原因:
(1)有可能是使用未初始化的变量作为下标方位数组。当变量未进行初始化时,变量的值是一个随机数。当变量的值大于数组定义大小时,就会导致数据溢出。如图,变量未初始化时其值为随机数。



(2)还有可能是通过计算关系计算下标,而在异常的情况下下标会越界。使用计算关系 计算下标时,当计算出错或者计算数值变化导致计算出的下标超出数组定义范围时,同样会 导致数据溢出。
(3)在SCI 通信中,如果在通讯线上有来自外部强干扰,可能导致 SCI 接收数组下标地址被篡改,那么这个地址返回的值也是错误的。单板模拟测试,在两块通讯芯片的SCI 通讯线上施加4.0V-6.0V之间,频率在100KHz-130KHz 之间的方波干扰时会导致 SCI 接收数组下标被篡改,从而导致数组溢出。如图,红色框线区域为被篡改的区域。

2.3访问指向错误指针
访问指向错误指针是指指针指向不可执行代码的地址,如芯片保留区、无代码区。例如指针作为函数参数传递时,指针未指向具体的地址,而在函数中使用,可能出现死机的情况。这是因为无法确认指针地址,如果指向错误地址会导致芯片死机。这些“指针未初始化”或“指针未指向具体变量”的问题编译器不会提示错误,最多提示警告。当编译时没有注意到这些问题时,就会导致最终编译的程序在运行时出现死机等问题。
比如如下这段程序:
Int  main ()
{
int l6* Al = NULL ;
int  TEST ;
Al  =  ( int*)  TEST ;
}
指针指向变量TEST,但变量 TEST未初始化(此时变量为随机数),即指针指向一个不确定地址 ,可能导致死机。而“指针未指向具体变量”作为函数参数传递,编译时不会报错,但有告警,在debug 状态下运行时直接就跑死了,也算是暴露问题了。
2.4无条件死循环
比如使用 whi le (l) ,for ( ;;)等语句,如果程序进入到死循环中无法跳出,也会导致程序死机。在编程中,一个无法靠自身的控制终止的程序称为死循环。而像while ( l)、for( ; ; ) 这样的没有条件就可以进入 ,进入后又无法靠自身控制终止,就是无条件死循环。为防止这样语句出现,可以在外部加入进入的条件,或者在内部做时间计数器,确认一定时间后,程序可以自行跳出,而不是无条件执行。
比如如下这段程序:
Int  main ()
{
Whi le ( x )
{
……………………….
}
}
While (x),X表示等待电平变化,正常情况下x都会变为0,如果x不变(例如硬件故障)则可能导致一直执行 while (x),导致芯片死机。
2.5看门狗没有关闭
有的芯片即使没使用看门狗,开机时也有可能意外自动开启了最小周期的看门狗,导致软件不断复位,这个要看芯片子册,最好在程序复位后首先应该显示清除看门狗再关闭看门狗。如果需要打开看门狗功能,要确认好主循环最大时间,不要将看门狗设定时间太短,导致主循环无法跑完 。
3、预防措施
3.1尽可能规避触发死机条件
3.1.1.在程序设计中防止堆栈的溢出,要解决两个问题:
(1)精确计算系统分配给用户的堆栈大小,假设是M。
(2)精确计算用户需要堆栈的大小,假设是N。
要求 M≥N,下面分别分析这两个问题。
计算系统分配给用户的堆棋大小
在程序设计中,编译器按照用户的设置,将所有的变量存放在片内和片外的 RAM 中。片内变量分配好空间后,将剩下的空间全部作为堆枝空间,这个空间是最大可能的堆梳空间。以下分析放在片内RAM 的变量。一般把变量分为两种情况:
(1)用作函数的参数和函数返回值的局部变量。这种变量尽量在寄存器组中存放。为了 方便讨论,假设统一用寄存器组0,具体的地址为 0x00一0x007。最多可以传递3个参数,如果参数的个数比较多,就将多余的参数放到内存(0x08以后的地址)中存放。这里假设每个函数的参数都不大于3个。
(2)我们在程序中定义的全局变量,以及不是用作函数的参数和函数返回值的局部变量。以上两种变量在内存中 Ox08 地址以后存放,存放完毕后将堆栈指针SP指向分配了变量的片内RAM 的最后一个字节。在根据芯片堆栈的规则来计算出系统分配给用户的堆栈空间。
计算用户需要堆栈的大小
堆栈区到底留多大才算足够呢?用户需要堆栈的大小可以从普通子函数和中断子程序的嵌套层数来计算。普通子函数的调用比较简单,每次调用时就是将函数的返回地址保存在堆栈中,这个地址占两个字节。函数嵌套调用时,从最内层的子函数算起,总的堆栈需求字节数为嵌套的层数乘以2.
中断子程序使用中断发生前的寄存器组的,中断的堆栈需求为 15 字节;中断子程序使用自己专用的寄存器组。这种堆栈的需求为 7 个字节。按照以上需求,可以累积计算用户需要的堆栈空间大小。
设计好堆栈的大小,可以很好的避免堆栈溢出问题。从而解决由于堆栈溢出而引起的死机问题。初始化阶段对堆栈空间填充固定标志,并在运行过程中检查这些标志的完整性,从而评估出堆栈空间,在开发阶段正确设置堆栈空间大小。
3.1.2.关于数组溢出问题,只要在应用下标前对下标的范围进行判定,保证下标范围正常 后再使用,如果下标超出范围,可以不进行数组操作或将下标强制清零等处理。这样即使芯片受到外部强信号干扰,也能尽可能的降低影响。
比如如下这段程序:
void  SciDeal (voi d)
{
…………………………
if (j  >= 17)
{
j =  17 ;
}
RecData [j++]  =  TempData [i] ;
………………………
}
如图:加入下标判定后再使用,注入干扰时数组内容被篡改,数组后面区域值不会被篡改。


3.1.3.访问指向错误指针防护。芯片手册上指引芯片本身有一种保护机制能够捕获到错误,当芯片捕获到这种错误时会进入默认中断(系统定义但未使用的中断称为默认中断),前提是指针指向的错误地址里面数据值为 0 或 0xFF。访问指向错误地址时,程序跳转到默认中断后,可在默中断进行紧急处理,将CPU 置于受控状态。
如图初始化 RAM 值为 0

3.1.4.无条件死循环防护。在系统设计时建立死循环退出机制:①外部加入进入的条件,② 在内部做时间计数器,确认一定时间后,程序序可以自行跳出。
在外部加入进入条件 :
Int  mai n ()
{
if (G_ableFlg == True)
   {
while   ( x )
{
           ……………
      }
   }
}
在内部做时间计数器 :
while ( x )
{
   …………
Cnt++ ;
if(Cnt >= Times)
{
break ;
}
}
3.1.5.正确使用看门狗、中断等功能。在使用看门狗、中断等功能前,要对其有深刻的理 解。在异常中断函数中,关波处理,并等待看门狗溢出进行恢复DSP:分配好时序,不要将数据全部分配到一起进行处理:尽量减少中断嵌套:中断调用周期要提前设定好,在中断中要有响应和清除中断标志,避免中断无法跳出;中断中数据运行时间不能大于或等于中断调用周期;在使用会在中断中被修改的变量时,要确认变量类型,并且要关闭中断后再调用,防止数据被更改等。
3.1.6.为了更好的防止程序死机问题及其他BUG 存在。可以通过优化在编写程序过程中采用特定的方法,以提高软件的可控制性。大致可将其分为:避免冗余、规范的软件编写、良好的软件架构以及其他措施等。
3.2加强故障检测
加强对死机故障的检测,芯片本身要在默认中断中做故障判断及故障存储等。保证触发死机时,可以较快捕捉错误。其他芯片可以通过通讯状态来判断是否可能触发死机问题。
3.3触发死机后处理
当触发死机时,若芯片本身无法继续运行,所以要通过相互通讯来判断是否可能死机。当通讯超时时,其他芯片要清除接收数据,并作出相应处理。防止一直默认最后一次接收的数据而导致严重故障。当触发死机时,若程序可运行,进入默认中断时,在中断中会进行关波处理,并关闭喂狗功能,使芯片复位。
四、结论
本文结合发生的故障现象,分析了DSP 程序死机时软件方面的问题。列举出多条可能导致死机的原因,并逐一阐述是如何导致死机。针对这些引起死机的原因,分别阐述了在编写程序时如何规避管控触发死机条件;程序在运行时,如何加强死机检测,保证尽快确认问题,对后续处理提供好的应对条件;触发死机后如何去管控措施,将故障后损失尽量降低到最小。
只有在程序编写时提前规避可能触发故障的原因,同时加强故障检测,在第一时间发现故障并及时处理故障,才能使故障发生时,将故障造成的损失降到最低,保证产品的安全性。
参考文献
1.秦 EV-QDDJKZQKZB_Tl.00.0  2014-03一10[S]。
2.雷电.96 系列单片机C 语言函数的重入与非重入性[J].微计算机信息,1996(2)。
3.赵利民. C51堆栈构成与空间需求分析[J].自动化与仪器仪表,2013 (3)。
投稿 打印文章 转寄朋友 留言编辑 收藏文章
  期刊推荐
1/1
转寄给朋友
朋友的昵称:
朋友的邮件地址:
您的昵称:
您的邮件地址:
邮件主题:
推荐理由:

写信给编辑
标题:
内容:
您的昵称:
您的邮件地址: