标签:很多 清单 没有 cpu 变量 efi 情况 fine data
1.内存对齐1.2 内存对齐作用和原因
各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台的要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为 32位)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。这也是空间和时间的博弈。
2.ARM平台下内存对齐
在ARM中,有ARM和Thumb两种指令。ARM指令:每执行一条指令,PC的值加4个字节(32bits),一次访问4字节内容,该字节的起始地址必须是4字节对齐的位置上,即地址的低两位为bits[0b00],也就是说地址必须是4的倍数。Thumb指令:每执行一条指令,PC的值加2个字节(16bits),一次访问2字节内容,该字节的起始地址必须是2字节对齐的位置上,即地址的低两位为bits[0b0],也就是说地址必须是2的倍数。
遵循以上方式叫对齐(aligned)存储访问操作,不遵守这样方式称为非对齐(unaligned)存储访问操作。SylixOS下的ARM平台遵守对齐方式。
ARM平台下由于内存对齐产生的问题,如程序清单 2.1,是一段由于ARM平台下遵守内存对齐访问产生问题的代码,代码是一个简单的宏定义将VAL值赋值到DATA地址上。在程序中我们无法保证传进的参数DATA是4的整数倍,所以导致了会出现内存访问异常的现象。程序在运行中出现地址访问错误后退出。
程序清单2.1 平台下问题代码
…
#define EC_WRITE_U32(DATA, VAL) \
do {
*((uint32_t *) (DATA)) = cpu_to_le32((uint32_t) (VAL));
} while (0)
…
3.ARM平台下解决方案
上述问题可以修改应用层代码去避免此类问题。如程序清单3.1,我们定义宏如果不是X86平台,直接将uint32_t内存地址强制转换成uint8_t地址,再将数据VAL强制拆分成4个uint8_t型数据分别赋值到对应的uint8_t内存地址上。
程序清单3.1 ARM平台下避免字节对齐访问
…
#ifdef X86_PLATFORM
#define EC_WRITE_U32(DATA, VAL) \
do { \
*((uint32_t *) (DATA)) = cpu_to_le32((uint32_t) (VAL));
} while (0)
#else
#define EC_WRITE_U32(DATA, VAL) \
do { \
*((uint8_t *) (DATA)) = (cpu_to_le32((uint32_t) (VAL))) & 0xff
*(((uint8_t *) (DATA)) + 1) =(cpu_to_le32((uint32_t)(VAL)) >> 8) & 0xff;
*(((uint8_t *) (DATA)) + 2) = (cpu_to_le32((uint32_t) (VAL)) >> 16) & 0xff;
*(((uint8_t *) (DATA)) + 3) = (cpu_to_le32((uint32_t) (VAL)) >> 24) & 0xff;
} while (0)
…
标签:很多 清单 没有 cpu 变量 efi 情况 fine data
原文地址:http://blog.51cto.com/13443077/2060303