[应用相关] 程序的位置与运行时间有关

[复制链接]
716|11
 楼主| characteristic 发表于 2019-7-22 15:21 | 显示全部楼层 |阅读模式
一、概述
  在我测量mian函数大循环的周期时,发生了怪事:我一点也没有更改main函数的代码,只在初始化时添加了一些无用的语句,结果测量时间发生了巨大的差异。

 楼主| characteristic 发表于 2019-7-22 15:22 | 显示全部楼层
二、事件详情

1、测试代码

main函数
  1. /**
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url]  主函数
  3.   * @param  无
  4.   * @retval 无
  5.   */
  6. int main(void)
  7. {        
  8.         LED_GPIO_Config();      
  9.         /* USART1 config 115200 8-N-1 */
  10.         USART1_Config();

  11.      /**
  12.       * @brief  通过注释掉程序,可以更改代码的长度
  13.       * @param  当注释的只剩下一个赋值等式的时候,计时长度值是0x116638
  14.       * @retval 当注释的剩下三个赋值等式的时候,计时长度值是0xEA726
  15.       */
  16.         DMA_USART1_Config();
  17.         
  18.         NVIC_Configuration();
  19.         SysTick_Init();     
  20.         SysTick_Time_Init(&UseDMATime);
  21.         for(;;)
  22.         {     
  23.             SysTick_Time_Start();
  24.             LED1(ON);LED2(OFF);LED3(OFF);
  25.             Delay();
  26.             LED1(OFF);LED2(ON);LED3(OFF);
  27.             Delay();
  28.             LED1(OFF);LED2(OFF);LED3(ON);
  29.             Delay();
  30.             SysTick_Time_Stop();
  31.         }
  32. }


Delay函数
  1. static void Delay(void)     //简单的延时函数
  2. {     
  3.    
  4.         uint16_t i;
  5.         
  6.         /*填充将要发送的数据*/
  7.         for(i = 0;i < SENDBUFF_SIZE ; i++)
  8.         {
  9.             SendBuff[i]     = (uint8_t)i;
  10.         }
  11.    
  12. }

 楼主| characteristic 发表于 2019-7-22 15:23 | 显示全部楼层
说明:

(1)测量代码段
  1.             LED1(ON);LED2(OFF);LED3(OFF);
  2.             Delay();
  3.             LED1(OFF);LED2(ON);LED3(OFF);
  4.             Delay();
  5.             LED1(OFF);LED2(OFF);LED3(ON);
  6.             Delay();


(2)无效代码段

  之所以称之为无效,实际上指的是“这些代码在程序中起到的是很次要的作用,主要是给CPU一些空指令,当然也会起到改变代码量的作用”。
  1. LED_GPIO_Config();      
  2.         /* USART1 config 115200 8-N-1 */
  3.         USART1_Config();

  4.      /**
  5.       * @brief  通过注释掉程序,可以更改代码的长度
  6.       * @param  当注释的只剩下一个赋值等式的时候,计时长度值是0x116638
  7.       * @retval 当注释的剩下三个赋值等式的时候,计时长度值是0xEA726
  8.       */
  9.         DMA_USART1_Config();



(3)与测量计时有关的代码
  1. SysTick_Init();     
  2. SysTick_Time_Init(&UseDMATime);
  3. SysTick_Time_Start();
  4. SysTick_Time_Stop();


关于测量计时代码的实现在随笔STM32之系统滴答定时器中进行了详细讲解。
 楼主| characteristic 发表于 2019-7-22 15:24 | 显示全部楼层
2、奇怪现象

  DMA_USART1_Config是在大循环之前调用的一个无用的函数,实际上可以称之为空函数或者延时函数。通过注释掉里边的语句可以改变排在DMA_USART1_Config代码段之后代码在Flash上的位置,也可以改变整个代码段的量(尽管很小)。
  1. void DMA_USART1_Config(void)
  2. {
  3.         DMA_InitTypeDef DMA_InitStructure;
  4.         
  5.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;   

  6.         /*传输大小DMA_BufferSize=SENDBUFF_SIZE*/   
  7.         DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
  8.         
  9.         /*外设地址不增*/        
  10.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;


  11. }


笔者发现,当这个函数完全保留三行语句的时候,while循环测出来的滴答计时器脉冲数是0xEA726(0d960294);而当注释掉只剩下一行语句时,脉冲数变为0x116638(0d1140280)。这中间的差距是0d179986,占0xEA726的百分比是18.7%。也就是说注释语句后的代码执行时间,比没有注释时的时间多了将近1/5,这值得考虑其中的原因。
 楼主| characteristic 发表于 2019-7-22 15:25 | 显示全部楼层
三、分析与结论

1、分析

     测量代码段中有关LED操作的代码执行时间几乎可以忽略,而占主要运行时间的是Delay函数,只要分析Delay函数,就能找到其中的问题。

Delay函数
  1. static void Delay(void)     //简单的延时函数
  2. {     
  3.    
  4.         uint16_t i;
  5.         
  6.         /*填充将要发送的数据*/
  7.         for(i = 0;i < SENDBUFF_SIZE ; i++)
  8.         {
  9.             SendBuff[i]     = (uint8_t)i;
  10.         }
  11.    
  12. }


Delay函数在两种情况下的反汇编代码

在完全保留代码的情况下
403035d3564d3bd1e8.png

在注释掉部分代码的情况下
247955d3564e2b8cf8.png

可以看到Delay函数的反汇编代码内容没有改变,改变的只是代码在Flash中的位置(当然也是程序执行时的位置)。       而后,我有试着在
DMA_USART1_Config代码的基础(3行语句)上不断增加代码,发现计时脉冲数周期性的在0xEA726、0x116638两个中变换。

       由此可以确定,就是由于代码的位置改变了程序的运行时间,也即改变了程序的运行速度。
 楼主| characteristic 发表于 2019-7-22 15:25 | 显示全部楼层
2、结论

  即使是同样的代码,通过改变代码的位置可以改变代码的运行时间。而最根本的原因是有些指令的周期给指令所在的Flash中的位置有关。

 楼主| characteristic 发表于 2019-7-22 15:26 | 显示全部楼层
3、还未完成的工作

  但是,由于J-link硬件调试时,单步调试误差太大,取得的值很有出入,难以确定究竟是Delay函数中哪些指令引起时间偏差。
wowu 发表于 2019-8-12 11:49 | 显示全部楼层

非常感谢楼主分享
xiaoqizi 发表于 2019-8-12 12:01 | 显示全部楼层
非常感谢楼主分享
木木guainv 发表于 2019-8-12 12:05 | 显示全部楼层
非常感谢楼主分享
磨砂 发表于 2019-8-12 14:00 | 显示全部楼层
非常感谢楼主分享
晓伍 发表于 2019-8-12 14:02 | 显示全部楼层
非常感谢楼主分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

18

主题

367

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部