1、背景

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

2、优化

2.1优化前

  HAL_GPIO_WritePin(TestPB12_GPIO_Port, TestPB12_Pin, );
#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, );

该处理过程耗时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 >> ;
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)>>);
*pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>);
*pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>);
*pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>);
blkCnt--;
} blkCnt = dstLen % 0x4u; while(blkCnt > 0u)
{
*pDst++ = ((*ptrHigh++) & 0xF0) | (((*ptrLow++) & 0xF0)>>);
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 >> ;
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)>>);
blkCnt--;
} blkCnt = dstLen % (0x4u); while(blkCnt > 0u)
{
*dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>);
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 >> ;
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)>>);
*dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>);
*dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>);
*dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>);
blkCnt--;
} blkCnt = dstLen % (0x4u*0x4u); while(blkCnt > 0u)
{
*dst++ = ((*ptrHigh++) & 0xF0F0F0F0) | (((*ptrLow++) & 0xF0F0F0F0)>>);
blkCnt--;
} return dstLen;
}

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

3、总结

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

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

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

STM32 MCU一次计算优化和提速的更多相关文章

  1. 如何获取STM32 MCU的唯一ID

    前段时间由于应用需要对产品授权进行限制,所以研究了一下有关STM32 MCU的唯一ID的资料,并最终利用它实现了我们的目标. 1.基本描述 在STM32的全系列MCU中均有一个96位的唯一设备标识符. ...

  2. 基于STM32的uCGUI移植和优化

    基于STM32的uCGUI移植和优化 首先在开始这个说明之前,要简要说明下具体的环境: 编译工具:MDK4.20 开发板:安富莱v2版开发板 调试器:JLink  v8盗版 移植篇 相信大家有移植经验 ...

  3. STM32 程序所占用空间计算 && FLASH存储的起始地址计算

    程序编译完成,会乘车program size .. 对STM32容量选型或者 计算FLASH 充当EEPROM起始地址时会用到此参数. 按照下面截图  程序空间 = (16700+732+4580)/ ...

  4. appium-基础搭建,适配,问题,优化,提速

    搭建开发环境,导入testng/log4j/maven 1.配置jdk环境 2.安装appium,下载eclipse-adt,配置appium环境 github.com/getlantern/foru ...

  5. 如何获取STM32 MCU的唯一ID及应用(转)

    源: 如何获取STM32 MCU的唯一ID

  6. MyEclipse6.5的速度性能优化大提速(转)

    MyEclipse是Eclipse的插件,也是一款功能强大的J2EE集成开发环境,支持代码编写.配置.测试以及除错.现在看一下MyEclipse6.5版本的速度性能优化大提速.优化MyEclipse6 ...

  7. 2019牛客多校第二场F Partition problem 暴力+复杂度计算+优化

    Partition problem 暴力+复杂度计算+优化 题意 2n个人分成两组.给出一个矩阵,如果ab两个在同一个阵营,那么就可以得到值\(v_{ab}\)求如何分可以取得最大值 (n<14 ...

  8. 递归、尾递归和使用Stream延迟计算优化尾递归

    我们在学数据结构的时候必然会接触栈(Stack),而栈有一个重要的应用是在程序设计语言中实现递归.递归用途十分广泛,比如我们常见的阶乘,如下代码: 1234 public static int (in ...

  9. 谈反应式编程在服务端中的应用,数据库操作优化,提速 Upsert

    反应式编程在客户端编程当中的应用相当广泛,而当前在服务端中的应用相对被提及较少.本篇将介绍如何在服务端编程中应用响应时编程来改进数据库操作的性能. 开篇就是结论 接续上一篇<谈反应式编程在服务端 ...

随机推荐

  1. JQuery实践--事件

    通过HTML网页所呈现的界面是异步的和事件驱动的.步骤: 建立用户界面 等待又去的事情发生 做出相应的反应 重复 浏览器所实现的事件模型 DOM第0级事件模型 事件处理程序是通过吧函数实例的引用指派到 ...

  2. P3474 [POI2008]KUP-Plot purchase

    思路:单调栈 提交:>5次 错因:单调栈写法有问题+前缀和写错 题解: 若有\(>=k\ \&\&\ <=2\times k\)的点,显然直接选他就行了. 否则,我们 ...

  3. 配置文件的属性ENC加密

    转载:https://www.cnblogs.com/zqyx/p/9687136.html 在micro service体系中,有了config server,我们可以把配置存放在git.svn.数 ...

  4. 如何实现对ArrayList排序 sort()

    package com.collection; import java.util.ArrayList;import java.util.Collections;import java.util.Com ...

  5. EditPlus 中添加 Win32 ASM 语法支持

    将以下内容保存为 Win32Asm.stx:然后选“工具”.“配置用户工具”.“设置与语法”.“添加”. “描述”=Win32Asm.“扩展名”=asm .”语法文件”选存入之文件,确定即可. #TI ...

  6. shell 显示详细信息

    MacdeMacBook-Pro:test macname$ ls -al | more total drwxr-xr-x macname staff : . drwxr-xr-x+ macname ...

  7. static关键字的用法小结

    static:是一个修饰符,用于修饰成员(成员变量,成员函数). 当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用,写法:类名.静态成员 static特点: 1.随着 ...

  8. windows环境rabbitmq安装步骤

    windows环境rabbitmq安装步骤: 1 提前安装erl; 2 rabbitmq安装后自动启动; 3 从开始菜单进入rabbit命令窗,启用插件;   下面是命令: 启用插件 rabbitmq ...

  9. CentOS 安装 MySQL PDO 扩展

    yum install php-pdo_mysql sudo service php-fpm restart

  10. 高性能高可用的微服务框架TarsGo的腾讯实践

    conference/2.3 高性能高可用的微服务框架TarsGo的腾讯实践 - 陈明杰.pdf at master · gopherchina/conferencehttps://github.co ...