PS死机案例系统死机的典型案例取数据异常所有中断均失效只有ARM核运行栈溢出,界外数据被破坏数据越界访问中断被误打开,并没有清除中断不能等到寄存器置位或者清零函数重入问题函数声明和实现的接口不统一双处理器的同步问题取数据异常非法指令FunctionA(){…}FunctionB(){Struct*pStr=(Struct*)m_malloc(sizeof(Struct));pStr-pC=A;….m_free(pStr);//不小心free了pStr,这时候pStr指向的数据块已经被其他数据所填充….pStr-pC;//调用A,但实际跳转到其他地址,可能进入指令预取异常中断,或者未定义指令异常中断,或者程序跑飞(最麻烦的)}取数据异常取数据异常中止(DataAbort)FunctionA(){char*p=GetPointer(index);//GetPointer没有写好,返回了一个非法的地址(乱七八糟的数据)….U8q=*p;//CPU遇到从一个非法地址取数而产生DataAbort异常,注意:如果是p=NULL是不会产生异常中断的,必须是一个CPU认为的不能取数的地址}所有中断均失效在607平台老的Framework上,有两个现象1.在第一幅开机动画处死机2.反复播放前一段开机铃声3.任何按键没有反应系统无任何中断产生,Melody部仅反复播放最开始送入的Midi数据,对用户来说是“死机”,实际是ARM核在bloop()中执行有限的几行代码。栈溢出,界外数据被破坏//#defineSMS_NUM10//UTXXXSMSnumber#defineSMS_NUM50//UTXXXSMSnumber….FunctionA{SMSLogsms[SMS_NUM];//仅仅修改宏定义是不够的,必须察看与之有关的所有代码….memset((void*)sms,0xFF,SMS_NUM*SMS_SiZE);//栈后面可能有其他全局量,被“无辜”的赋为0xFF….}数据越界访问FunctionA{….m=m_malloc(size);…m++;//不小心++,可能是其他方式导致其++…memset((void*)m,0,size);//堆中的数据被“无辜”破坏}数据越界访问可以看到,紧挨在m后面的数据被无辜的破坏,导致系统在其他状态下“死机”。所有的赋值语句都要慎重,特别是对某一地址指向的一段数据进行赋值的时候要特别小心。中断被误打开,且没有清除中断FunctionA{SetTimeXInt();//设置某个时钟,产生周期性中断DisnableTimeXInt();//禁止该时钟中断(不需要该时钟)}….FunctionB{DisnableAllInt();//禁止所有中断….EnableAllInt();//使能所有中断,误打开了TimeX中断}中断被误打开,且没有清除中断1.如果不需要该时钟,那么就要把时钟控制寄存器设置为禁止2.使能所有中断是危险的,必须使能那些需要使能的中断U32irqs=ReadIntEnableReg();…WriteIntEnableReg(irqs);使得该时钟中断频繁进入,几乎完全占用了CPU的MIPS,其他程序没有机会执行,从而表现出“死机”不能等到寄存器置位或者清零FunctionA{while(1){if((U8)(*BBIO_XXXX_XXXX)==0x01)break;//如果等不到这么办}}不能等到寄存器置位或者清#ifdef_DEBUGU32nCount=0;#endifFunctionA{#ifdef_DEBUGnCount=0;#endifwhile(1){一种可选的做法#ifdef_DEBUGnCount++;if(nCountXXXX)ASSERT(0);//做一个超时保护#endifif((U8)(*BBIO_XXXX_XXXX)==0x01)break;}}函数重入的问题FunctionA{….*BBIO_XXXX_XXXX|=0x08;//打开AD采样电路while(*BBIO_YYYY_YYYY==0x0b);//采样完成vol=*BBIO_ZZZZ_ZZZZ;//得到电压*BBIO_XXXX_XXXX&=0xF7;//关闭AD采样电路}如果函数c在调用A时,正在等待采样完成,被中断打断,函数D调用了A,完成采样之后,把采样电路关闭了,这样函数c就永远无法从A出来了。函数重入的问题1.可以在函数内部增加调试代码,来找到重入的证据2.也可以在系统级别避免类似函数的重入问题(避免中断调用此函数)3.如果无法避免重入,那只好关中断了函数声明和实现的接口不统一XXX.hS8A(U8a,LP_U8b,LP_U16c);YYY.hU8A(U8a,LP_U8b,LP_U16c,U16d);XXX.cS8A(U8a,LP_U8b,LP_U16c){…}双处理器的同步问题双处理器的通信方式(串口,双口RAM等)造成不能同步的原因往往是数据Buffer溢出,或者中断丢掉数据Buffer大小的合理设定,考虑“生产者”和“消费者”的活动状态;从系统角度考虑中断优先级的安排两边同步失调可能会造成死机“死机”预防(最重要)绝大部分的“死机”可以通过仔细的设计和编码预防主动设置“陷阱”,主动增加调试代码,在任何程序不该进入的地方设置“陷阱”来“捕获”它,一旦捕获有更多的信息来分析(使用StackInsight工具)在一些看起来没有任何问题的地方也要设置“陷阱”(数据越界访问和栈溢出等导致看起来没有问题的地方也容易无辜牵连,这也是“死机”分析的突破口)“死机”预防系统软件正常运行图系统软件异常运行图“死机”预防主动设置“陷阱”后的图陷阱“陷阱”就是中止程序正常运行的代码。最常用的就是ASSERT(0);或者软件中断或者reset系统(release)“死机”分析必现或者容易重现的“死机”分析,(Debug,代码走读,案例套用,版本比较)落入陷阱的“死机”分析(StackInsight输出文件)没有落入陷阱的,又很难重现的“死机”分析(陷阱没有设置全,运气不好)。重复1-2个星期的专项测试,争取重现,如果还重现不了,就让领导拍板是否可以量产。“死机”的“亡羊补牢”“陷阱”处让系统resetWatchdog“偷偷”地reset#ifdef_DEBUG#defineASSERT(x)DebugAssert(….)#else#defineASSERT(x)(if(FALSE==(U32)x)reset_req())#endif提高“死机”分析的能力扎实的基本功(C,汇编,硬件知识,各种仪器使用等)对系统的充分熟悉(BIOS,AP,Protocol,BBIC等)遇到问题多问“为什么”,并且找到真正的答案遇到问题,迎难而上,碰到难题应该庆幸,是提高自己的机会,“进一步海阔天空”StackInsight工具输出文件的熟练和完备的分析谢谢!谢谢!