This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28388D:将 memcpy 移动到 RAM -测量执行时间

Guru**** 2540720 points
Other Parts Discussed in Thread: TMDSCNCD28388D, C2000WARE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1118404/tms320f28388d-move-memcpy-to-ram---measure-execution-time

器件型号:TMS320F28388D
主题中讨论的其他器件:TMDSCNCD28388DC2000WARE

你好

我在 CPU1项目中编写了一个名为 HandleCmToCpu1IpcRequests 的函数、该函数通过以下方式将来自 CM->CPU1消息 RAM 的数据复制到结构中:

memcpy (&s_CanTelegramReceivedFromMaster、(const void *) ipcAddr、(size_t) sizeof (s_CanTelegramReceivedFromMaster)

在不久的将来、我必须从 RAM 运行函数 HandleCmToCpu1IpcRequests 和从该函数调用的所有其他函数。 这是必需的、因为 HandleCmToCpu1IpcRequests 可从 IRQ 中调用、而 CPU1的闪存可能正在擦除扇区的过程中。 因此、我首先尝试通过链接器命令文件将 memcpy 函数本身移动到 RAM、例如对于.TI.ramfunc 段

--library=rts2800_fpu64_eabi.lib (.text)

 

但这显然不是一个好主意、因为我收到了链接器警告、并且固件不再工作:

"./2838x_flash_lnk_cpu1.cmd"、行92:警告#10068-D:无匹配段

警告#10278-D:为".text:rts2800_fpu64_eabi.lib 段指定了加载放置 "。 本节包含链接器生成的复制表和 C/C++自动初始化所需的解压缩例程。  必须确保在执行 C/C++引导代码之前将此段复制到运行地址、或使用单个分配说明符(例如、">"存储器")进行放置。

之后、我将 memcpy 函数从 C:\ti\ccs1040\ccs\tools\compiler\ti-cgt-C2000-20.2.4.LTS \lib\src\memcpy.c 复制到我的项目中、将该函数重命名为 innoMemcpy 并将其移动到 RAM 中:

我现在通过 CPU 定时器1测量了 HandleCmToCpu1IpcRequests 函数的执行时间。 无论我为 innoMemcpy 使用哪种其他 pragma、如-opt_for_speed opt_level=2 (请参阅上图)、innoMemcpy数的速度始终是 rts2800_fpu64_eabi.lib 库 memcpy 的两倍。 因此、在下图中、第一行始终比第二行的因子2更快。

是否有什么想法会导致执行时间的差异? 如何使函数  innoMemcpy 的速度与  memcpy 一样快

谢谢、

Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    memcpy 函数不能是输出段.TI.ramfunc 的一部分。  这是因为它用于将 .TI.ramfunc 从闪存复制到 RAM。  它必须是 不同输出段的一部分。  包含 memcpy 的输出段只能分配给一个存储器范围。  它被加载到该存储器范围中、并从该范围运行。  您可能希望将包含 memcpy 的输出段分配到存储器的最快部分。

    请告诉我这些建议是否能解决问题。

    谢谢、此致、

    乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、George、

    我创建了一个名为 innoMemcopy 的函数、该函数与 memcpy 函数相同、但由于您在上面写的内容(memcpy 用于复制.TI.ramfunc)、因此刚刚重命名。 我的问题是不同的:

    为什么函数 memcpy (驻留在闪存上)的执行时间比 innoMemcpy 函数(驻留在 RAM 上)更快、无论 我在上面发布的第二张图片中使用哪种 pragma。 我所谈论的是:

    #pragma FUNCTION_OPTIONS (innoMemcpy、"-opt_for_speed");或 #pragma FUNCTION_OPTIONS (innoMemcpy、"-opt_level=2");

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    [引用 userid="459171" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1118404/tms320f28388d-move-memcpy-to-ram--measure-execution-time/4146596#4146596"]我创建了一个称为 memcpy 的函数、但将其重命名为 memcpy 函数的函数、该函数称为 memcpy、但将其命名为 memcpy/memcpy。]

    您是否从 TI 库复制了相同的函数?  

    此致、

    Vivek Singh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、我是这样做的。 我首先检查了 memcpy 函数所在的映射文件:

    然后、我打开文件并将其复制到我的项目中:

    您可以将上面的图片与我最初发布的第一张图片进行比较。

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是否可以向我发送我可以在我的设置中运行的示例 CCS 项目?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Vivek Singh、

    您可以在简单的 LED 闪烁示例程序中轻松重现此问题。 我可以为您提供代码、您只需将其复制到示例项目即可。

    首先、我在 TMDSCNCD28388D 评估 板上运行代码、并从 C2000器件产品中导入 CPU1/CM 闪烁 LED 示例。 我在配置闪存中编译了闪烁 LED CPU1项目、请参阅此处:

    我使用 CPU1计时器1进行时间测量。

    在 main()函数之前添加以下代码

    #define MEMCOPY_DEBUG_CODE 1
    
    #if MEMCOPY_DEBUG_CODE == 1
    
    #pragma CODE_SECTION(innoMemcpy, ".TI.ramfunc");
    #pragma FUNCTION_OPTIONS(innoMemcpy,"--opt_for_speed");
    //#pragma FUNCTION_OPTIONS(innoMemcpy,"--opt_for_space");
    //#pragma FUNCTION_OPTIONS(innoMemcpy,"--opt_level=2");
    void *innoMemcpy(void *to, const void *from, size_t n)
    {
         register char *rto   = (char *) to;
         register char *rfrom = (char *) from;
         register unsigned int rn;
         register unsigned int nn = (unsigned int) n;
    
         /***********************************************************************/
         /*  Copy up to the first 64K. At the end compare the number of chars   */
         /*  moved with the size n. If they are equal return. Else continue to  */
         /*  copy the remaining chars.                                          */
         /***********************************************************************/
         for (rn = 0; rn < nn; rn++) *rto++ = *rfrom++;
         if (nn == n) return (to);
    
         /***********************************************************************/
         /*  Write the memcpy of size >64K using nested for loops to make use   */
         /*  of BANZ instrunction.                                              */
         /***********************************************************************/
         {
            register unsigned int upper = (unsigned int)(n >> 16);
            register unsigned int tmp;
            for (tmp = 0; tmp < upper; tmp++)
            {
               for (rn = 0; rn < 65535; rn++)
               *rto++ = *rfrom++;
               *rto++ = *rfrom++;
               }
         }
    
         return (to);
    }
    
    uint16_t myMemcpyBuff[40];
    uint16_t myInnoMemcpyBuff[40];
    
    // The elements of the struct hold the CPU Timer 1 value in raw counts (200[MHz])
    struct ExecutionTimeMeasurement
    {
        int32_t s32_time_at_start_of_function;      // Time at start of function
        int32_t s32_prev_time_at_start_of_function; // Previous time at start of function
        int32_t s32_current_sample_time;            // Current sample rate of the task
        int32_t s32_current_execution_time;         // Current execution time
        int32_t s32_max_execution_time;             // maximum execution time
    };
    
    volatile struct ExecutionTimeMeasurement memcpy_ExecutionTime = {0, 0, 0, 0, 0};
    volatile struct ExecutionTimeMeasurement innoMemcpy_ExecutionTime = {0, 0, 0, 0, 0};
    
    #endif

    在进入无限循环之前在主函数内部启用 CPU 定时器1作为自由运行计数器(for (;;):

        // *****************************************************************************
        // Here we set up TIMER 1 as a free running timer for time measurement purposes.
        // *****************************************************************************
        // enable timer 1 to free run, can be read via: CPUTimer_getTimerCount(CPUTIMER1_BASE);
        //                                              CpuTimer1Regs.TIM.all; when adding the C-files f2838x_XYZ (e.g. f2838x_globalvariabledefs.c, f2838x_gpio.c...) to the project
        // Timer 1 runs per default with 200[MHz] system clock speed and counts down.
        CPUTimer_setPeriod(CPUTIMER1_BASE, 0xFFFFFFFF); // Initialize timer period to maximum
        CPUTimer_setPreScaler(CPUTIMER1_BASE, 0); // Initialize pre-scale counter to divide by 1 (SYSCLKOUT)
        CPUTimer_stopTimer(CPUTIMER1_BASE); // Make sure timer is stopped
        CPUTimer_reloadTimerCounter(CPUTIMER1_BASE); // Reload all counter register with period value
        CPUTimer_startTimer(CPUTIMER1_BASE); // start timer (counts down)

    现在、在无限循环中添加时间测量代码:

    #if MEMCOPY_DEBUG_CODE == 1
    
            memcpy_ExecutionTime.s32_time_at_start_of_function = CPUTimer_getTimerCount(CPUTIMER1_BASE);
            memcpy_ExecutionTime.s32_current_sample_time = memcpy_ExecutionTime.s32_prev_time_at_start_of_function - memcpy_ExecutionTime.s32_time_at_start_of_function;
            memcpy_ExecutionTime.s32_prev_time_at_start_of_function = memcpy_ExecutionTime.s32_time_at_start_of_function;
    
            // Memcopy 40 words from CM to CPU1 MSG RAM 0
            memcpy(&myMemcpyBuff[0], (const void *)0x38000, (size_t)sizeof(myMemcpyBuff));
    
            memcpy_ExecutionTime.s32_current_execution_time = memcpy_ExecutionTime.s32_time_at_start_of_function - CPUTimer_getTimerCount(CPUTIMER1_BASE);
            if(memcpy_ExecutionTime.s32_current_execution_time > memcpy_ExecutionTime.s32_max_execution_time)
            {
                memcpy_ExecutionTime.s32_max_execution_time = memcpy_ExecutionTime.s32_current_execution_time;
            }
    
    
    
            innoMemcpy_ExecutionTime.s32_time_at_start_of_function = CPUTimer_getTimerCount(CPUTIMER1_BASE);
            innoMemcpy_ExecutionTime.s32_current_sample_time = innoMemcpy_ExecutionTime.s32_prev_time_at_start_of_function - innoMemcpy_ExecutionTime.s32_time_at_start_of_function;
            innoMemcpy_ExecutionTime.s32_prev_time_at_start_of_function = innoMemcpy_ExecutionTime.s32_time_at_start_of_function;
    
            // innoMemcpy 40 words from CM to CPU1 MSG RAM 1
            innoMemcpy(&myInnoMemcpyBuff[0], (const void *)0x38400, (size_t)sizeof(myInnoMemcpyBuff));
    
            innoMemcpy_ExecutionTime.s32_current_execution_time = innoMemcpy_ExecutionTime.s32_time_at_start_of_function - CPUTimer_getTimerCount(CPUTIMER1_BASE);
            if(innoMemcpy_ExecutionTime.s32_current_execution_time > innoMemcpy_ExecutionTime.s32_max_execution_time)
            {
                innoMemcpy_ExecutionTime.s32_max_execution_time = innoMemcpy_ExecutionTime.s32_current_execution_time;
            }
    #endif

    您可以在调试器中检查最长执行时间、这对我来说如下:

    请注意 、如果计时器1回滚、测量的执行时间仍然正常、因为测量的执行时间、例如变量 memcpy_ExecutionTime.s32_curry_execution_time 内的执行时间也将面临回滚。

    另一个意见是 :从明天到8月11日,我将不在办公室,因此我无法对这一职务作出回应。 也许可以保持该帖子的打开状态、除非 您能够重现问题并找到根本原因?

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Inno、

    您是否尝试使用 CCS 分析功能来了解函数的执行时间? 您可以在以下链接中找到有关此功能的更多详细信息-

    https://software-dl.ti.com/ccs/esd/documents/c2000_profiling-on-c28x-targets.html

    代码快照中的注释表明您正在将数据从 CM 复制到 CPU1 MSG RAM、但 memcpy 函 数在 CPU1上执行、CPU1只有对 CMtoCPU1 MSG RAM 具有读取权限。 我是否遗漏了什么?

    您是否还检查了是否没有中断会中断 innoMemcpy 函数的执行?  

    我仍然希望您可以导出 CCS 工程并将其发送给我、因为它不仅涉及 C 代码、还涉及链接器 cmd 文件和编译配置、这将影响执行时间。

    此致、

    Vivek Singh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    HELO Vivek Singh。

    1) 1)我还可以在我返回后使用 CCS 的时钟周期测量方法、但在上面的链接中、您还可以找到"在 Sys/BIOS 中进行分析"一章中介绍的我应用的方法。 因此、我看到激励方法没有差异。  

    2) 2)我的 memcpy 函数 CMtoCPU1消息 RAM 中读取数据、并将其复制到 CPU1 RAM 中的变量(例如 RAMLS5存储器)。 这意味着该 memcpy 指令模拟从 CM 到 CPU1的 IPC 数据交换的一部分、因此 CPU1当然必须从只读消息 RAM 存储器中读取数据。

    3) 3)我将在接下来的几天内尝试用私人邮件向您提供我的项目。

    谢谢、

    Inno  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="459171" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1118404/tms320f28388d-move-memcpy-to-ram--measure-execution-time/4153046#4153046"]2) My memcpy 从 CPU1 RAM 变量读取 RAM 中的数据并将其复制到 CPU1 RAM 中。 这意味着该 memcpy 指令模拟从 CM 到 CPU1的 IPC 数据交换的一部分、因此 CPU1当然必须从只读消息 RAM 存储器中读取数据。

    好的、有道理。  

    将等待 CCS 项目检查这个。

    此致、

    Vivek Singh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Vivek Singh、

    我相信我的同事已经通过名为'emcpyProjects.zip'的文件中的项目向您发送了该项目。

    您是否能够在 CPU1项目中重现问题(请参阅文件'led_ex1_C28x_cm_blinky_cpu1.c')?

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我获得了项目,可以在闪存配置中运行.out,但不确定如何重现问题(BTW,当我尝试编译它时,它给出了错误)。 我应该在该项目中寻找什么?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Vivek Singh、

    这很奇怪、我可以毫无问题地编译项目。 要查看的重要代码位于以下散列定义之间:

    #if Memcopy_debug_code = 1.

    #endif

    当我运行项目时、 然后、我连续将40个字从 MSG RAM 复制到一个数组中、一次使用库中的"memcpy"(下图中的第344行)、一次使用相同的函数代码、但只使用不同的名称"innoMemcpy"(下图中的第359行)。 我通过 CPU 定时器1测量最坏情况下的内存复制代码执行时间。  

    如下图所示、我在最坏情况下的执行时间得到不同的结果:

    尽管我 尽力确保"innoMemcpy"的最大速度

    那么、我该怎么做才能使 "innoMemcpy"像"memcpy"一样快速运行呢? 正如我说过的、库中的"memcpy"函 数已复制到我的工程中并重命名为"innoMemcpy"、因此"innoMemcpy"和"memcpy"必须包含相同的代码。  

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、明天会尝试这个、然后回来。 这是 RAM 编译配置还是闪存?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    它在 CPU1_FLASH 编译 配置中编译。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、谢谢。 我在发送的工程中具有该.out 文件、以便可以重复使用该文件、但如果我需要重新编译、我将遇到问题。 将会通知您。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    或者、您可以 执行以下操作:

    1) 1)采用 TMDSCNCD28388D 评估板。

    2) 2)从 C200ware 导入工程、例如 :C:\ti\c2000Ware_3_04_00_00\driverlib\f2838x\examples\C28x_cm\led

    3)在配置闪存中编译 CPU1项目(不需要编译 CM 项目)并将我的附加代码移动到该项目。

      a)哈希中的代码定义"#if Memcopy_debug_code =="1"... "#endif"

      b)我将 CPU 定时器1设置为自由运行计数器的几行代码。  

    4) 4)将 CPU1项目刷新到板上并运行(同样、不需要 CM 项目)。

    我相信您使用的 C2000器件版本无关紧要。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、我仍然无法生成此问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Vivek Singh、

    您是说您尚未运行示例代码、还是运行了示例、但在"Expressions"窗口中看到了相同的时间消耗时间值?

    如果您尚未运行该示例(由于缺少时间)、则没有问题。 这种情况对我来说还不是特别紧急。

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我还没有执行你提到的步骤。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我查看了两个函数的编译代码、这里是我看到的-

    memcpy (&myMemcpyBuff[0]、(const void *) 0x38000、(size_t) sizeof (myMemcpyBuff);

    它使用 RPT 循环、因此没有分支指令。

    innoMemcpy (&myInnoMemcpyBuff[0]、(const void *) 0x38400、(size_t) sizeof (myInnoMemcpyBuff);

    这里没有 RPT 循环指令。 而是使用分支到自身的指令、这将需要多个周期(4个周期)。 这意味着对于每个副本、第2个函数中都有额外的周期。  

    这就是  innoMemcpy 函数谈论更多周期的原因。  

    希望这一点很清楚。  

    此致、

    Vivek Singh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Vivek Singh:

    感谢您找到准确的原因。 但是、生成的汇编器当然必须不同、否则就不会进一步解释执行时间的差异(代码所在的位置、RAM 或闪存除外)。 我的问题实际上是一个不同的问题。

    memcpy 函数是库中的一些预编译代码。 这意味着 TI 以不同的方式编译了该函数(编译期间很可能是相同的编译器、但具有某些属性)。 我通常很感兴趣的是、尽可能提高我们自己的书面代码的时间效率、因此我想学习一些技巧。

    因此,我原来的问题如下:

    我需要做什么(例如、我必须使用哪个#pragma)才能使 C2000编译器为"innoMemcpy"生成与 TI 预编译"memcpy"函数相同的高效汇编器代码?

    谢谢、

    Inno   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    [~ userid="459171" url="支持/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1118404/tms320f28388d-move-memcpy-to-ram--measure-execution-time/41812#41812"]感谢您找到准确的原因。 但是、生成的汇编器当然必须不同、否则就不会进一步解释执行时间的差异(代码所在的位置、RAM 或闪存除外)。 我的问题实际上是不同的。

    您的查询被转移到与闪存与 RAM 执行相关的设计问题中、因此我从编译器团队那里回来。 我刚才已经展示了当函数从 RAM 执行时、为什么您会获得更大的执行时间。

    [引用 userid="459171" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1118404/tms320f28388d-move-memcpy-to-ram--measure-execution-time/41812#4181812"]为了生成与"memcpy"相同的编译器函数、我必须做什么(例如、如"memcpy")、以使"memcpy"编译器具有相同的函数(例如、"memcpy")?

    为此、我必须将此帖子再次移至编译器团队。  

    此致、

    Vivek Singh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Inno、

    我们的编译器专家不可用。

    但是、我们确实会随编译器一起提供 C 运行时库的源代码和构建实用程序。  工具链实际上会根据需要动态构建库。

    因此、您可以查看源代码以及它们是如何构建的。

    我不确定您使用的编译器的版本、但您可以在编译器用户指南中查找并搜索"构建标准库"。  将提供有关如何调用 mklib 的信息。

    此致、

    John

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Johns、

    我使用以下内容:

    如果您的编译器专家将在下周提供、并且可能会现场发现相关情况、请告诉我。 否则、我将在 编译器用户指南中自行检查并搜索"构建标准库"。

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Inno、

    他们将在下周二离开。

    此致、

    John

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这对我来说绝对是可以的。  如果编译器专家知道在本周或下周生成相同代码所需的#pragma 指令、这将大有帮助。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我们的编译器专家明天应该回来看一看。 感谢您的耐心等待。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="459171" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1118404/tms320f28388d-move-memcpy-to-ram--measure-execution-time/41812#4181812"]为了生成与"memcpy"相同的编译器函数、我必须做什么(例如、如"memcpy")、以使"memcpy"编译器具有相同的函数(例如、"memcpy")?

    我可以使用优化级别2来生成相同的代码、而无需其他特殊设置。  下面是一个演示。

    C:\examples>ar2000 -x C:\ti\compilers\ti-cgt-c2000_20.2.4.LTS\lib\rts2800_fpu64_eabi.lib memcpy.c.obj
    
    C:\examples>dis2000 --quiet memcpy.c.obj > rts_dis.txt
    
    C:\examples>copy C:\ti\compilers\ti-cgt-c2000_20.2.4.LTS\lib\src\memcpy.c .
            1 file(s) copied.
    
    C:\examples>cl2000 --opt_level=2 --abi=eabi --float_support=fpu64 memcpy.c
    
    C:\examples>dis2000 --quiet memcpy.obj > build_dis.txt
    
    C:\examples>fc rts_dis.txt build_dis.txt
    Comparing files rts_dis.txt and BUILD_DIS.TXT
    FC: no differences encountered

    在第一个帖子中、指示您使用版本20.2.4.LTS 和 RTS 库  rts2800_fpu64_eabi.lib。  这些命令使用相同的版本和库。  第一个命令从 RTS 库中提取 memcpy.c.obj。  第二条命令将其反汇编、并将结果保存在 rts_dis.txt 文件中。  copy 命令从编译器安装目录复制 memcpy.c。  cl2000命令会将其构建。  请注意、唯一与优化相关的设置是-opt_level=2。  最后个 dis2000命令会反汇编刚刚编译的 memcpy.obj、并将结果保存在 build_ds.txt 文件中。  最后一个命令会比较两个反汇编文件、并显示它们匹配。

    谢谢、此致、

    乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的乔治:

    我为 Vivek Singh 提供了一个简单的闪烁 LED 示例项目、在该项目中、我将 memcpy 函数从文件"C:\ti\ccs1040\ccs\tools\compiler\ti-cgt-C2000-20.2.4.LTS lib\src\memcpy.c"复制到 C 文件中、并将其重命名为 innoMemcpy。

    我在该工程中调用了 memcpy 和 innoMemcpy、并在将相同数量的数据复制 到特定缓冲区时测量执行时间。 我确保了两个函数都驻留在闪存上、并按照您的建议在我的项目中启用了编译器优化级别2。

    对于此测试、注释了 innoMemcpy 的所有#pragma 指令:

    如果我现在使用 CPU 定时器1测量函数调用的执行时间、那么我仍然看到测量的执行时间有很大差异:

    您是否可以在评估板上重现此问题? 问题不是很紧迫、但我仍然希望达到这样一个状态:调用 memcpy 和 innoMemcpy 的测量执行时间相同。

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您是否检查了程序集以查看它是否正在您的本地函数中生成 RPT 块指令?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Vivek Singh:

    我有点困惑。 代码看起来与我相同、BANZ 同时用于这两种应用(BTW、使用 LCR 时、堆栈是否堆积且可能达到临界级?)。 但是、下面是"Disassembly"窗口中的函数:

    我再次检查了相关变量的位置以及映射文件中的代码:

    测量执行时间的代码也与我在其中一篇文章中看到的相同 C 代码。

    因此、一切看起来都是一样的、但通过定时器1测得的时间是不同的:

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    汇编代码看起来与您为我提供的项目不同。 memcpy 是库函数的一部分、早期使用 RPT 块、但在此快照中我看不到这一点。 如果您对项目进行了任何修改、请将更新后的项目发送给我。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="459171" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1118404/tms320f28388d-move-memcpy-to-ram--measure-execution-time/41812#4181812"]为了生成与"memcpy"相同的编译器函数、我必须做什么(例如、如"memcpy")、以使"memcpy"编译器具有相同的函数(例如、"memcpy")?

    确保 innoMemcpy 的内联方式与 memcpy 的内联方式相同。  一个很好的方法是在头文件中提供这些行...

    #pragma FUNC_ALWAYS_INLINE(innoMemcpy)
    static inline void *innoMemcpy(void *to, const void *from, size_t n)
    {
        /* implementation here */
    }    

    #include 此头文件位于调用 innoMemcpy 的任何源文件中。

    要使用的最佳构建选项是--opt_level=2 (或更高版本)和 --unified_memory。  在较低的优化级别、编译器不内联任何函数。  选项--unified_memory 允许编译器使用 PREAD 指令实现内存到内存的复制,进而允许使用单个 RPT 指令实现循环。   

    很抱歉、我之前没有意识到内联的重要性。

    谢谢、此致、

    乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Vivek Singh:

    我使用了相同的项目、但仅具有以下设置:

    谢谢、

    Inno  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、George、

    我执行了以下操作:

    1) 1)我验证了在 CCS 的编译器设置中激活了-unified_memory。

    2) 2)我将 innoMemcpy 移动到头文件、并按照上面的建议将其声明为 always_inline。

    3)我为 main 函数(调用 innoMemcpy)启用了编译器优化级别2

      #pragma FUNCTION_OPTIONS (main、"-opt_level=2");
      void main (void)

    我的结果如下所示:

    现在可以看到、innoMemcpy 比 memcpy 快5-7倍。 这意味着 memcpy 和 innoMemcpy 之间仍然存在差异、但这次 innoMemcpy 函数的速度要快得多。 当然我不会抱怨它 ;-)

    非常感谢您的帮助。

    -否

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很高兴看到您终于能够让这项工作取得成功。

    此致、

    Vivek Singh