zoukankan      html  css  js  c++  java
  • 程序的位置与运行时间有关

    一、概述

      在我测量mian函数大循环的周期时,发生了怪事:我一点也没有更改main函数的代码,只在初始化时添加了一些无用的语句,结果测量时间发生了巨大的差异。

    二、事件详情

    1、测试代码

    main函数

    /**
      * @brief  主函数
      * @param  无
      * @retval 无
      */
    int main(void)
    {        
            LED_GPIO_Config();      
            /* USART1 config 115200 8-N-1 */
            USART1_Config();
    
         /**
          * @brief  通过注释掉程序,可以更改代码的长度
          * @param  当注释的只剩下一个赋值等式的时候,计时长度值是0x116638
          * @retval 当注释的剩下三个赋值等式的时候,计时长度值是0xEA726
          */
            DMA_USART1_Config();
            
            NVIC_Configuration(); 
            SysTick_Init();     
            SysTick_Time_Init(&UseDMATime); 
            for(;;)
            {     
                SysTick_Time_Start();
                LED1(ON);LED2(OFF);LED3(OFF);
                Delay();
                LED1(OFF);LED2(ON);LED3(OFF);
                Delay();
                LED1(OFF);LED2(OFF);LED3(ON);
                Delay();
                SysTick_Time_Stop();
            }
    }

    Delay函数

    static void Delay(void)     //简单的延时函数
    {     
        
            uint16_t i;
            
            /*填充将要发送的数据*/
            for(i = 0;i < SENDBUFF_SIZE ; i++)
            {
                SendBuff[i]     = (uint8_t)i;
            }
        
    }

    说明:

    (1)测量代码段

                LED1(ON);LED2(OFF);LED3(OFF);
                Delay();
                LED1(OFF);LED2(ON);LED3(OFF);
                Delay();
                LED1(OFF);LED2(OFF);LED3(ON);
                Delay();

    2)无效代码段

      之所以称之为无效,实际上指的是“这些代码在程序中起到的是很次要的作用,主要是给CPU一些空指令,当然也会起到改变代码量的作用”。

            LED_GPIO_Config();      
            /* USART1 config 115200 8-N-1 */
            USART1_Config();
    
         /**
          * @brief  通过注释掉程序,可以更改代码的长度
          * @param  当注释的只剩下一个赋值等式的时候,计时长度值是0x116638
          * @retval 当注释的剩下三个赋值等式的时候,计时长度值是0xEA726
          */
            DMA_USART1_Config();

    (3)与测量计时有关的代码

    SysTick_Init();     
    SysTick_Time_Init(&UseDMATime); 
    SysTick_Time_Start();
    SysTick_Time_Stop();

      关于测量计时代码的实现在随笔STM32之系统滴答定时器中进行了详细讲解。

    2、奇怪现象

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

    void DMA_USART1_Config(void)
    {
            DMA_InitTypeDef DMA_InitStructure;
            
            DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;    
    
            /*传输大小DMA_BufferSize=SENDBUFF_SIZE*/    
            DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
            
            /*外设地址不增*/        
            DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
    
     
    } 

      笔者发现,当这个函数完全保留三行语句的时候,while循环测出来的滴答计时器脉冲数是0xEA726(0d960294);而当注释掉只剩下一行语句时,脉冲数变为0x116638(0d1140280)。这中间的差距是0d179986,占0xEA726的百分比是18.7%。也就是说注释语句后的代码执行时间,比没有注释时的时间多了将近1/5,这值得考虑其中的原因。

    三、分析与结论

    1、分析

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

    Delay函数

    static void Delay(void)     //简单的延时函数
    {     
        
            uint16_t i;
            
            /*填充将要发送的数据*/
            for(i = 0;i < SENDBUFF_SIZE ; i++)
            {
                SendBuff[i]     = (uint8_t)i;
            }
        
    }

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

    在完全保留代码的情况下

    在注释掉部分代码的情况下

       可以看到Delay函数的反汇编代码内容没有改变,改变的只是代码在Flash中的位置(当然也是程序执行时的位置)。

          而后,我有试着在

    DMA_USART1_Config代码的基础(3行语句)上不断增加代码,发现计时脉冲数周期性的在0xEA726、0x116638两个中变换。

           由此可以确定,就是由于代码的位置改变了程序的运行时间,也即改变了程序的运行速度。

    2、结论

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

    3、还未完成的工作

      但是,由于J-link硬件调试时,单步调试误差太大,取得的值很有出入,难以确定究竟是Delay函数中哪些指令引起时间偏差。

  • 相关阅读:
    Orcale 之基本术语一
    robots 小记
    划分子网例题详解 转
    jsp中利用response.senddirect(str)重定向,传递参数新思路
    当有多个form表单请求时如何处理?
    Form表单中的action提交路径问题
    用mysql workbench导出mysql数据库关系图
    eclipse中html编辑环境的搭建
    两个jsp文件运行后弹出对话框 下载文件问题
    Eclipse tomcat配置 未在Eclipse中添加.jar包出错
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/3752438.html
Copyright © 2011-2022 走看看