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.

[参考译文] SK-AM62P-LP:关于 memcpy 速度

Guru**** 2576215 points
Other Parts Discussed in Thread: AM62P

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1557560/sk-am62p-lp-about-memcpy-speed

器件型号:SK-AM62P-LP
主题:AM62P 中讨论的其他器件

工具/软件:

TI 团队大家好

 我使用的是 MCU SDK demo Display share、我发现 memcpy 的速度异常。 代码如下:  

        endMs = (ClockP_getTimeUsec() / 1000U);
        DebugP_log("Splash -> Gen 1 buffer: %u ms\r\n", (endMs - gBoot2SplashStartMs));
        {   // copy second flame 
            uint8_t *dst  = (uint8_t*)&gFirstPipelineFrameBuf[1];
            uint8_t *src  = (uint8_t*)&gFirstPipelineFrameBuf[0];
            size_t   bytes = 5529600U; // 1920*720*4 = 5,529,600
            memcpy(dst, src, bytes);
            /* Ensure DDR visibility for the second frame */
            CacheP_wb(dst, (uint32_t)bytes, CacheP_TYPE_ALLD);
        }
        endMs = (ClockP_getTimeUsec() / 1000U);
        DebugP_log("Splash -> Gen 2 buffer: %u ms\r\n", (endMs - gBoot2SplashStartMs));

我得到了下面的日志:

Splash -> Gen 1 buffer: 264 ms
Splash -> Gen 2 buffer: 408 ms

这意味着 memcpy  约使用了 140ms 的 5529600 位数据。

为什么这么慢?

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

    您好、
    要消除 除 memcpy 之外的其他函数调用引入的任何变异性、您可以尝试如下所示的操作:

    {   // copy second flame 
        uint8_t *dst  = (uint8_t*)&gFirstPipelineFrameBuf[1];
        uint8_t *src  = (uint8_t*)&gFirstPipelineFrameBuf[0];
        size_t   bytes = 5529600U; // 1920*720*4 = 5,529,600
        startMs = (ClockP_getTimeUsec() / 1000U);
        memcpy(dst, src, bytes);
        endMs = (ClockP_getTimeUsec() / 1000U);
        /* Ensure DDR visibility for the second frame */
        CacheP_wb(dst, (uint32_t)bytes, CacheP_TYPE_ALLD);
    }
    DebugP_log("Splash -> Gen 2 buffer: %u ms\r\n", (endMs - startMs));

    此外、该值在多个帧上是否一致?

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

    TI 团队大家好

    我更改了代码:获取下面的日志:

    启动界面-> Gen 2 缓冲区:78ms

    修改点位于 DispApp_splashThread() 中  、第二个缓冲区是 memcpy、不生成另一个火焰:

    /*在开始显示之前更新流水线的帧缓冲区*/
        DispApp_updateSplashFrameBuffer ((void *)&gFirstPipelineFrameBuf[0]、DISP_splash_image_XPOSTION、\
                    disp_splash_image_YPOSTION、DISP_splash_image_width、\
                    disp_splash_image_height、DISP_bytes_per_pixel);
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是在调试模式还是释放模式下构建映像?

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

    它是调试模式。

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

    请尝试使用释放模式、预计会减少该延迟。

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

    它有效但不会太多:

    设置为 RELEASE(调试模式)之前:

    ciserver Testapp Built On: Apr  3 2025 09:26:45
    Sciserver Version: v2025.04.0.0-REL.MCUSDK.K3.11.00.00.16+
    RM_PM_HAL Version: v11.00.07
    Starting Sciserver..... PASSED
    DispApp_init() - DONE !!!
    Display create complete!!锛
    Starting display ... !!!
    Display in progress ... DO NOT HALT !!!
    Splash -> Start to gen 1 Frame buffer 56 ms
    Splash -> Gen 1 buffer: 166 ms
    Splash -> memcpy 2 buffer: 140 ms
    Splash -> Gen 2 buffer: 355 ms
    Splash-> Start Fvid2 driver & first flame displayed: 358 ms
    DSS display share Passed!!
    [IPC RPMSG ECHO] Version: REL.MCUSDK.K3.11.00.00.16+ (Aug 27 2025 10:43:02):  

    下面是释放模式日志:

    Sciserver Version: v2025.04.0.0-REL.MCUSDK.K3.11.00.00.16+
    RM_PM_HAL Version: v11.00.07
    Starting Sciserver..... PASSED
    DispApp_init() - DONE !!!
    Display create complete!!锛
    Starting display ... !!!
    Display in progress ... DO NOT HALT !!!
    Splash -> Start to gen 1 Frame buffer 51 ms
    Splash -> Gen 1 buffer: 103 ms
    Splash -> memcpy 2 buffer: 140 ms
    Splash -> Gen 2 buffer: 322 ms
    Splash-> Start Fvid2 driver & first flame displayed: 325 ms
    DSS display share Passed!!
    [IPC RPMSG ECHO] Version: REL.MCUSDK.K3.11.00.00.16+ (Aug 27 2025 15:52:05):
    First Number of elapsed frames = 300, elapsed msec = 5005, fps = 59.94

    生成或执行 RLE 解码速度更快:110ms => 52mS; memcpy 时间不变:140ms ; 但   CacheP_WB 时间  从 49ms 增加 到 79ms。

    这是从以下位置打印的日志:

     
                }
                endMs = (ClockP_getTimeUsec() / 1000U);
                DebugP_log("Splash -> Generation 1 frame buffer finish: %u ms\r\n", (endMs - gBoot2SplashStartMs));
                {   // copy second flame 
                uint8_t *dst  = (uint8_t*)&gFirstPipelineFrameBuf[1];
                uint8_t *src  = (uint8_t*)&gFirstPipelineFrameBuf[0];
                size_t   bytes = 5529600U; // 1920*720*4 = 5,529,600
                uint32_t startMs = (ClockP_getTimeUsec() / 1000U);
                memcpy(dst, src, bytes);
                endMs = (ClockP_getTimeUsec() / 1000U);
                /* Ensure DDR visibility for the second frame */
                DebugP_log("Splash -> memcpy 2 buffer time endMs-startMs: %u ms\r\n", (endMs - startMs));
                CacheP_wb(dst, (uint32_t)bytes, CacheP_TYPE_ALLD);
                }
                endMs = (ClockP_getTimeUsec() / 1000U);
                DebugP_log("Splash -> Gen 2 buffer finished: %u ms\r\n", (endMs - gBoot2SplashStartMs));
    这在 DDR 读取或写入速度方面非常奇怪、因为我的计算 BW 仅为 78.99MB/s、远低于 DDR SK-AM62PX 速度、
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、
    让我从内部来看看、下周中旬回复您。

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

    你好  

    我们在这个问题上是否有任何进展?

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

    您好、

    我正在研究这个问题、请允许我在我的最后进行测试

    此致、

    会面。

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

    您好、

    我在结束时对此进行了测试、对于相同的字节、memcpy 需要 71ms 的时间、我将运行更多测试来确认这一点、但这就是我目前观察到的结果。

    这里还需要添加一点、那就是可以将 startMs 和 endMs 变量设置为 uint64_t 类型、这是 ClockP_getTimeUsec 函数的返回类型。 我不确定这是否有任何影响、但您可以对此进行一次测试。

    此致、

    会面。

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

    感谢!等待您的进一步答复!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    还有一件事要在这里添加、那就是可以将 startMs 和 endMs 变量设置为 uint64_t、
    类型。

    同时我请您尝试一次。

    此致、

    会面。

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

    是的、

    我更改为 uint64

    启动界面->第 1 代帧缓冲区完成:552ms
    启动界面-> memcpy 2 缓冲区时间:119ms、dst=93DCA000、src =93500000、大小=7680 字节
    启动界面-> Gen 2 缓冲区完成:683 ms

    没有变化。 是否有一些驱动程序或设备未初始化? 或者 memcpy 需要针对 TI 板进行定制?

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

    您好、

    Splash -> memcpy 2 缓冲区时间:119ms、dst=93DCA000、src =93500000、size=7680 字节

    5529600 字节的时间为 71ms、在您的代码片段中、我还看到 DebugP_print 日志、 CacheP_WB 和此 140ms 时间中还包含一些其他操作、如果您想测量准确的时间、那么您应该在 memcpy 指令之前和之后立即记下时间戳。

    memcpy 的时间很 长、如果您认为 memcpy 对系统来说花费的时间太长、则可以使用 dma 或 Utils_memcpyWord、通常您会使用图形引擎来修改帧中的某些像素、但在每个 vsync 后更新整个帧的成本应该很高。

    您能详细说明一下此处的用例是什么以及预计在什么时间完成 memcpy 吗?

    此致、

    会面。

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

    你好、Pu Jia、

    上述 讨论的 要点是有效的。
      测量期间、我们在 memcpy 操作中未使用任何 Cache API 或 Debug API。
    借助电流满足设置、我们能够在~71ms 内传输约 5MB 的数据。
    •如果您希望进一步缩短此传输时间、唯一可行的选择是利用基于 DMA 的数据移动。
    •作为参考、在 AM62x 器件的早期测试中、使用 DMA 时相同的 5MB 传输需要~10ms。
    •我们建议在 AM62P 器件上执行相同的基于 DMA 的测试、以测量和验证您设置中的结果。

    此致、

    Anil.

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

    TI 团队大家好

    在 am62px 中执行基于 memcpy CPU 的复制是正常的吗? 当我厌倦使用 UDMA 时, 复制 1920*1200*4 帧缓冲大约需要 40ms。

    这是否正常?

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

    你好、Pu Jia、

    在 AM62P 器件上使用 memcpy 时不会出现问题。 然而、对于大传输(例如 5MB 或 8.6MB)、memcpy 将明显比 DMA 慢、因此我们建议对大块使用 DMA。

    在 AM62x 上、我们测得大容量存储器传输的 DMA 吞吐量约为~500MB/s。 按该速率:
    •5 MB→~10.0 ms(十进制 MB)/~10.49 ms (5 MIB)
    •8.6 MB→~17.2 ms(十进制 MB)/~18.0 ms (8.6 MIB)
    因此、~8.6MB 的传输在~17ms 至 18ms 内完成、DMA 速率为~500MB/s

    但您的性能分析会看到 8.6MB 的更大值、我认为您可能无法测量正确的 方法。

    建议的 DMA 示例序列和测量过程:

    1.开始 DMA 传输(对描述符排队/调用 UDMA 启动 API)。
    2.在 UDMA 队列/启动前立即启动计时器。
    3.执行缓存失效后、停止 DMA 完成回调中的计时器。
    4.重复测量多次,并取中位数/百分位数,以避免单次运行的噪音。

    此致、

    Anil.

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

    TI 团队大家好

    我的代码  需要大约 40ms 来复制 8.6M 数据。

     

    int32_t udma_memcpy_2d(void *dst, const void *src,
                           uint32_t line_bytes, uint32_t lines,
                           uint32_t src_stride, uint32_t dst_stride,
                           uint32_t timeout_ms)
    {
        if (g_ch == NULL || dst == NULL || src == NULL)
            return SystemP_FAILURE;
        if (line_bytes == 0u || lines == 0u)
            return SystemP_FAILURE;
        if (src_stride < line_bytes || dst_stride < line_bytes)
            return SystemP_FAILURE;
    
        CSL_UdmapTR15 *tr = (CSL_UdmapTR15 *)UdmaUtils_getTrpdTr15Pointer(g_trpd, 0U);
        fill_tr15_2d(tr, src, dst, line_bytes, lines, (int32_t)src_stride, (int32_t)dst_stride);
    
        uint32_t src_span = (lines - 1u) * src_stride + line_bytes;
        uint32_t dst_span = (lines - 1u) * dst_stride + line_bytes;
    
        CacheP_wb((void*)src, src_span, CacheP_TYPE_ALLD);
        CacheP_inv(dst, dst_span, CacheP_TYPE_ALLD);
    
        int32_t ret = queue_trpd_and_wait(g_trpd, timeout_ms);
        if (ret != SystemP_SUCCESS) return ret;
    
        CacheP_inv(dst, dst_span, CacheP_TYPE_ALLD);
        return SystemP_SUCCESS;
    }

    您能帮助我提高代码速度吗?

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

    你好、Pu Jia、

    •您在哪个内核上运行上述代码? (A53、DM R5F 或 MCU R5F)

    •如果它在 A53 内核上运行、请确认正在使用的操作系统—Linux 或裸机?

    •从代码流程来看、它看起来更像是自定义代码、而不是标准 MCU+ SDK 示例。 您能否确认?

    •您是在释放模式还是调试模式下构建并运行该程序?

    •您进行性能测量的确切程度如何—您在哪里启动和停止计时器?

    •在您的测试用例中、您在设置(如 PMU 或通用计时器)中使用的计时器是什么?

    此致、

    Anil.

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

    您好团队

    这是 DM R5 内核示例。

    位于 MCU 驱动程序/DSS/DSS 共享中的示例。 我想是 FreeRTOS。

    代码是使用 UDMA 的自定义 memcpy 函数。

    它是 释放模式。

    我开始/stop 代码请查看我的帖子顶部。

    我不知道计时器。 只需使用  ClockP_getTimeUsec() 函数。

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

    你好、Pu Jia、

    如果您使用的是自定义代码、那么我很难在不知道具体启动和停止计时器的位置的情况下查看您的代码流。

    在定制 UDMA 代码中、您如何区分该流和 MCU+SDK 参考流? 请阐明该部分。

    为了进行测量、我建议您尝试使用以下 MCU+SDK 应用:
    •在 UDMA_queraw () 调用之前启动计时器。
    •在 CacheP_inv() 调用后停止计时器。

    该序列将给出正确的结果。 我也用这种方式衡量、数字是一致的。

    C:\ti\mcu_plus_sdk_am62px_11_01_00_16\examples\drivers\UDMA\UDMA_memcpy_interrupt\am62px-sk

    此致、

    Anil.

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

    您好团队

    您可以尝试将代码行 231 ~233 替换 为我的代码:在 void DispApp_splashThread(void *args)

                endMs = (ClockP_getTimeUsec() / 1000U);
                DebugP_log("Splash -> Generation 1 frame buffer finish: %u ms\r\n", (endMs - gBoot2SplashStartMs));
                {   // copy second flame 
                uint8_t *dst  = (uint8_t*)&gFirstPipelineFrameBuf[1];
                uint8_t *src  = (uint8_t*)&gFirstPipelineFrameBuf[0];
                size_t   bytes = 1920*1200*4U; 
                uint32_t startMs = (ClockP_getTimeUsec() / 1000U);
                memcpy(dst, src, bytes);
                endMs = (ClockP_getTimeUsec() / 1000U);
                /* Ensure DDR visibility for the second frame */
                DebugP_log("Splash -> memcpy 2 buffer time endMs-startMs: %u ms\r\n", (endMs - startMs));
                CacheP_wb(dst, (uint32_t)bytes, CacheP_TYPE_ALLD);
                }
                endMs = (ClockP_getTimeUsec() / 1000U);
                DebugP_log("Splash -> Gen 2 buffer finished: %u ms\r\n", (endMs - gBoot2SplashStartMs));

    然后尝试 它将 导致 120ms 的 memcpy ,这是  确认.
    因此、我尝试使用 UDMA_CPY、复制大约 8.7m 数据需要大约 40ms。
    ~~下面是我的 UDMA CPY 主代码区域,您能帮助检查我的代码为什么比您的代码慢得多吗?
    static inline void fill_tr15_linear(CSL_UdmapTR15 *pTr, const void *src, void *dst, uint32_t length)
    {
        /* Generate completion event; end-of-packet set. */
        pTr->flags    = CSL_FMK(UDMAP_TR_FLAGS_TYPE,          CSL_UDMAP_TR_FLAGS_TYPE_4D_BLOCK_MOVE_REPACKING_INDIRECTION);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_STATIC,        0U);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_EOL,           CSL_UDMAP_TR_FLAGS_EOL_MATCH_SOL_EOL);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_EVENT_SIZE,    CSL_UDMAP_TR_FLAGS_EVENT_SIZE_COMPLETION);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER0,      CSL_UDMAP_TR_FLAGS_TRIGGER_NONE);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER0_TYPE, CSL_UDMAP_TR_FLAGS_TRIGGER_TYPE_ALL);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER1,      CSL_UDMAP_TR_FLAGS_TRIGGER_NONE);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER1_TYPE, CSL_UDMAP_TR_FLAGS_TRIGGER_TYPE_ALL);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_CMD_ID,        0x00U);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_SA_INDIRECT,   0U);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_DA_INDIRECT,   0U);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_EOP,           1U);
    
        pTr->icnt0    = length;
        pTr->icnt1    = 1U;
        pTr->icnt2    = 1U;
        pTr->icnt3    = 1U;
        pTr->dim1     = (int32_t)pTr->icnt0;
        pTr->dim2     = (int32_t)(pTr->icnt0 * pTr->icnt1);
        pTr->dim3     = (int32_t)(pTr->icnt0 * pTr->icnt1 * pTr->icnt2);
        pTr->addr     = (uint64_t)Udma_defaultVirtToPhyFxn((void *)src, 0U, NULL);
    
        pTr->dicnt0   = pTr->icnt0;
        pTr->dicnt1   = 1U;
        pTr->dicnt2   = 1U;
        pTr->dicnt3   = 1U;
        pTr->ddim1    = (int32_t)pTr->dicnt0;
        pTr->ddim2    = (int32_t)(pTr->dicnt0 * pTr->dicnt1);
        pTr->ddim3    = (int32_t)(pTr->dicnt0 * pTr->dicnt1 * pTr->dicnt2);
        pTr->daddr    = (uint64_t)Udma_defaultVirtToPhyFxn((void *)dst, 0U, NULL);
    
        pTr->fmtflags = 0x00000000U;
    }
    
    static inline void fill_tr15_2d(CSL_UdmapTR15 *pTr,
                                    const void *src, void *dst,
                                    uint32_t line_bytes, uint32_t lines,
                                    int32_t src_stride, int32_t dst_stride)
    {
        pTr->flags    = CSL_FMK(UDMAP_TR_FLAGS_TYPE,          CSL_UDMAP_TR_FLAGS_TYPE_4D_BLOCK_MOVE_REPACKING_INDIRECTION);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_STATIC,        0U);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_EOL,           CSL_UDMAP_TR_FLAGS_EOL_MATCH_SOL_EOL);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_EVENT_SIZE,    CSL_UDMAP_TR_FLAGS_EVENT_SIZE_COMPLETION);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER0,      CSL_UDMAP_TR_FLAGS_TRIGGER_NONE);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER0_TYPE, CSL_UDMAP_TR_FLAGS_TRIGGER_TYPE_ALL);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER1,      CSL_UDMAP_TR_FLAGS_TRIGGER_NONE);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER1_TYPE, CSL_UDMAP_TR_FLAGS_TRIGGER_TYPE_ALL);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_CMD_ID,        0x00U);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_SA_INDIRECT,   0U);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_DA_INDIRECT,   0U);
        pTr->flags   |= CSL_FMK(UDMAP_TR_FLAGS_EOP,           1U);
    
        pTr->icnt0    = line_bytes;
        pTr->icnt1    = lines;
        pTr->icnt2    = 1U;
        pTr->icnt3    = 1U;
        pTr->dim1     = src_stride;
        pTr->dim2     = (int32_t)(src_stride * (int32_t)pTr->icnt1);
        pTr->dim3     = (int32_t)(src_stride * (int32_t)pTr->icnt1 * (int32_t)pTr->icnt2);
        pTr->addr     = (uint64_t)Udma_defaultVirtToPhyFxn((void *)src, 0U, NULL);
    
        pTr->dicnt0   = pTr->icnt0;
        pTr->dicnt1   = pTr->icnt1;
        pTr->dicnt2   = 1U;
        pTr->dicnt3   = 1U;
        pTr->ddim1    = dst_stride;
        pTr->ddim2    = (int32_t)(dst_stride * (int32_t)pTr->dicnt1);
        pTr->ddim3    = (int32_t)(dst_stride * (int32_t)pTr->dicnt1 * (int32_t)pTr->dicnt2);
        pTr->daddr    = (uint64_t)Udma_defaultVirtToPhyFxn((void *)dst, 0U, NULL);
    
        pTr->fmtflags = 0x00000000U;
    }
    int32_t udma_memcpy_2d(void *dst, const void *src,
                           uint32_t line_bytes, uint32_t lines,
                           uint32_t src_stride, uint32_t dst_stride,
                           uint32_t timeout_ms)
    {
        if (g_ch == NULL || dst == NULL || src == NULL)
            return SystemP_FAILURE;
        if (line_bytes == 0u || lines == 0u)
            return SystemP_FAILURE;
        if (src_stride < line_bytes || dst_stride < line_bytes)
            return SystemP_FAILURE;
    
        CSL_UdmapTR15 *tr = (CSL_UdmapTR15 *)UdmaUtils_getTrpdTr15Pointer(g_trpd, 0U);
        fill_tr15_2d(tr, src, dst, line_bytes, lines, (int32_t)src_stride, (int32_t)dst_stride);
    
        uint32_t src_span = (lines - 1u) * src_stride + line_bytes;
        uint32_t dst_span = (lines - 1u) * dst_stride + line_bytes;
    
        CacheP_wb((void*)src, src_span, CacheP_TYPE_ALLD);
        CacheP_inv(dst, dst_span, CacheP_TYPE_ALLD);
    
        int32_t ret = queue_trpd_and_wait(g_trpd, timeout_ms);
        if (ret != SystemP_SUCCESS) return ret;
    
        CacheP_inv(dst, dst_span, CacheP_TYPE_ALLD);
        return SystemP_SUCCESS;
    }
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    为了审查并提供准确的反馈、我们恳请您提供以下信息:
    1、完整的审核项目
    请分享完整的项目。 对于部分代码、我们很难验证计时器是在正确的位置启动/停止、还是在您的设置中存在隐藏的依赖项。
    2.计时器放置
    •计时器应在传输排队之前立即启动(在 queue_trpd_and_wait 之前)。
    •在缓存失效 (CacheP_inv) 后或 确认传输完成后、应立即停止计时器。
    这样、测量结果反映了 CPU 观察到的真实传输延迟。
    3.对 queue_trpd_and_wait 的说明
     您能否确认此函数仅在 DMA 完成后返回、还是支持轮询模式或中断模式? 分享执行情况将有助于我们确认。
    我们理解、对于~5MB 测试用例、观察到 71ms、但对于 8.6MB 传输、观察不到 71ms。

    我获得了 5529600 字节的 71ms 时间、在您的代码片段 中、我还看到了 DebugP_print 日志、CacheP_WB 和一些其他操作也包含在这 140ms 时间中、如果要测量准确的时间、那么您应该在您的指令
    之前和之后立即花费时间戳

    此致、

    Anil.

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

    是的、对于 6M 测试、71ms 和 8.6M 应是 110ms。

    我们需要尝试 UDMA 来实现这个目的吗?

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

    是的,如果你去与 DMA 几乎你可能会得到下面的结果.

    •5MB→ ~10.49ms  
    •8.6MB→~18.0ms  

    此致、

    Anil.

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

    你好,你能为我分享 DMA 复制代码吗? 您可以看到我的 DMA 复制代码上部... 如何改进我的代码?

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

    你好、Pu Jia、

    请使用下面的示例。

    C:\ti\mcu_plus_sdk_am62px_11_01_00_16\examples\drivers\UDMA\UDMA_memcpy_interrupt\am62px-sk

    将源缓冲区和目标缓冲区配置为所需的大小。

    在 DMA 启动之前、获取 计时器 T1 值。

    调用计时器并在 CacheP_Inv 调用后获取 T2 值。

    最后、执行 T2 - T1。

    测试需要在版本构建中完成。

    请查看下图以获取 T1 和 T2 值。

    此致、

    Anil.

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

    你好

    我设置的代码和示例不同  

    CSL_UdmapTR15   *ptr

     

      ptr->icnt0  = line_bytes;   
      PTR->icnt1  =行;

     

    您知道的局限性吗  

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

    你好、Pu Jia、

    ICNT0 的长度最大为 64KB。

    因此、为了满足传输 5MB 和 9MB 的要求、我们需要配置 icnt0 和 inct1。

    确保只需在版本生成中执行测试。

    此致、

    Anil.

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

    您好、

    如果我尝试使用 ICNT1/2/3 如何处理其余数据?

    这意味着如果我试图复制 64K*15+15K 数据、那么我做 ICNT0=64K、ICNT1=15 + ICNT=15K ICNT1=1?

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

    你好、Pu Jia、

    是的、上述方法有效。

    每个 icnt 值最大为 64KB。 因此、您可以相应地进行配置。

    此致、

    Anil.

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

    您好、

    icnt 最大值 的大小=64K 或 64K-1?

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

    你好、Pu Jia、

    您是否遇到 ICNT 0=64K 的任何问题?

    ICNT0 的最大大小为 64K。

    此致、

    Anil.

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

    抱歉。 我的 AI 总是告诉我、计数应该是 64K-1。 因此、我想与您确认一下。

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

    你好、Pu Jia、

    请您也可以与 Tetsing 确认。

    将 icnt0 配置为 64K 或 63K、并在测试中确认最大大小限制。

    此致、

    Anil.