这可以更快完成吗?

时间:2014-07-23 12:13:58

标签: c performance

我有一个功能,它通过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;
       }
    } 

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位变量时检查没有低效率。)