STM32 MCU一次计算优化和提速

1、背景

    STM32 MCU对25.6Kb数据进行压缩,丢掉每个数据的低4位然后2个字节拼接为1个字节。发现处理耗时竞达1ms以上,于是开始进行优化,最后达到200us的效果,提速5倍以上。

2、优化

2.1优化前

  HAL_GPIO_WritePin(TestPB12_GPIO_Port, TestPB12_Pin, 1);
  #if (USE_BINNING)
   ImgCompressTo4Bit(img_ptr + PACKAGE_HEADER_SIZE, ImgSampBuf, IMG_SIZE);
  #else
    memcpy(img_ptr + PACKAGE_HEADER_SIZE, ImgSampBuf, IMG_SIZE);
  #endif
  HAL_GPIO_WritePin(TestPB12_GPIO_Port, TestPB12_Pin, 0);

该处理过程耗时1ms60us。

2.2 第一次优化

考虑到过多的for循环,会导致效率变低,于是一次处理4个字节。

/**   
 * @brief compress a arrary with high 4bit and low 4bit.    
 * @param[out]      *pDst arrary to be filled  
 * @param[in]       *pSrc input arrary   
 * @param[in]       len src length  
 * @return   dst length.   
 *   
 */
int ImgCompressTo4Bit(uint8_t *pDst, uint8_t *pSrc, int srcLen)
{
  /*loop Unrolling */
  uint32_t dstLen = srcLen >> 1;
  uint32_t blkCnt = dstLen >> 2u;
  
  uint32_t halfOffset = dstLen;
  uint8_t * ptrHigh = pSrc; // high 4 bit
  uint8_t * ptrLow  = pSrc + halfOffset; // low 4 bit

  while(blkCnt > 0u)
  {
    *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4);
    *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4);
    *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4);
    *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4);
    blkCnt--;
  }

  blkCnt = dstLen % 0x4u;

  while(blkCnt > 0u)
  {
    *pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>4);
    blkCnt--;
  }
  
  return dstLen;
}

优化后:一次处理4个数据时间为640us。如果进一步 一次处理8个数据,时间为600us。

 

 2.3 第二次优化

考虑到MCU是32位机器,那么使用u32类型数据进行处理,可以提高效率。

int ImgCompressTo4Bit(uint8_t *pDst, uint8_t *pSrc, int srcLen)
{
  /*loop Unrolling */
  uint32_t dstLen = srcLen >> 1;
  uint32_t blkCnt = dstLen >> 2u;
  
  uint32_t halfOffset = dstLen;
  uint32_t * ptrHigh = (uint32_t*)pSrc; // high 4 bit
  uint32_t * ptrLow  = (uint32_t*)(pSrc + halfOffset); // low 4 bit
  uint32_t * dst  = (uint32_t*)pDst;

  while(blkCnt > 0u)
  {
    *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4);
    blkCnt--;
  }

  blkCnt = dstLen % (0x4u);

  while(blkCnt > 0u)
  {
    *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4);
    blkCnt--;
  }
  
  return dstLen;
}

优化后速度达到240us。

  2.4 第三次优化

同样考虑降低for循环的次数,一次处理4个u32,实际上是16个字节的数据。

int ImgCompressTo4Bit(uint8_t *pDst, uint8_t *pSrc, int srcLen)
{
  /*loop Unrolling */
  uint32_t dstLen = srcLen >> 1;
  uint32_t blkCnt = dstLen >> 2u >> 2u;
  
  uint32_t halfOffset = dstLen;
  uint32_t * ptrHigh = (uint32_t*)pSrc; // high 4 bit
  uint32_t * ptrLow  = (uint32_t*)(pSrc + halfOffset); // low 4 bit
  uint32_t * dst  = (uint32_t*)pDst;

  while(blkCnt > 0u)
  {
    *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4);
    *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4);
    *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4);
    *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4);
    blkCnt--;
  }

  blkCnt = dstLen % (0x4u*0x4u);

  while(blkCnt > 0u)
  {
    *dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>4);
    blkCnt--;
  }
  
  return dstLen;
}

优化后速度达到180--200us左右。

3、总结

基于c语法的优化:减少循环处理的次数。

基于芯片特性的优化:使用u32数据,提高处理效率。

经过3次简单的优化,1ms60us的处理降低到200us实现原有的操作。

 

posted on 2019-11-29 10:18  啊哈彭  阅读(3059)  评论(0编辑  收藏  举报

导航