我正在ARM Cortex M0上做一个项目,它不支持未对齐(4字节)访问,我正在尝试优化未对齐数据的操作速度.
我将蓝牙低功耗访问地址(48位)作为6字节数组存储在一些作为数据包缓冲区的打包结构中.由于打包,BLE地址不一定从字对齐的地址开始,并且在优化我对这些地址的访问功能时遇到了一些复杂问题.
第一种也是最明显的方法是对数组中每个字节单独运行的for循环.例如,检查两个地址是否相同可以这样做:
uint8_t ble_adv_addr_is_equal(uint8_t* addr1, uint8_t* addr2)
{
for (uint32_t i = 0; i < 6; ++i)
{
if (addr1[i] != addr2[i])
return 0;
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
我在我的项目中做了很多比较,我想看看是否可以从这个功能中挤出更多的速度.我意识到对于对齐的地址,我可以将它们转换为uint64_t,并与应用的48位掩码进行比较,即
((uint64_t)&addr1[0] & 0xFFFFFFFFFFFF) == ((uint64_t)&addr2[0] & 0xFFFFFFFFFFFF)
Run Code Online (Sandbox Code Playgroud)
可以对写入进行类似的操作,并且它适用于对齐版本.但是,由于我的地址并不总是字对齐(甚至是半字),所以我必须做一些额外的技巧来完成这项工作.
首先,我想出了编译器宏的未经优化的噩梦:
#define ADDR_ALIGNED(_addr) (uint64_t)(((*((uint64_t*)(((uint32_t)_addr) & ~0x03)) >> (8*(((uint32_t)_addr) & 0x03))) & 0x000000FFFFFFFF)\
| (((*((uint64_t*)(((uint32_t)_addr+4) & ~0x03))) << (32-8*(((uint32_t)_addr) & 0x03)))) & 0x00FFFF00000000)
Run Code Online (Sandbox Code Playgroud)
它基本上将整个地址移位到前一个字对齐的存储器位置,而不管偏移量.例如:
0 1 2 3
|-------|-------|-------|-------|
|.......|.......|.......|<ADDR0>|
|<ADDR1>|<ADDR2>|<ADDR3>|<ADDR4>|
|<ADDR5>|.......|.......|.......|
Run Code Online (Sandbox Code Playgroud)
变
0 1 2 3
|-------|-------|-------|-------|
|<ADDR0>|<ADDR1>|<ADDR2>|<ADDR3>|
|<ADDR4>|<ADDR5>|.......|.......|
|.......|.......|.......|.......| …Run Code Online (Sandbox Code Playgroud)