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.

[参考译文] AM6442:GPMC 接口的突发大小限制

Guru**** 2563960 points
Other Parts Discussed in Thread: AM6442, TMDS64EVM

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1552547/am6442-burst-size-limitations-of-the-gpmc-interface

器件型号:AM6442
Thread 中讨论的其他器件: TMDS64EVM

工具/软件:

您好:

我将尝试通过 GPMC 接口以突发的方式传输数据、以尽可能提高吞吐量。

瞬间、GPMC 以 16 位和中等 33.33MHz 时钟运行。

该 GPMC 参数在 TRM 中称为 ATTACHEEDDEVICEPAGELENGTH(CONFIG1_I 的 24:23 位)。 与标准 OMAP-LGPMC 驱动程序和 Linux 器件树结合使用 、它被称为 GPMC、BURST-LENGTH、具有略微不同的参数表示法。 也就是说 、GPMC、BURST-LENGTH 指定最大突发长度(以字为单位)、而不是从其编码到 ATTACHEDDEVICEPAGELENGTH 中的值。  例如、当 GPMC、BURST-LENGTH 设置为 16 时、ATTACHEDDEVICEPAGELENGTH 被找到为 10 个二进制文件、对应于 16 个字。 因此、这似乎没问题。

我在第一个实例中发现了一个奇怪的事情 、那就是 SDK(我暂时使用 11.00.09.04)不支持 32 个字的最大突发长度、根据 TRM、这应该适用于 16 位模式。 出于测试目的、我对 OMAP-LGPMC 驱动程序打了一点补丁、以便能够 通过器件树设置将 ATTACHEEDDEVICEPAGELENGTH 设置为 11。

现在、相应的 GPMC 地址窗口可以被 Linux 进程占用、然后像正常存储器一样进行访问。 这是有效的、我看到在读取和写入期间使用了突发。

为了在主存储器和某个 GPMC 窗口之间移动数据,使用 SDK 附带的 memcpy () 应该是明智的。 虽然我没有详细检查,但我认为 memcpy () 实现通常针对处理器进行了高度优化。

例如、这将是一段代码、将 64 字节数据从主存储器中的某个缓冲区 buffer1 移动到表示 GPMC 区域内存储器的某个指针 GPMC_space、然后在 buffer2 处返回到主存储器

    memcpy ((void *) GPMC_space、(void *) buffer1、64);
    memcpy ((void *) buffer2、(void *) GPMC_space、64);

需要注意的是、我确实使用 GPMC_SPACE 进行测试、是 GPMC 窗口的起点 — 所以保持了一致。 buffer1 buffer2 通常在 C 函数的代码中声明为 64 位整数组。 AFAIK 编译器放置与此类数组的数据类型对齐 — 因此它们应在这里与 64 位对齐。

事实证明、对于写入、在 GPMC 接口上仅出现长度为 8 个字的突发、而对于读取、则使用长度为 16 个字的突发。

突发长度设置为 16(而不是 32)对实际突发长度没有影响。

因此、通过使用处理器、只能生成 8 个字的写入突发长度、这里匹配 16 个字节、而读取 16 个字的突发长度或者 可以创建 32 个字节。

这是正常行为、是否有一些调整来优化它? GPMC 肯定不会连接到处理器的高速缓存一致性机制。 但缓存行大小至少为 64 字节。 我不知道如何在处理器中处理这个问题。 但我认为确实有一个很好的机会一次可以传输 64 个字节。

谢谢、

Mario

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

    你好 Mario、

    请允许我在一天或两天内就上述问题回复您。

    FYI、TI 印度将于 2025 年 8 月 15 日度假。

    此致、

    Anil.

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

    尊敬的 Anil:

    感谢您再次参加本次课程。 所以我知道有人在照顾。

    我只是写下了一些关于这种情况的其他想法。 它们是:

    TRM (SPRUIM2H) 说明以下信息:

    • “32 位互连目标接口、支持高达 16x32 位的非缠绕和缠绕突发。“ (“第 12.3.3.1.1 节 GPMC 特性“)

    此外(“第 12.3.3.1.1 节 GPMC 特性“)指出、“ GPMC 支持以下各种访问类型“(以及其他类型):

    • 异步读取页面访问 (4-8-16-32 Word16、4-8-16 Word32)
    • 具有/不具有折返功能的同步读取/写入突发访问 (4-8-16-32 Word16、4-8-16 Word32)

    因此一般而言、GPMC 应能够生成最多 64 字节的突发大小。

    当然、这并不一定意味着处理器可以导致它们。

    TRM 中还有一个部分“12.3.3.4.9.5 系统突发与外部器件突发支持“。 它指出:

    器件系统可以向 GPMC 发出以下请求:

    • 递增 2、4 和 8 个字的固定长度突发

    此处的问题:  

    • 什么确切地被称为“器件系统“?
    • 什么是“词“?

    至于“字“的定义、这里可假设为 64 位、因为 AM64x 是 64 位器件。 8 x 64 位也将再次匹配这 64 个字节。 而“设备系统“可能不仅仅是实际的处理器、还包括其他单元、即 DMA 引擎。

    在“12.3.3.4.5 GPMC 互连端口接口“部分中、TRM 说明了以下内容:

    • GPMC 互连接口是一个流水线接口、包括一个 16 × 32 位字写入缓冲器。 (注意:这里我们还有 64 个字节)
    • 器件系统可以发出 8 个 递增的 32 位互连访问(读取/写入)(注意:其中 8 个是最大的访问)
    • 只有两次长度的幂精密突发 2 × 32、4 × 32、8 × 32 和 16 × 32、突发基地址与总数对齐
      支持突发大小

    这里有一个不符之处、一方面有人指出“器件系统“可以通过系统发出多达 8 个递增的 32 位访问、而另一方面有人提到最多 16 x 32 的突发。 这里没有提到 16 位的情况、但可以假设这里的突发长度刚刚加倍。

    由于它可以从 Linux 的默认 OMAP-LGPMC 驱动程序获取、但不支持设置用于生成 64 字节突发长度(意味着 32 x 16 位)的 GPMC、尽管至少可以设置 GPMC 以允许这样做(这意味着必须将 ATTACEDDEVICEPAGELENGTH 设置为 3) 。 我想之所以存在这种限制、是因为连接到 GPMC 的典型器件无论如何都只在 16 位时支持高达 16 的突发长度。 在平均时间、我对 OMAP-LGPMC 驱动程序做了一些调整、以便也可以设置为允许高达 32 的突发长度。 然而,这在读取操作中没有特别的效果,在读取操作中,我仍然观察到暴冲长度为 16。  

    处理器不能用于生成 32 的突发长度这一事实对我来说并不一定是一个惊喜 — 尽管可能有一些方法来实现我只是不知道的。

    但 DMA、特别是“BCDMA"呢“呢? 然后、BCDMA 是否能够让 GPMC 生成 32@16 位 或 16@32 位的突发长度 、同时在主存储器和 GPMC 之间传输数据块、从而更大限度地提高吞吐量?

    顺便说一下、可能是超出范围的位、但在 TRM 的“器件概述“(即 1.3.17 通用存储器控制器 (GPMC) 一节)中、既没有提到 GPMC 以 32 位运行的能力、也没有提到 16 位 32 字突发可兼容性。 但是、我想这是某种复制和粘贴错误、此文本来自较旧的微控制器。

    您好、

    Mario

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

    阿尼尔 ·斯瓦加姆在这个时候,是否有一些关于这个问题的想法?

    谢谢、

    Mario

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

    你好 Mario、

    我觉得根据上述信息、您使用的是 A53 内核和 Linux 进行测试。 请确认。

    ATTACHEDDEVICEPAGELENGTH 在 TRM 中、定义了 GPMC 可以使用 32 个字的最大页/突发长度。

    读取:

    •由于 GPMC 为 16 位(每个字 2 个字节)、因此 16 字突发= 32 字节。

    写入:

    GPMC 为 16 位(2 个字节/字)、8 字突发= 16 字节。

    我认为、即使您增加了突发数据量、您也不会看到以下分析点可能带来的任何改进。

    对于读取操作、CPU 始终是高速缓存行的一半(为 32 字节)、而不是完整的高速缓存行长度(为 64 字节)。

    即 1/4 高速缓存行。

    CPU 以高速缓存行大小的突发从存储器中获取(A 类内核上为 64 字节、R5F 内核上为 32 字节)。

    它们并不总是一次推出整个 64 字节的行;相反、它们会按较小的块进行刷新。

    最初,我的怀疑与 GPMC 内存的 MMU 区域设置.

    您如何为 GPMC 内存进行 MMU 区域设置?

    我正在寻找第二组查询,将很快得到答复。

    此致、

    Anil.

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

    你好 Mario、

    如果您想增加吞吐量、为什么 33.33MHz 以较低的频率运行、而不是支持直至 133MHz?

    此致、

    Anil.

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

    尊敬的 Anil:

    感谢您对此事提供一些见解!

    要逐步了解您的问题/要点:

    如果您想增加吞吐量、为什么 GPMC 以较低的 33.33MHz 频率运行、而不是支持 133MHz?

    这些 33MHz、仅用于第一个实验。 在 100MHz 运行 GPMC 的平均时间内、 由于目标配置为 32 位、因此不能选择 133MHz。 根据数据表、限制为 100MHz。 总而言之、目标是尽可能多地为主存储器和 GPMC 器件之间的数据传输提供带宽、从而接近 GPMC 接口的理论限值。 这当然只能在突发长度尽可能长的情况下实现。 由于读取操作期间的额外开销(在流水线中传播读取地址并在流水线中传播读取数据)、这尤其重要。 我还在考虑某种直接 FIFO 实现、其中地址在 GPMC 器件中固有已知、可以忽略 AM6442 提供的地址。 使用此方法至少可以为每个事务保存一些周期。 但是,当可以保留正常的内存语义时,这将是一个加号。

    顺便说一下、在 100MHz 时、每次突发的读取突发长度似乎会从 32 字节减少到 16 字节。 所以也有一些关于各个时钟的关系的方面。

    根据上述信息、您正在 A53 内核上进行测试并使用 Linux。 请确认。

    是的、没错。

    我认为、即使您增加了突发大小、您也不会看到以下分析点可能带来的任何改进。

    是的、这就是我的观察结果。 正如我所写的、我甚至调整了 OMAP-LGPMC 驱动程序、该驱动程序通常出于任何原因将 ATTACHEEDDEVICEPAGELENGTH 限制在 16 个字、而不是 32 个字。 但这没有效果。

    [报价 userid=“525901" url="“ url="~“~/support/processors-group/processors/f/processors-forum/1552547/am6442-burst-size-limitations-of-the-gpmc-interface/6004055

    CPU 以高速缓存行大小的突发从存储器中获取(A 类内核上为 64 字节、R5F 内核上为 32 字节)。

    它们并不总是一次推出整个 64 字节的行;相反、它们会按较小的块进行刷新。

    [/报价]

    如果是这种情况,这里似乎还有其他一些因素会引入切口 — 尤其是当 GPMC 突发长度从 32 字节@33MHz 中断到 16 字节@100MHz 时、读取时。

    在这种情况下、我们还需要注意的一点是缓存行大小是否真的很重要。 也许还有更多关于某种写入缓冲区和预取缓冲区的问题。 这是因为 GPMC 存储器当然是不可缓存的。 但是、假设它在连接处可缓存且具有一些显式缓存一致性(例如缓存刷新和软件执行的缓存无效)、在这里可能是一个技巧。

    [报价 userid=“525901" url="“ url="~“~/support/processors-group/processors/f/processors-forum/1552547/am6442-burst-size-limitations-of-the-gpmc-interface/6004055

    最初,我的怀疑与 GPMC 内存的 MMU 区域设置.

    您如何为 GPMC 内存进行 MMU 区域设置?

    [/报价]

    我在这里没有进行任何特定的 MMU 区域设置。 总结一下我要做的是:

    • 通过 Linux 器件树设置 GPMC
    • 确保标准 OMAP-LGPMC 驱动程序加载和 GPMC 模块得到正确配置
    • 在应用程序过程中、使用 mmap() 映射/dev/mem 中相应 GPMC ChipSelect 窗口的物理地址
    • 然后只需访问映射的存储器 — 在 GPMC 器件和主存储器之间移动数据时、最好使用 memcpy ()、它会针对复制进行优化。

    因此、与 MMU 资源相关的所有设置或多或少都是 Linux 本身进行的标准设置。  

    在这里还能做些什么、怎么能做呢? 例如声明 GPMC 区域可缓存?

    无论如何。 我怀疑最好的方法是使用 DMA RESP。 BCDMA。 不过、还有几个问题:

    1. BCDMA 是否会使用 64 个字节的完整 GPMC 突发长度、即 32 个字@16 位或 16 字@32 位?
    2. Linux 中是否有利用 BCDMA 的现有基础架构? 它是否可以使用、或者它是否已被利用它的其他功能所阻止?
    3. 除了 TRM、是否还有一些有关如何使用它的其他文档、特别是在 Linux 下? 这肯定是一个复杂的问题、还涉及其他问题、例如确保主存储器中的连续区域等

    感谢和问候、

    Mario

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

    你好 Mario、

    根据您的测试结果和我们的讨论、由于互连延迟或等待时序、线路上的突发有时会以更高的 GPMC 频率碎片整理。

    下一步、我建议按如下方式配置 DMA TR:
    •ICNT0 = 64 个字节  
    •ICNT1 = Total_Bytes / 64(完成传输所需的突发数)

    此设置将允许 DMA 以对齐突发方式推送数据。 即使线路上的突发在更高的频率下仍然碎片化、与 CPU 驱动的 memcpy 相比、DMA 通常也会提供更高的吞吐量、因为它可以更高效地进行流水线传输。

    请注意、我不是 Linux 专家、因此我会将该问题发送给我们的 Linux 团队、以获得以下方面的额外指导:
    •在 Linux 下如何将 BCDMA 与 GPMC 集成
    •是否有现有的框架或驱动程序支持可用
    •对设备树或 DMAPEngine 配置所需的任何更改

    感谢您的耐心等待、我们将为您提供合适的专业知识。

    此致、

    Anil.

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

    您好 Anil、

    是的、基本上我同意、只要传输的数据块足够大、DMA 有望在这方面变得更好。 此外、DMA 将离开 CPU 来执行其他任务。

    关于您对这些 ICNT0/ICNT1 设置的建议、强制进行该对齐是有道理的。但当然、这只能应用于 DMA。   

    顺便说一下、我提到了这个替代方案、不是以可寻址 RAM 方式访问一些外部存储器、而是以 FIFO 方式访问、这样就可以缩短每个事务的几个周期。 我只是尝试了一下。 确实可以取得一些改善。 但是、增益是行不通的。 当从 GPMC 复制到主存储器(仍具有 16 位宽接口)时、我将实现 62MiB/s。 因此、系统会创建长度为 8 个字或 16 字节。 此类突发事务需要 10 个时钟周期加上一个周转周期、因此在 100MHz 时为 110ns。 16 字节块的平均传输时间约为 250ns RESP。 25 个时钟周期(基于这些 62MiB/s)。 因此、GPMC 接口确实需要花费更多的时间来等待、而不是传输数据。 在示波器上也可以清楚地看到这一点。这有点令人失望、但在给定的情况下可能不会有更多的期待。

    在将 GPMC 存储器区域视为与软件控制的高速缓存一致性连接的可缓存区域时、您认为该选项是什么? 这可能会有所改善? 这在理论上是可能的吗?

    对于 Linux 中的 BCDMA、感谢您将其转发给 Linux 专家。 在平均时间,你还能告诉我一些教程或示例,使使用 BCDMA 在某种形式的裸骨时尚(如果有可用的东西)?

    感谢和问候、

    Mario

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

    您好 Anil、

    只是一些其他的注意事项和想法...

    我认为、尽管评估套件 (TMDS64EVM 和 TMDS64GPEVM) 未提供 GPMC 性能、但确实可以以 32 位的速率对 GPMC 性能进行基准测试。 当然、不能进行一些有效的数据传输、但用户仍可以进行读取或写入。 所以我确实将一个 GPMC 窗口配置为 32 位宽度。 为了实现这一点、我必须为 Linux 扩展默认的 OMAP-LGPMC 驱动程序、因为它仅支持 8 位或 16 位。 但是、这不是什么大问题。 因此、突发长度以字为单位进行光分、这是几乎可以预期的、因为我们现在有 32 位而不是 16 位。 但业绩数字令人失望。 对于从主存储器到 GPMC 器件的传输、带宽约为 167MiB/s 对于使用上述 FIFO 语义从 GPMC 器件到主存储器的传输、带宽约为 72MiB/s 读取和写入突发总共需要 7 个时钟响应。 对于此类 16 字节突发、100MHz 处为 70ns。

    除了可以将 GPMC 窗口声明为可缓存区域并驱动一些软件控制的缓存一致性之外、我还想到了另一点:CPU 频率如何?

    我似乎无法在网络上(或在内核引导消息中)找到 A53 内核实际运行频率的任何信息。 目前似乎不支持动态频率调节。 我在 /sys/devices/system/cpu 下遗漏了相关条目、这里还有一个帖子、指出不支持该条目 (https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1097572/am6442-cpu-frequency-scaling-support)。 然而、动态频率调节和频率设置是不同的重要因素。 我使用的是最新的 SDK (11.01.05.03)、从未指定处理器应该以的频率运行、也没有找到任何关于默认设置频率的参考。 人们可能假设这里是 1GHz、但这可能是错的。 还有一个奇怪的事情、AM6442(即 IC) 在)在评估套件上始终几乎是冷的。 这并不是太糟糕、因为它表明功耗较低。 但是、这也可能表明默认情况下它的运行频率远低于其指定的 1GHz 时钟。 也有规定在 eval 套件上添加一些散热器,我已经看到了套件的图片与安装的散热器。 AM6442 在其他情况下似乎会变热。 只是增加 CPU 频率可能不是最明智的选择,因为它会产生其他问题(功耗,发热等),但它可能会导致改善。

    您好、

    Mario

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

    经过进一步的研究,我了解了这个 k3conf 工具。  k3conf 转储处理器让我:

    ---------------------------------------------------------------------------------------- |
    版本信息                                            |
    ---------------------------------------------------------------------------------------- |
    | K3CONF       |(版本 0.3-nogit builded Thu Jun 26 21:17:32 UTC 2025)              |
    | SoC        | AM64x SR2.0                                   |
    | SoC 标识符 |[0x328cd4e4] 0x19466 Func-safe Secure 的'级–40°C 至 105°C ALV 封装 |
    | SYSFW       | ABI:4.0(固件版本 0x000b'11.1.2--v11.01.02(花哨 RAT))       |
    |固件功能| 0x1:生成                                     |
    ---------------------------------------------------------------------------------------- |

    ------------------------------------------------------------------------------------ |
    |器件 ID |处理器 ID |处理器名称  |处理器状态|处理器频率|
    ------------------------------------------------------------------------------------ |
    |  135         | 32 | A53SS0_CORE_0  | DEVICE_STATE_ON | 1000000000      |
    |  136         | 33 | A53SS0_CORE_1  | DEVICE_STATE_ON | 1000000000      |
    |   9         | 24 | MCU_M4FSS0_CORE0 | DEVICE_STATE_ON | 400000000       |
    |  121          | 1 | R5FSS0_CORE0   | DEVICE_STATE_ON | 800000000       |
    |  122          | 2 | R5FSS0_CORE1   | DEVICE_STATE_ON | 800000000       |
    |  123          | 6 | R5FSS1_CORE0   | DEVICE_STATE_ON | 800000000       |
    |  124          | 7 | R5FSS1_CORE1   | DEVICE_STATE_ON | 800000000       |
    ------------------------------------------------------------------------------------ |

    因此、主内核似乎确实已经以 1GHz 的频率运行。 我还没有弄清楚这个频率是设置在哪里的。 即、查看稍微超频时会发生什么情况。 然而,在最终应用程序中超频并不是一个真正的选择....   

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

    嗨、Mario、

    我正在调试另一个问题、今天没有机会查看整个主题。 但要回答最后一个回答中的问题、可以使用 k3conf 工具检查 A53 运行时钟。 AM64x 不支持 CPU 频率调节、因此 Linux sysfw 中不存在 cpufreq。 而且绝对不支持和建议超频。 A53 频率在 U-Boot 上配置。

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

    嗨 Bin!

    是的、超频绝对不是一种选择。 这只是为了看看这是否会随着 GPMC 上的活动而改变某种东西。 但是,如果它确实是一件令人着迷的事情,它不能在实践中使用无论如何...

    为了总结应更认真考虑的事项:

    • 是否有选项可以结合软件控制的一致性来为 GPMC 地址窗口启用缓存? 如果是、如何在 Linux 中实现这一点? 我希望这可以显著提高性能、因为这可能会导致以下情况:始终传输完整的缓存行、并且 GPMC 模块可能生成这些 64 字节突发、似乎它基本上能够生成。
    • 是否有一个积极的观点可以通过使用 BCDMA 来克服现有的带宽限制、这可能与实际实验中的现有基准数据有关、而不必在 Linux 下进行?  对于在 100MHz 上运行的 32 位宽 GPMC 接口、当前需要检测的持续性能数据为 167MiB/s(将数据从主存储器复制到 GPMC 时)和 72MiB/s(将数据从 GPMC 复制到主存储器时)。
    • 是否有一些现有的基础设施可以在 Linux 下使用 BCDMA、如果是、如何使用它? 在 Linux 下、BCDMA 是否可以由某种应用程序使用、或者它的源代码是否已被重要驱动程序占用?  
    • 是否有一些示例文档或教程显示了 BCDMA 的应用? 不一定在 Linux 下、但一般而言。

    感谢和问候、

    Mario

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

    嗨、Mario、

    是否有一个积极的视角来克服通过使用 BCDMA 而存在的带宽限制、可能是使用实际实验中的现有基准数据、而不一定是在 Linux 下进行的数据?  对于在 100MHz 上运行的 32 位宽 GPMC 接口、当前需要检测的持续性能数据为 167MiB/s(对于将数据从主存储器复制到 GPMC)和 72MiB/s(对于从 GPMC 复制到主存储器)。[/报价]

    您是否需要 DMA 以固定的间隔定期写入 GPMC?

    如果是这样、它将需要以循环模式进行 BCDMA 传输、而这在 Linux 内核中未实现;

    如果没有,你可以使用内核 dmaengine API  dmaengine_prep_DMA_memcpy () 来编程 BCMDA 来执行传输。  有关 API 使用情况、请参阅内核驱动程序 drivers/spi/spi-cadence-quadspi.c。

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

    您好 Bin、

    [引用 userid=“7730" url="“ url="~“~/support/processors-group/processors/f/processors-forum/1552547/am6442-burst-size-limitations-of-the-gpmc-interface/6011710

    您是否需要 DMA 以固定的间隔定期写入 GPMC?

    如果是这样、它将需要以循环模式进行 BCDMA 传输、而这在 Linux 内核中未实现;

    [/报价]

    我不明白“在固定间隔内定期“是什么意思,但我认为我不需要它。 该应用的工作方式会定期检查 GPMC 器件上是否有可用的一些新数据块、或者 GPMC 器件是否可以接收新的数据块(取决于方向)。 如果是、则会将该块从 GPMC 器件复制到主存储器、反之亦然。 也就是说、每个传输都是单次传输。

    如果没有、您可以使用内核 dmaengine API  dmaengine_prep_dma_memcpy () 对 BCMDA 进行编程以执行传输。  有关 API 使用情况、请参阅内核驱动程序:drivers/spi/spi-cadence-quadspi.c。

    好的、这似乎是一个很好的起点。 感谢您的提示! 我将深入研究、看看可以在这里执行什么操作。

    对于这些缓存的选项很重要,您不知道 — 至少这一点是否值得?

    您好、

    Mario

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

    嗨、Mario、

    我不清楚“在固定间隔内定期“是什么意思、

    此类用例的一个示例是在音频应用中、其中数据传输采用固定的短间隔和固定数据长度。 DMA 通道在传输开始时被配置为循环模式。 DMA 只需移动一个数据块、DMA 通道就可以为下一个数据块做好准备、无需使用软件来重新配置通道。 但您似乎不需要此用例。

    对于这些缓存的选项很重要,您不知道 — 至少这是否值得?

    我今天刚刚联系了我们的 GPMC 模块专家、GPMC 本身没有高速缓存数据的机制。

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

    尊敬的 Bin:

    此类用例的示例之一是在音频应用程序中、其中数据传输间隔固定、数据长度固定。 DMA 通道在传输开始时被配置为循环模式。 DMA 只需移动一个数据块、DMA 通道就可以为下一个数据块做好准备、无需使用软件来重新配置通道。 但您似乎不需要此用例。

    我怀疑有类似的事情。 因此、这仅适用于实时流应用。 不过、这样做的好处是无需为每次传输重新配置通道。 根据此类重新配置的重构程度、这也可能很关键...

    我今天刚刚和我们的 GPMC 模块专家交谈过、GPMC 本身没有缓存数据的机制。

    那是肯定的。 但我没有提到 GPMC 中的一些高速缓存、而是提到常规 CPU 高速缓存。 我已经做了一些家庭工作在这个问题...

    首先、/dev/mem 后面的驱动程序通常将映射内存视为无缓存。 因此、即使一个是通过/dev/mem 映射常规存储器、也不会有缓存。 相关部分可在 arch/arm64/mm/mmu.c 中找到

    pgprod_t phys_mem_access_prot(结构文件*文件、无符号长整型 PFn、
                   无符号长整型、pgprot_t vMA_prot)

        if(!PFN_IS_MAP_MEMORY (PFN))
            返回 pgprot_noncached (vMA_prot);
        else if (file->f_flags 和 O_sync)
            返回 pgprot_writecombine (vMA_prot);
        返回 vMA_PROT;
    }

    有这个调用 pgprot_noncached()、或者当为文件句柄  pgprot_writecombine() 设置了 O_SYNC 时

    pgprot_writecombine () 被认为至少实现了一个写入组合。 事实上,我从一开始就无意中使用了这种方法。 但是、无论 是否设置了 O_SYNC、我都看不到写入性能发生变化。

    这些 pgprot-mapping 函数在 arch/arm64/include/asm/pgtable.h 中进行了定义 其中、如下所示:

    /*
     *将 PROT 值标记为不可缓存和不可缓存。
     */
    #define pgprot_noncached (prot)\
        __pgprot_modify (PROT、PTE_ATTRINDx_mask、PTE_ATTRINDX (MT_DEVICE_nGnRE)| PTE_PXN | PTE_UXN)
    #define pgprot_writecombine (prot)\
        __pgprot_modify (PROT、PTE_ATTRINDX_MASK、PTE_ATTRINDX (MT_NORMAL_NC)| PXN | PTE_UXN)
    #define pgprod_device (prot)\
        __pgprot_modify (PROT、PTE_ATTRINDx_mask、PTE_ATTRINDX (MT_DEVICE_nGnRE)| PTE_PXN | PTE_UXN)
    #define pgprot_tagged (prot)\
        __pgprot_modify (PROT、PTE_ATTRINDX_MASK、PTE_ATTRINDX (MT_NORMAL_TIGEN))
    #define pgprot_mhp   pgprot_tagged
    /*
     *非相干设备的 DMA 分配使用 Arm 架构调用的内容
     *“正常的不可缓存“内存,允许推测,未对齐的访问
     *和合并的写入。  这与“Device-nGnR[ne]"存储“存储器不同
     *适用于 MMIO、因此禁止猜测、保留访问大小、
     *需要严格对齐、也可以强制来自的写入响应
     *端点。
     */
    #define pgprot_dmacoherent (prodt)\
        __pgprot_modify (PROT、PTE_ATTRINDx_mask、\
                Pte_ATTRINDX (MT_NORMAL_NC)| PTE_PXN | PTE_UXN)

    因此,从我的角度来看,这里需要的是使用 pgprot_dmacoherent() 而不是 pgprot_noncached()  pgprot_writecombine ()。 可能最简单的方法是将/dev/mem 驱动程序复制到某种/dev/mem2 驱动程序中、然后替换该 pgprot-call。

    接下来是关于软件控制一致性的问题。 在这里我找到了命令  DC CISW(缓存行清理和失效)、DC CSW(缓存行清理)以及可能的  DC ZVA(通过虚拟地址缓存零)。 后一个高速缓存行对于在写入 GPMC 窗口之前分配高速缓存行很有用、因此可以避免首先从 GPMC 读取相应的高速缓存行、这将是无稽之谈。 但是、我迄今为止发现的有关  DC ZVA 的文档 有些不清楚。 可能是它根本没有接触高速缓存。 如果是这种情况、则必须接受在写入过程中无用的初始高速缓存行填充、然后希望此高速缓存行仍然分配在高速缓存中用于后续写入。  将 64 个字节写入 GPMC 后会使用 DC CSW 命令、以引发相应的通信线路刷新、希望在 GPMC 上创建 64 字节写入突发。 从 GPMC 进行的任何读取都应产生 64 字节的高速缓存行填充、并有望产生 64 字节的 GPMC 读取突发。 在处理一个 64 字节的读取块后(或最晚在从该非常相同的地址进行下一次读取之前)、 需要立即执行 DC CISW、以确保没有处理过时的数据。

    您能遵循这些想法吗?

    谢谢。此致、

    Mario   

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

    嗨、Mario、

    我曾与我们的一位高级开发人员谈论过这些问题。

    但是、无论 是否设置了 O_SYNC、我都看不到写入性能的变化。

    此 O_SYNC 是关于内核块设备驱动程序中的数据缓存、它不是内存中的常规缓存。

    因此、从我的角度来看、这里需要使用 pgprot_dmacoherent ()  、而不是使用 pgprot_noncached () 或 pgprot_writecombine ()。 可能最简单的方法是将/dev/mem 驱动程序复制到某种类型的/dev/mem2 驱动程序中、然后替换该 pgprot-call。

    内核已经有一个驱动程序“dma_buf"可以“可以在启用缓存的情况下将存储器区域映射到用户空间、但我们不确定它是否适用于 IO 存储器区域、例如 0x50000000 GPMC 数据存储器窗口。 您可能需要尝试一下。

    请检查内核器件树 k3-am62a7-sk-edgeai.dtso、它在&reserved-memory 节点中具有以下节点:

    edgeai_shared_region:edgeai_shared-memory{
        compatible =“dma-heap-carveout";“;
        REG =<0x00 0xa3000000 0x00 0x0ac00000 >;
    };

    您可以在上面的“reg"属性“属性中更改 GPMC 区域的位置及其大小、然后内核 dma-buf 驱动程序应该在/dev/dma_heap/.下为其创建一个条目 您可以尝试在应用程序上打开并映射它、以查看它是否提高了性能。

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

    尊敬的 Bin:

    此 O_SYNC 是关于内核块设备驱动程序中的数据缓存、它不是内存中的常规缓存。

    是的、我同意。 更确切地看了我上面引用的代码后、映射存储器(或物理地址空间)时、始终调用 pgprot_noncached (vMA_prot)。 然而,不管怎样,这里似乎不相关,因为仅仅写合并在这里是不够的。

    [引用 userid=“7730" url="“ url="~“~/support/processors-group/processors/f/processors-forum/1552547/am6442-burst-size-limitations-of-the-gpmc-interface/6016440

    内核已经有一个驱动程序“dma_buf"可以“可以在启用缓存的情况下将存储器区域映射到用户空间、但我们不确定它是否适用于 IO 存储器区域、例如 0x50000000 GPMC 数据存储器窗口。 您可能需要尝试一下。

    请检查内核器件树 k3-am62a7-sk-edgeai.dtso、它在&reserved-memory 节点中具有以下节点:

    edgeai_shared_region:edgeai_shared-memory{
        compatible =“dma-heap-carveout";“;
        REG =<0x00 0xa3000000 0x00 0x0ac00000 >;
    };

    您可以在上面的“reg"属性“属性中更改 GPMC 区域的位置及其大小、然后内核 dma-buf 驱动程序应该在/dev/dma_heap/.下为其创建一个条目 您可以尝试在应用程序上打开并映射它、以查看它是否提高了性能。

    [/报价]

    AHA、这很有趣。 我确实尝试过,但它在一目了然的失败。 不过、问题似乎更具一般性、我相信还有其他事情要做。

    例如、我在设备树的&reserved-memory 节点中添加了以下部分:

            FPGA: FPGA-存储器@53000000 {
                compatible =“dma-heap-carveout";“;
                REG =<0x00 0x053000000 0x00 0x00020000>;
                //reg =<0x00 0x0C0000000 0x00 0x00020000>;
            };

    这会从配置的 GPMC 窗口之一开始设置一个 128kiB 窗口。 出现相应的条目 /dev/dma_heap/carveout_fpga-memory@53000000。  

    例如、可以使用以下命令打开该文件:

    fd2 = open(“/dev/dma_heap/carveout_fpga-memory@53000000“, O_RDWR );

    但当它通过以下方式出现间隙时:

    FPGA_space =(Volatile int32_t *) mmap (NULL、FPGA_RAM_SPACE_SIZE、PROT_READ | PROT_WRITE、MAP_SHARED、fd2、 0);

    mmap() 总是失败、错误是  ENODEV resp. “无此类设备“。  

    Linux 响应可能会带来一些风险。 dma_buf 本身就允许为实际的物理主存储器提供这样的区域 — 您还写了,您不确定这是否适用于 GPMC 等 IO 区域。 但是、在这种情况下、我会期望 dmesg 中出现一些错误消息、并且/dev/dma_heap/.上缺少一个条目 为了检查我是否通过实验将该窗口放入实际 DDR 主存储器的中间。 请参阅上述器件树配置中注释掉的寄存器设置。 这种情况同样无法实现。   

    因此、这使我相信、在这样一个区域能够被削弱之前、还需要做一些其他的事情。 你有什么想法吗?

    谢谢、

    Mario

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

    这方面的一点更新:

    似乎没有使用打开的/dev/dma_heap/carveout...中的文件句柄来调用 mmap() 添加到工程。 相反、  必须在该文件句柄上执行 IOCTL DMA_HEAP_IOCTL_ALLOC、然后创建要在此处使用的另一个文件句柄。 我真的不明白这一过程背后的意义、因为操作系统实际上已经获得了所需的所有信息、但谁知道。  我将代码扩展如下:

    其他包括:

    #include
    #include

    用于 IOCTL 的结构声明:

    dma_heap_allocation_data dma_heap1_config;

    填写数据结构供以后使用:  

    dma_heap1_config.len = 0x2000;
    dma_heap1_config.fd = 0;
    DMA_heap1_CONFIG.FD_FLAGS = O_RDWR;
    dma_heap1_config.heap_flags = 0;

    IOCTL、移交先前打开的/dev/dma_heap/carveout-file 的文件句柄以及填充的数据结构:

    ioctl (fd2、dma_heap_IOCTL_ALLOC、&dma_heap1_config);

    使用文件调用 mmap() 处理数据结构中剩余的 IOCTL:

    FPGA_space =(Volatile int32_t *) mmap (NULL、FPGA_RAM_SPACE_SIZE、PROT_READ | PROT_WRITE、MAP_SHARED、DMA_heap1_CONFIG.FD、 0);

    实际上、IOCTL 会返回一些看起来合理的文件句柄、并且“No these device“错误已消失。 但是、现在的错误是“Invalid argument(无效参数)“。 我不知道这种说法适用于哪种说法以及现在可能有什么问题。  

    还有其他的事情… 我遇到了这个讨论:  TDA4VM:[e-mirror][sdk8.5][tda4vm]将物理地址转换为虚拟地址 

    引用 尼基尔·达桑 在那里写道:

    mmap  dma-heap-carveout 区域中不允许进行操作、因为它是为 DMA(直接存储器存取)操作保留的存储器区域。

    内核使用此内存区域为 DMA 操作分配内存、器件使用此区域直接访问系统内存、而不涉及 CPU。

    。  CONFIG_STRICT_DEVMEM 内核配置选项限制对 /dev/mem 文件的访问、这些文件提供对系统物理内存的直接访问。 启用此选项后、只有特权用户才能访问这些文件。 由于 dma-heap-carveout 是为 DMA 操作保留的存储器区域、因此 mmap 在 CONFIG_STRICT_DEVMEM 启用时无法通过操作进行访问。

    我不确定“特权用户“是指用户“root"之类“之类的用户还是内核驱动程序。 实际上、我确实发现为 SDK 中的默认内核激活了 CONFIG_STRICT_DEVMEM。 在测试中、我确实通过 向  board-support/ti-linux-kernel-6.12.35+git-ti/arch/arm64/configs/defconfig 添加 CONFIG_STRICT_DEVEM=n 来禁用它、并重建内核。 然而,这并没有改变任何事情。

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

    嗨、Mario、

    我将从明天晚些时候离开办公室 1.5 周,在我离开之前有一些关键的事情要总结,所以我今天没有足够的时间来审查你的完整更新,但是

    我不确定“特权用户“是指用户“root"之类“之类的用户还是内核驱动程序。

    是的、特权用户是根用户和等效用户。

    对于测试、我确实通过 在  board-support/ti-linux-kernel-6.12.35+git-ti/arch/arm64/configs/defconfi
    中添加 CONFIG_STRICT_DEVMEM=n 来禁用它

    这不是禁用内核配置选项的正确方法。 (在此 defconfig 文件中找不到任何此类引用。)

    而是需要添加

    # CONFIG_STRICT_DEVMEM 未设置

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

    您好 Bin、

    [引用 userid=“7730" url="“ url="~“~/support/processors-group/processors/f/processors-forum/1552547/am6442-burst-size-limitations-of-the-gpmc-interface/6021824

    这不是禁用内核配置选项的正确方法。 (在此 defconfig 文件中找不到任何此类引用。)

    而是需要添加

    # CONFIG_STRICT_DEVMEM 未设置

    [/报价]

    我很难找到做出这种改变的地方。 但是,我在最后所做的(和上面提到的)确实导致了内核的最终.config 文件的变化,其中相应的行已设置为:# CONFIG_STRICT_DEVMEM 未设置

    老实说、我仍然在努力处理 Linux 内核中的这些配置策略。 不管怎么说,没关系。。 这个 strict_DEVMEM 的东西似乎与这个问题无关。

    那么我认为有两个基本的问题,需要是 anserwed :

    1. AM6442 的主应用程序处理器是否支持对 DDR RAM 主存储器区域之外的物理地址进行缓存?
    2. Linux 中是否有任何内容禁止 DDR RAM 主存储器区域之外的可缓存映射?

    第一个问题的答案可能是“否“、因为高速缓存在虚拟地址上运行。 物理地址无关紧要。 但谁知道...对于第二个问题、我不太确定、我倾向于认为答案是“是“。

    我还不能让 dma-heap/dma-carveout-stuff 运行。 相反,我发现这: https://github.com/ikwzm/udmabuf/tree/master

    我得到了这种“运行“。 我不知道这是一个错误的驱动程序,或一些其他不兼容,或我做了什么错. 但我无法让该驱动程序将缓冲区与相应的 GPMC 窗口相关联。 它始终从 DDR 主存储器中获取一部分内容。 无论如何,乍一看,我做了一些内存速度测试基于这一点,要么启用缓存或禁用它(我假设它是这样做的)。 结果是显著的:当从非缓存缓冲区读取数据并将数据复制到一些定期分配的缓冲区(当然缓存)时,带宽约为 103MiB/s 当从缓存缓冲区执行相同操作时、带宽约为 3640MiB/s — 还不错。 写入带宽远高于未缓存的 1400MiB/s 和缓存超过 3800MiB/s。  

    最重要的是、这个内存到内存实验表明、打开或关闭高速缓存的方法是正确的。

    由于我努力说服这个 u-dma-buf 驱动程序选择通过设备树设置进行的正确缓冲区设置、因此我将正确的物理地址直接硬编码到驱动程序中。 由于我可以看到 GPMC 接口上的操作、因此我很可能正确地进行了调整。 但是、无论我是否在启用缓存的情况下映射 GPMC 窗口、我始终可以获得相同的 GPMC 窗口读取和写入性能数据。 实际上、这里没有高速缓存处于活动状态。 特别是在读取的情况下、我看到相同地址反复生成事务、尽管处理器应该从高速缓存读取以进行后续读取。 然而、当复制较大的块时、我偶尔会在这里看到 64 字节读取突发! 它们混合为 16 字节读取突发、每 64 字节突发的速率约为 2 16 字节突发。 通过/dem/mem 进行映射后、我只能看到 16 字节读取突发(对于执行的完全相同的复制代码)。   

    然而,有两个附加的事实值得一提:

    1. 当通过 u-dma-buf 驱动程序而不是/dev/mem 使用映射时、GPMC 写入突发长度从 4 个字加倍到 8 个字(即对于 32 位 GMPC 宽度、从 16 到 32 个字节)。 因此,写入性能得到了提升,超过 230MiB/秒的速度正在慢慢接近我所说的“可接受的水平“。 这很好。
    2. 在读取期间、尽管当我通过 u-dma-buf 驱动器映射时我会看到一些 64 字节突发、但在读取 u-dma-buf 映射时、整体性能甚至会略有下降(我的当前 GPMC 时序设置从大约 74MiB/s(使用/dev/mem) 到)到大约 70MiB/s(通过 u-dma-buf)。 阅读案例的一个主要问题似乎是交易之间的等待时间。  我认为、这些延迟甚至会在处理器实际使用其高速缓存时出现、除非他不使用某种推测预取。 但是、我看到 Cortex-A53 处理器确实包含这样的内容、甚至可以通过软件进行控制。  

    总而言之、已经取得了一些进展、尽管有明显的迹象表明、目前还没有使用缓存。 通过 u-dma-buf 映射时写入性能的提高可能是某种写合并效果。 为什么在读取过程中出现降级以及为什么出现至少 64 字节突发 — 老实说,我不知道,但也可能是某些缓冲策略的微小变化导致的。 但最重要的是、在我看来、有一些常规设置阻止了对这些存储器映射 IO 区域的缓存使用。

    我将继续进行此操作、看看我是否在 Linux 中找到导致内存映射 IO 的一般非可缓存映射的内容。 单独来看、我还会更深入地了解完全不同的 DMA Matter。

    您好、

    Mario

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

    嗨、我离岗了 1.5 周。 请期待响应延迟。  

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

    尊敬的 Bin:

    在平均时间,我花了大量的时间在缓存问题。 有好消息和坏消息...

    为了结构化的东西,我做了一个编号列表的个别点。

    1. 我提出的问题可能带有“是的、AM6442 的主应用程序处理器可以高速缓存 DDR 区域之外的存储器区域。“ “不,没有任何硬性限制,使得 Linux 不允许在常规主内存之外进行缓存。“
    2. 要注意的关键是根据内存添加@… 区域添加到器件树中(即在常规 DDR 区域的定义之外)。 此外、需要使 器件树中的保留存储器节点具有匹配条目。 我确实使用了参数  compatible =“shared-dma-pool “,并 在那里可重复使用(我不确定这是否特别需要,但它的工作方式)。 注意窗口大小/对齐也很重要。 这需要是 4MiB。 如果此处未正确完成任何操作、则在启动期间将出现内核错误。
    3. 现在、可以通过/dev/mem.映射这些区域 但是、要做到这一点、 需要设置 CONFIG_STRICT_DEVMEM=n(另外,顺便说一下,我仍然需要按照我最初描述的方式进行设置)。 如果不设置  CONFIG_STRICT_DEVMEM=n、在 mmap() 期间将出现一些权限错误。 无需再使用这些驱动程序来映射 DMA 区域。 另外、为了使用这些驱动程序、必须在设备树中应用相同的调整。 至少这对于 u-dma-buf 来说是值、我在这里进行了初始测试。 正如我发现的某种副作用、我仍然可以使用/dev/mem.的映射 我继续使用/dev/mem.
    4. 在打开   存在或不存在 O_SYNC 的/dev/mem 时、缓存是否处于活动状态确实受到控制。 如果使用 O_SYNC、则缓存不会处于活动状态。 如果未使用高速缓存、则高速缓存将处于活动状态。
    5. 值得注意的是、当没有使用缓存时、写入行为甚至会发生变化。 处理器似乎在这里执行更密集的写入操作。 即在非缓存模式下是否有这样一个准备好的区域,或通过/dev/mem 而没有所有这些额外的准备,这是一个不同的。
    6. 第一个小问题是:打开缓存时、正如预期的那样、作为缓存处于活动状态的明确标志、确实存在对 GPMC 区域的写入操作会导致缓存行填充操作的问题。 从性能的角度来看、这是无稽之谈。 以前我曾提到  DC ZVA 指令可能用于分配缓存行。 不幸的是,它没有这样做。 相反、它似乎在不接触缓存的情况下清除物理地址空间中相应缓存行的区域。 这在某些情况下可能很有用、但这里不有用。 经过进一步调查、ARM 处理器通常缺乏此类指令。 例如、PowerPC 有这样的指示。 如果有一些方法可以在 A53 上这样做、我愿意提供建议...
    7. 尽管我确实使用了指令 DC CVAC (按虚拟地址清理缓存行)和  DC CIVAC (按虚拟地址清理缓存行并使其无效)、但执行缓存维护的工作符合预期。 但是、我觉得即使 DC CVAC 也 会使缓存行无效。 这是不正常的。 然而、从存储器语义的角度来看、尽管只请求了清理、但可以执行清理和失效。
    8. 我重复使用了 Linux memcpy() 实现的部分、以便将其限制为此处所需的函数、该函数复制完整且对齐的缓存行。 本质上、这是通过重叠的 128 位加载/存储完成的、看起来效果很好。
    9. 一个小缺陷是缓存维护操作不能与实际数据移动重叠、因为这会降低性能。 最好在 GPMC 块读取开始之前对所有缓存行执行失效操作、并在 GPMC 块写入完成后对所有缓存行执行清除操作(当然从编程角度而言)。   
    10. 现在这个大问题:我相信我发现了 AM6442 中的一些错误。 我不知道这是分配给 A53 本身还是分配给周围的逻辑。 问题是、在写入过程中偶尔会有 16 字节的写入块与所有的 1(即 0xffffffff 为 32 位字时的四倍)。 该错误的地址对齐始终位于缓存行的开头。 或者换言之:每当出现问题时、高速缓存行的前 16 个字节都会受到影响。 默认 memcpy () 也存在此问题,因此这肯定与某些编程错误无关。 还值得注意的是、问题主要发生在缓存未被激活的情况下。 然而,非常冷漠,我也看到这与活动缓存. 另一方面,当通过/dev/mem 使用传统映射时,我从未看到它(即没有对设备树进行特殊调整)。 我还可以告诉您如何简单地避免此问题 — 即在每个写入的缓存行之后插入一个内存屏障(例如 DSB ST)。 但是、这会导致性能丧失。 读操作似乎完美无缺、顺便说一句。 GPMC 按照预期在此处正确创建 64 字节突发。

    当然、后一个问题又是一个杀手。 我知道这里的事情很棘手,特别是在与缓存的交界处,那里可能会发生奇怪的事情很快。 然而,实际上,这只是与一些一般写入组合的问题有关,因为它通常在缓存关闭时出现,实际上。 虽然我没有解释为什么在打开缓存时它很少出现。 这个问题当然也不是一个根本的问题。 这意味着 memcpy () 一般不会工作,这会导致几乎所有东西都会崩溃的情况。  因此、这似乎完全与存储器映射 IO 相关。  

    现在就介绍到这里。 我还没有研究 DMA 选项。 但恐怕我也要这样做...

    此致、

    Mario

      

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

    嗨、Mario、

    感谢您的详细更新。 它似乎你花了相当多的努力,并取得了巨大的进展! 但我恐怕我们无法在这里提供大量输入、您的实验超出了 SDK Linux 的范围、我们在这些方面没有经验。

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

    尊敬的 Bin:

    我也认为没有简单的解决办法。 这看起来就像是需要在控制器的后续版本中修复的东西。 因此、我认为至少应将此事转交开发部门进行调查。

    总之、这里只是为了文档编写的一些附加注释:

    • 我在上面写过,每个 64 字节块后完成的内存屏障解决了这个问题。 但不幸的是、它没有。 但是、它确实会降低出现的可能性。
    • 出于好奇心,我将每个缓存行的拷贝循环从四个 128 位加载/存储(如标准 memcpy () 实现中所示)更改为 8 个 64 位加载/存储。 问题仍然存在、但我在这里看到了不同的模式。 也就是说、这些问题并不完全与从 64 字节边界开始的 16 字节块相关。 相反、存在 8 个字节、16 字节和 24 字节的块、它们与所有 1 错误地写入。 大多数情况下、错误写入的块的对齐也位于 64 字节边界处。 但我也看到了 32 字节边界。 还值得注意的是、与具有 128 位加载/存储的型号相比、采用此配置时、问题出现的频率要高得多。 内存屏障的使用大大降低了出现的可能性,但没有消除它。  
    • 我还尝试重新调整 128 位加载/存储、以便它们不再交错。 这肯定会破坏性能、但问题仍然存在。 虽然,随着每 64 字节的额外内存障碍复制的问题似乎消失了(这意味着我还没有看到的问题...)。
    • 我确实使用了 NOP RESP 的加载/存储间距。 中立的指示,但这似乎没有效果。

    我想我需要放弃缓存问题、并且必须了解块移动 DMA 的可能情况。 不过、可能只能将缓存映射用于读取目的、而传统映射(即,即使在设备树中没有进行这些特殊的存储器重构调整)仅用于写入目的(读取该窗口会带来相当高的性能损失)。 这需要为单个存储器选择两个 GPMC ChipSelects。  这里应保持至少更高的读取速度(最多 250MB/s 左右)。 虽然写入速度可能与那些 170MB/s 左右,我之前报告(所有与 32 位@ 100MHz ). 实际上,这已经不会那么糟糕 — 但这个相当小的 AM6442 似乎能够做更多... 问题是这些性能数据是否可以用 DMA 达到顶峰 — 尤其是考虑到设置的开销。 但显然没有人能说在这方面能取得什么成就。 因此、除了在自己身上实施和尝试之外、什么都没有...

    还有其他问题时、我会在此处汇报。

    此致、

    Mario

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

    嗨、Mario、

    感谢更多细节,已经令人印象深刻的工程工作! 让我们知道使用 DMA 会带来哪些性能。