我有一个功能,它通过DMA获取通过SPI接收的一些数据。对于通过SPI传输时的速度,三个10位数据被打包成一个32位字(带有两个填充位)。收到后,我需要将其解压缩回三个16位字(十个实际数据位和六个填充位)。
此功能经常被调用,因此任何速度优化都会使整体执行时间大大改善。它使用IAR EWARM 7.10作为编译器在STMicro Cortex M3上运行,优化设置为高,优化速度。
/*******************************************************************************
* Function Name : Unpack
* Description : the previous adc sample has been
DMA'd into an array
unpack each 32 bit transfer into 3, 10bit samples
( low 16 spi word ) ( high 16 spi word )
{ p15 p14 ch1_9:0 ch2_9:0 ch3_9:0 } 32 bit packing
* Input : output buf 16 bit word (10 bit adc, right justified)
input buf 32 bit data
count in 32 bit input words
* Output : None.
* Return : None.
*******************************************************************************/
void Unpack( u16* pDest, u16* pSrc, u16 packed32_count)
{
u16 i;
u32 n;
u16 dest_index = 0;
u16 src_index = 0;
for ( i = 0; i < packed32_count ; i++ )
{
n = pSrc[src_index]; //get high 16
n <<= 16;
n |= pSrc[src_index+1]; //get low 16
src_index+=2;
pDest[dest_index+2] = n & 0x3ff;
n >>= 10;
pDest[dest_index+1] = n & 0x3ff;
n >>= 10;
pDest[dest_index] = n & 0x3ff;
dest_index+=3;
}
}
答案 0 :(得分:2)
以下代码并不多,但它可能比上面的代码更快。您也可以尝试使用优化来编译速度。
void Unpack( u16* pDest, u32* pSrc, u16 packed32_count)
{
int i;
u32 val;
for(i = 0; i < packed32_count; i++)
{
val = pSrc[i];
pDest[2] = val & 0x3ff;
pDest[1] = (val >> 10) & 0x3ff;
pDest[0] = val >> 20;
pDest += 3;
}
}
答案 1 :(得分:1)
这可能会更快一点
void Unpack( u16* pDest, u16* pSrc, u16 packed32_count)
{
u32 n;
u16* pSrcEnd = pSrc + 2 * packed32_count;
while (pSrc < pSrcEnd)
{
n = *pSrc++; //get high 16
n <<= 16;
n |= *pSrc++; //get low 16
*pDest++ = (n>>20) & 0x3ff;
*pDest++ = (n>>10) & 0x3ff;
*pDest++ = n & 0x3ff;
}
}
答案 2 :(得分:0)
假设您的处理器是大端(如果不是,您可以在打包中对其进行排序,使打包/解包对称),您可以使用以下内容加载数据:
n = ((u32*)pSrc)[src_index++];
使用u32索引比使用u16更快。如果你有32位寄存器则使用16位效率不高。
您可以使用register
,但我怀疑优化工具已经这样做了:
register u32 src_index;
但如果经常使用它,你应该真正看一下生成的汇编代码(例如,在使用16位变量时检查没有低效率。)