赞
踩
MTK异常LOG深入探讨mastervon 发表于 2010-8-23 23:42:00开篇序言:此篇意在对异常LOG有一个总体上面的了解。异常的LOG有很多信息,但是对不同的异常,需要看的LOG却不一样。刚接触MTK平台之时,我也犯过这样的错误:就是这么多的异常LOG,我应该怎样看?非把自己弄得昏头转向不可。待此篇结束之后,小弟会根据不同的异常情况,选取一些典型的例子,给大家演示怎样去看异常LOG。小弟不才,希望能抛砖引玉,望各位高手多多指教。
出现异常的时候,正如上一篇小弟写的《MTK异常流程处理》所述,会把异常信息写在一个structure中。这个structure的定义为:
typedef struct ex_exception_log_t
{
EX_HEADER_T header; //记录异常类型、异常发生时间
kal_char sw_version[EX_SWVER_LEN]; //版本号
EX_ENVINFO_T envinfo; //一些重要寄存器和内存信息
EX_DIAGNOSISINFO_T diaginfo; //系统状态
EX_CONTENT_T content; //异常信息主要内容
} EX_LOG_T;
1、EX_HEADER_T header;
typedef struct ex_exception_record_header_t
{
exception_type ex_type;
kal_uint8 ex_nvram;
kal_uint16 ex_serial_num;
} EX_HEADER_T;
exception_type ex_type;是异常类型,MTK系统中共有8种异常的类型,在小弟《MTK异常错误类型》一篇中有消息的介绍。
kal_uint8 ex_nvram;大家看看nvram_write_exception这个函数就会明白。NVRAM中有10项记录异常错误信息。若此变量的值为0xff,则表明该项没有写过,可以往此项记录异常错误信息。
kal_uint16 ex_serial_num;每次出现异常,ex_serial_num都会加1。因此,对于这个值,10个NVRAM项中,后面的应该比前面的大。正如小弟的《MTK异常处理流程》所述,NVRAM中10项是循环去写的。那么怎样判断已经循环了一圈?就是靠ex_serial_num的值去判断。假如当前项比前一项ex_serial_num小,证明循环了一圈。可以放心把这一项写上冲掉,写上新的异常信息。
2、kal_char sw_version[EX_SWVER_LEN];
这个不用说了,就是我们维护的版本号。
3、EX_ENVINFO_T envinfo;
typedef struct ex_environment_info_t
{
boot_mode_type boot_mode;
ex_rtc_struct rtc;
kal_char execution_unit[EX_UNIT_NAME_LEN];
kal_uint8 status;
kal_uint8 pad[2];
kal_uint32 stack_ptr;
kal_uint32 stack_dump[EX_STACK_DUMP_LEN];
kal_uint16 ext_queue_pending_cnt;
kal_uint32 ext_queue_pending[EX_QUEUE_TRACK];
kal_uint32 interrupt_mask[2];
kal_uint32 processing_lisr;
kal_uint32 lr;
} EX_ENVINFO_T;
boot_mode_type boot_mode;标识是什么模式开机,是按power键开机,还是RTC开机,还是USB开机,还是充电开机等等
ex_rtc_struct rtc;从RTC的寄存器中读出时间
kal_char execution_unit[EX_UNIT_NAME_LEN];记录出现异常时,当前的task
kal_uint8 status;记录出现异常时,当前task的状态
kal_uint8 pad[2];好像是保留值
kal_uint32 stack_ptr;异常出现时的SP值
kal_uint32 stack_dump[EX_STACK_DUMP_LEN];以上面的stack_ptr作为栈顶,搜索10个像是函数的地址,这些地址可以通过build目录中的sym文件猜测函数的调用关系。但这10个地址不一定准确,需要靠人脑去判断是否为正确的函数地址
kal_uint16 ext_queue_pending_cnt;当前task的外部队列中,残留还没有被处理的消息个数
kal_uint32 ext_queue_pending[EX_QUEUE_TRACK];当前task的外部队列中,残留还没有被处理的消息ID
kal_uint32 interrupt_mask[2];中断屏蔽寄存器值
kal_uint32 processing_lisr;假如lisr正在执行,这里会记录lisr正在运行的地址
kal_uint32 lr;异常发生时的lr寄存器的值
4、EX_DIAGNOSISINFO_T diaginfo;
typedef struct ex_diagnosis_info_t
{
EX_DIAGNOSIS_T diagnosis;
kal_char owner[EX_UNIT_NAME_LEN];
kal_uint8 pad[3];
kal_uint32 timing_check[EX_TIMING_CHECK_LEN];
} EX_DIAGNOSISINFO_T;
EX_DIAGNOSIS_T diagnosis;异常情况出现时,会检查系统是否已经有问题。比如说中断向量表是否被踩,stack是否被爆掉。所以假如这里不是显示health,则需要先解决系统的问题。
kal_char owner[EX_UNIT_NAME_LEN];假如出现了stack爆掉的情况,会显示哪个task或者hisr的名字
kal_uint8 pad[3];不知道有什么用,像是保留
kal_uint32 timing_check[EX_TIMING_CHECK_LEN];还不知道有什么用
5、EX_CONTENT_T content;
typedef union
{
EX_FATALERR_T fatalerr;
EX_ASSERTFAIL_T assert;
} EX_CONTENT_T;
这是一个联合体,假如是fatal error,则会填入fatal error的信息。假如是assert,则会填入assert的信息。(- -!有点罗嗦,抱歉!)
6、EX_FATALERR_T fatalerr;
typedef struct ex_fatalerror_t
{
EX_FATALERR_CODE_T error_code;
EX_DESCRIPTION_T description;
EX_ANALYSIS_T analysis;
EX_GUIDELINE_T guideline;
union
{
EX_CTRLBUFF_T ctrl_buff;
EX_TASKINFO_T task_info[EX_MAX_TASK_DUMP];
EX_CPU_REG_T cpu_reg;
} info;
} EX_FATALERR_T;
EX_FATALERR_CODE_T error_code;出现fatal error的时候,会记录error code1和error code2。这两个值特别重要,因为可以知道出现fatal error大概原因。从而选择不同的分析方法。
EX_DESCRIPTION_T description;我猜测是出现fatal error时,还可以输出一些附加信息。
EX_ANALYSIS_T analysis;与EX_DESCRIPTION_T description;变量一样。我猜测是出现fatal error时,还可以输出一些附加信息。
EX_GUIDELINE_T guideline;与EX_DESCRIPTION_T description;变量一样。我猜测是出现fatal error时,还可以输出一些附加信息。
EX_CTRLBUFF_T ctrl_buff;假如control buffer有问题,则会记录control buffer的一些信息。
typedef struct
{
kal_uint32 ex_ctrlbuf_size;
kal_uint32 ex_ctrlbuf_num;
EX_CTRLBUFF_INFO_T ex_ctrlbuf_top;
EX_CTRLBUFF_INFO_T ex_ctrlbuf_second;
EX_CTRLBUFF_INFO_T ex_ctrlbuf_third;
EX_CTRLBUFF_OWNER_T ex_monitor[3];
kal_uint32 ex_reserved[2]; /* reserved */
} EX_CTRLBUFF_T;
kal_uint32 ex_ctrlbuf_size; control buffer的大小
kal_uint32 ex_ctrlbuf_num; control buffer的数量
EX_CTRLBUFF_INFO_T ex_ctrlbuf_top;
EX_CTRLBUFF_INFO_T ex_ctrlbuf_second;
EX_CTRLBUFF_INFO_T ex_ctrlbuf_third;
control buffer出错时,有两种错误。一种是buffer数量太少,不足够被申请;另外一种是buffer里面的数据被踩坏。对于两种错误,这3个变量的意义都不一样。对于第一种错误,ex_ctrlbuf_top记录排名第一位申请最多buffer的模块的一些信息,ex_ctrlbuf_second记录排名第二多,ex_ctrlbuf_third记录排名第三多的信息:
typedef struct
{
kal_char ex_his_owner[8];
kal_char ex_his_source[16];
kal_uint32 ex_his_line;
kal_uint32 ex_his_count;
} EX_CTRLBUFF_HISTORY_T;
kal_char ex_his_owner[8];申请control buffer的模块
kal_char ex_his_source[16];申请control buffer的文件名
kal_uint32 ex_his_line;申请control buffer的地方在文件中第几行
kal_uint32 ex_his_count;申请control buffer的数量
对于第二种错误,ex_ctrlbuf_second记录被写坏的buffer的信息。ex_ctrlbuf_top是被踩坏的buffer的前一个buffer的信息。ex_ctrlbuf_third是被踩坏的buffer的后一个buffer的信息。
typedef struct
{
kal_uint32 ex_buf_NU_header1;
kal_uint32 ex_buf_NU_header2;
kal_uint32 ex_buf_KAL_header1;
kal_uint32 ex_buf_KAL_header2;
kal_uint32 ex_buf_KAL_header3;
kal_uint32 ex_buf_poolID;
kal_uint32 ex_buf_KAL_footer1;
kal_uint32 ex_buf_KAL_footer2;
} EX_CTRLBUFF_COMMON_T;
kal_uint32 ex_buf_NU_header1;假如buffer被申请出去了,这里是NULL。假如没被分配,这里记录下一个还未被分配的buffer的指针
kal_uint32 ex_buf_NU_header2;control buffer的ID
kal_uint32 ex_buf_KAL_header1;control buffer头部的一个标记“0xF1F1F1F1”,假如buffer被踩,这个标记会写成另外一个值
kal_uint32 ex_buf_KAL_header2;该control buffer是被哪个模块申请
kal_uint32 ex_buf_KAL_header3;control buffer的ID
kal_uint32 ex_buf_poolID;control buffer pool的ID
kal_uint32 ex_buf_KAL_footer1;觉得没有什么用
kal_uint32 ex_buf_KAL_footer2;底部的一个标记“0xF2F2F2F2”,假如buffer被踩或者buffer溢出时,这个标记会写成另外一个值
EX_TASKINFO_T task_info[EX_MAX_TASK_DUMP];
当task出现错误时,例如外部队列爆掉就会输出task的信息:
typedef struct
{
kal_char ex_task_name[8];
kal_char ex_task_stack_gp[8];
kal_uint32 ex_task_cur_status;
EX_QUEUE_T ex_task_external_q;
EX_QUEUE_T ex_task_internal_q;
kal_uint32 ex_reserved;
} EX_TASKINFO_T;
kal_char ex_task_name[8];task的名字
kal_char ex_task_stack_gp[8];每个task的堆栈的最顶部都会有一个标记“STACKEND”。假如堆栈爆了,会把这个标记写坏。所以可以从这个标记判断堆栈是否坏掉
kal_uint32 ex_task_cur_status;task当前的状态
EX_QUEUE_T ex_task_external_q;task外部队列的消息的信息
typedef struct
{
kal_uint8 ex_q_src_mod;
kal_uint8 ex_q_count;
kal_uint16 ex_q_msg_id;
kal_uint16 ex_q_cur_mes_no;
kal_uint16 ex_q_config_entry;
} EX_QUEUE_T;
kal_uint8 ex_q_src_mod;队列中若有相同的消息,这里记录发送消息的模块名字
kal_uint8 ex_q_count;队列中若有相同的消息,相同消息的数量
kal_uint16 ex_q_msg_id;队列中若有相同的消息,显示该消息的ID
kal_uint16 ex_q_cur_mes_no;当前外部队列中有一共有多少信息
kal_uint16 ex_q_config_entry;队列最大可以容纳多少个消息
EX_CPU_REG_T cpu_reg;假如发生了CPU触发的异常,则会把CPU寄存器的信息记录在这个structure中
7、EX_ASSERTFAIL_T assert;
typedef struct ex_assert_fail_t
{
kal_char filename[EX_ASSERTFAIL_FILENAME_LEN];
kal_uint32 linenumber;
kal_uint32 parameters[3];
kal_uint8 dump[EX_ASSERTFAIL_DUMP_LEN];
kal_uint8 guard[EX_GUARD_LEN];
} EX_ASSERTFAIL_T;
kal_char filename[EX_ASSERTFAIL_FILENAME_LEN];出现assert时候的文件名
kal_uint32 linenumber;出现assert的地方在文件的第几行
kal_uint32 parameters[3];EX_ASSERT可以输出3个变量信息,会记录在这里
kal_uint8 dump[EX_ASSERTFAIL_DUMP_LEN];EX_ASSERT_DUMP会输出10个buffer的信息,指针会记录在这里
kal_uint8 guard[EX_GUARD_LEN];这个不知道作用是什么
本文来自:我爱研发网(52RD.com) - R&D大本营
详细出处:http://www.52rd.com/Blog/Detail_RD.Blog_mastervon_24767.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。