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實現原有的操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM