Data abort为例子:数据非对齐访问异常
例子1 数据非对齐异常
1. 首先看call stack 如下图:
目的:Call stack反应出任务的调用流程。
2. 分析当前指令位置:
目的:从上如可以看出,
1)当前指令的大概执行位置,以及前后函数位置;2)得到当前指令的执行情况:如寄存器,变量,内存地址等等,比如现在可以看出R4 R0 R1这些相关寄存器的值。他们的值反应出对应的数据位置,比如数组。
3.分析寄存器现场:
目的:
( 1)这里R4寄存器的值就反应出一个数据位置0x001ff8AD,这个我们可以通过该位置,在Lis文件里面找到对应的数据。如下:
R4 地址对应的数据就是:NVRAM_EF_MMI_CACHE_SHORT_DEFAULT
( 2)最左边的一列数据就是stack dump信息,反应的是当时栈中最近执行的10条指令的地址,我们通过对这些地址的研究,也就可以找到出错的地方。
输入data.dump 0x001ff8ad 得到下图的数据:
从上图看出当访问0x1ff8a9地址(偏移是2c-->实际应用时要读这里的数据。
这里有人会问,cpu这个时候可以一次性取出0x1ff8a8地址开始的4个字节,不存在越过对齐边界,不需要两个CPU周期,为什么还会异常呢?
因为RISC体系是严格要求对齐的,这种情况也是属于非对齐的一种情况,LDRH指令是半字节访问,要求目标地址是访问数据单元字节数的整数倍。具体请参考CPU其他资料。
---综合以上我们就得出异常的大概两个位置:
函数:
1)CCC_nvram_enum_to_short_default()
{
kal_uint8id_index;
kal_uint16*tempbuf;
tempbuf = (kal_uint16 *)NVRAM_EF_MMI_CACHE_SHORT_DEFAULT; //对它的访问出现问题
id_index= mmi_cache_search_index(nDataItemId,nDataType);
buffer[id_index] = tempbuf[id_index];//这里是访问的位置
}
-----初步分析是对数组访问NVRAM_EF_MMI_CACHE_SHORT_DEFAULT[512] 这个数组的时候 有发生字节不对齐的问题。
原因是0x001ffb0d是一个奇数地址。存在问题。
以前版本为什么没有问题?就是因为该数组的地址是一个偶数地址。
解决方法:
方法1:__align(4)或者__align(2) 修饰NVRAM_EF_MMI_CACHE_SHORT_DEFAULT。这个当16bit访问的时候,就是对齐访问。
mmi_rp_mmi_cache.c
方法2:不做对齐访问修饰,改成8bit访问方式,也可以避免问题,因为字节访问不存在对齐的问题。