PS死机案例及原因发现方法浅析

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

char *p = GetPointer(index);//GetPointer没有写好, 返回了一个非法的地址(乱七八糟的数据)
…. U8 q = *p;//CPU遇到从一个非法地址取数而产生 DataAbort异常,注意:如果是p=NULL是不会产生异常中断的, 必须是一个CPU认为的不能取数的地址 }
中断被误打开,且没有清除中 断
使得该时钟中断频繁进入,几乎完全占用了CPU的 MIPS,其他程序没有机会执行,从而表现出“死机”
1. 如果不需要该时钟,那么就要把时钟控制寄存器设置 为禁止
2. 使能所有中断是危险的,必须使能那些需要使能的中 断
U32 irqs = ReadIntEnableRRAM等) 造成不能同步的原因往往是数据 Buffer溢出,或者中断丢掉 数据Buffer大小的合理设定,考虑 “生产者”和“消费者”的活动状态; 从系统角度考虑中断优先级的安排 两边同步失调可能会造成死机
“死机”预防(最重要)


绝大部分的“死机”可以通过仔细的设计和 编码预防 主动设置“陷阱”,主动增加调试代码,在 任何程序不该进入的地方设置“陷阱”来 “捕获”它,一旦捕获有更多的信息来分析 (使用StackInsight工具) 在一些看起来没有任何问题的地方也要设置 “陷阱”(数据越界访问和栈溢出等导致看 起来没有问题的地方也容易无辜牵连,这也 是“死机”分析的突破口)
//#define SMS_NUM 10 //UTXXX SMS number
#define SMS_NUM 50 //UTXXX SMS number ….
Function A
{ SMSLog sms[SMS_NUM];//仅仅修改宏定义是不够的,必 须察看与之有关的所有代码 …. memset((void *)sms, 0xFF, SMS_NUM*SMS_SiZE);//栈后 面可能有其他全局量,被“无辜”的赋为0xFF
提高“死机”分析的能力




扎实的基本功(C,汇编,硬件知识,各种仪 器使用等) 对系统的充分熟悉(BIOS,AP,Protocol, BBIC等) 遇到问题多问“为什么”,并且找到真正的答 案 遇到问题,迎难而上,碰到难题应该庆幸,是 提高自己的机会,“进一步海阔天空” StackInsight工具输出文件的熟练和完备的分 析
“死机”的“亡羊补牢”


“陷阱”处让系统 reset Watchdog “偷偷”地 reset
#ifdef _DEBUG #define ASSERT(x) DebugAssert(….)
#else
#define ASSERT(x) (if(FALSE==(U32)x) reset_req()) #endif
谢谢!
谢谢!
所有中断均失效
在607平台老的Framework 上,有两个现象 1. 在第一幅开机动画处死机 2. 反复播放前一段开机铃声 3. 任何按键没有反应
系统无任何中断产生,Melody部仅反复播放最开 始送入的Midi数据,对用户来说是“死机”,实际 是ARM核在bloop()中执行有限的几行代码。
栈溢出,界外数据被破坏
PS 死机案例
系统死机的典型案例

取数据异常 所有中断均失效只有ARM核运行 栈溢出,界外数据被破坏 数据越界访问 中断被误打开,并没有清除中断 不能等到寄存器置位或者清零 函数重入问题 函数声明和实现的接口不统一 双处理器的同步问题
取数据异常
非法指令
Function A(){…} Function B() { Struct *pStr = (Struct *)m_malloc(sizeof(Struct)); pStr->pC = A; ….
m_free(pStr);//不小心free了pStr,这时候pStr指向的数据块已 经被其他数据所填充
…. pStr->pC;//调用A,但实际跳转到其他地址,可能进入指令预取 异常中断,或者未定义指令异常中断,或者程序跑飞(最麻烦的) }
取数据异常
取数据异常中止(DataAbort)
Function A() {
….
}
数据越界访问
Function A { …. m = m_malloc(size); … m++;//不小心++,可能是其他方式导致其++ … memset((void *)m, 0, size);//堆中的数据被“无辜”破坏 }
数据越界访问
可以看到,紧挨在m后面的数据被无辜的破坏, 导致系统在其他状态下“死机”。所有的赋值 语句都要慎重,特别是对某一地址指向的一段 数据进行赋值的时候要特别小心。
Function A
{ #ifdef _DEBUG nCount = 0; #endif while(1) { }
#ifdef _DEBUG nCount++; if(nCount>XXXX) ASSERT(0);//做一个超时保护
#endif
if((U8)(*BBIO_XXXX_XXXX) == 0x01) break; }
… WriteIntEnableReg(irqs);
不能等到寄存器置位或者清零
Function A { while(1) { if((U8)(*BBIO_XXXX_XXXX) == 0x01) break;//如果等不到这么办 } }
不能等到寄存器置位或者清
一种可选的做法
#ifdef _DEBUG U32 nCount = 0; #endif
“死机”预防
系统软件正常运行图 系统软件异常运行图
“死机”预防
主动设置“陷阱”后的图
陷阱 “陷阱”就 是中止程序 正常运行的 代码。最常 用的就是 ASSERT(0); 或者软件中 断或者reset 系统(release)
“死机”分析



必现或者容易重现的“死机”分析, (Debug,代码走读,案例套用,版本比较) 落入陷阱的“死机”分析(StackInsight输 出文件) 没有落入陷阱的,又很难重现的“死机”分析 (陷阱没有设置全,运气不好)。重复1-2 个星期的专项测试,争取重现,如果还重现 不了,就让领导拍板是否可以量产。
函数声明和实现的接口不统一
XXX.h S8 A(U8 a, LP_U8 b, LP_U16 c); YYY.h U8 A(U8 a, LP_U8 b, LP_U16 c, U16 d); XXX.c S8 A(U8 a, LP_U8 b, LP_U16 c) { … }
双处理器的同步问题




}
如果函数c在调用A时,正在等待采样完成,被中断打断,函 数D调用了A,完成采样之后,把采样电路关闭了,这样函数c 就永远无法从A出来了。
函数重入的问题
1. 可以在函数内部增加调试代码,来找到重入 的证据 2. 也可以在系统级别避免类似函数的重入问题 (避免中断调用此函数) 3. 如果无法避免重入,那只好关中断了
函数重入的问题
Function A
{ ….
*BBIO_XXXX_XXXX |= 0x08;//打开AD采样电路
while(*BBIO_YYYY_YYYY == 0x0b);//采样完成 vol = *BBIO_ZZZZ_ZZZZ;//得到电压
*BBIO_XXXX_XXXX &= 0xF7;//关闭AD采样电路
中断被误打开,且没有清除中 断
Function A { SetTimeXInt(); //设置某个时钟,产生周期性中断 DisnableTimeXInt();//禁止该时钟中断(不需要该时钟)
}
…. Function B
{
DisnableAllInt();//禁止所有中断 …. EnableAllInt();//使能所有中断,误打开了TimeX中断 }
相关文档
最新文档