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.

[参考译文] AM5728:PCIe 访问挂起 DSP 和 ARM

Guru**** 2559750 points
Other Parts Discussed in Thread: AM5728

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/615543/am5728-pcie-access-hangs-dsp-and-arm

器件型号:AM5728

运行自定义 AM5728板、ARM 运行 Linux、DSP 运行 Sys/BIOS。

DSP 是一个与 FPGA EP 第2代单通道通信的 PCIe RC。  DSP 内核1通过 PCIESS2连接。

DSP 的驱动程序代码大量偏离处理器 SDK 的 PCIe 示例。

整个过程的工作方式如下:

ARM 为 Linux 提供支持

ARM 加载 DSP 应用

ARM 将 FPGA 图像放入共享存储器

ARM 通知 DSP (通过 MessageQ)通过 GPMC 接口加载 FPGA。

加载 FPGA 并准备就绪后、DSP 将启动 PCIe 初始化。

PCIe 初始化如下所示:

1) 1) 通过 GPIO 对 FPGA PCIe 子系统进行硬件复位

2)调用 PCIe_init()

3)调用 pcieSerdesCfg -> PlatformPCIESS2ClockEnable()、PlatformPCIESS2PllConfig()、PlatformPCIESS2CtrlConfig()、PlatformPCIESS2Reset()、PlatformPCIESS2PhyConfig()

4)调用 PCIe_open ()

5)调用 pcieCfgRC()

6)调用 PCIe_cfgBar()

7)调用 pcieIbTransCfg()

8)调用 pcieObTransCfg()

9)调用 PCIe_getMemSpaceRange()

10)调用 pcieLtssmCtrl()<-启用链接训练

11)调用 waitLinkup()<-在链接启动时返回

我们的 ARM 应用每分钟多次重新加载 DSP 和 FPGA、并显示不同的图像。  经过一段随机的时间后、DSP 将不会响应。  当我们尝试连接 JTAG 调试器时、会出现"Device core is hung (设备内核挂起)"错误。   

为了帮助隔离该问题、在 DSP 中、我循环执行上述 PCIe 初始化步骤、并在结束时反复关闭。  在 DSP 内核挂起之前、我可以进行50到1000次迭代。

在通过 printf 日志进行大量调试后,我发现它始终挂起在 pcieCfgRC()函数中。  在更多 printf 调试后、它始终挂起在代码中:

MEM_SET (&getRegs、0、sizeof (getRegs));

getRegs.statusCmd =&statusCmd;

跟踪(DspTrace::error_log、"pcieCfgRC 启用存储器读取"); 新生儿睡眠(10);
if ((RetVal = PCIe_readRegs (handle、PCIe_location_local、&getRegs))!= PCIe_RET_OK) { 跟踪(DspTrace::error_log、"读取状态 Comand 寄存器失败!"); }

跟踪是我提供的一个记录函数、用于将字符串写入循环缓冲区。 SLEEP 命令允许我们运行低级任务、该任务会将刚刚写入 ARM 的字符串发送到控制台上以供显示。
我还可以从 ARM 访问该缓冲存储器。 在每个故障情况下、最后记录的是"pcieCfgRC 使能存储器读取"。

我深入研究了 PCIe V1源代码、发现上面的代码正在读取地址0x51800004处的状态/命令寄存器。 因此、我用以下代码替换了对 PCIe_readRegs 的调用:

uint32 statusCmdVal =*(volatile uint32_t *)((uint32_t *) 0x51800004); 

它仍然完全停留在该位置。

因此、经过数百次迭代、反复运行相同的代码后、内核将突然在读取0x51800004时挂起。

然后,有人建议从 ARM 读取同一地址。 我使用命令 omapconf 读取0x51800004、然后 Linux 挂起。 我必须按下电路板上的 POR 才能重新启动。

引导 Linux 时、但在加载 DSP 或配置 PCIe 之前、omapconf 读取0x51800004将返回以下结果:

bash-4.3# omapconf 读取0x51800004


!!! OUPS。。。 内存错误@ 0x00000000!!!
您确定:
   存储器地址有效?
   目标模块计时?

我想这是意料之中的、因为 PCIe 尚未启动并运行。  (BTW、所有对 PCIe 的引用均已从 Linux 器件树中删除。)

加载 DSP/FPGA 并循环后、读取正常工作:

bash-4.3# omapconf 读取0x51800004
00100146

当 DSP 最终挂起时、我尝试使用相同的命令、并且 Linux 提示符永远不会返回、Ctrl-C 不起作用、我无法将 SSH 连接到主板、我必须按下重置按钮。

不确定下一步要去哪里。  很明显、PCIe 子系统中的某个组件锁定、导致对其进行存储器访问挂起存储器总线。  只是不确定如何证明或修复它。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    软件团队已收到通知。 他们将在这里作出回应。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    过去、我们设置了 AM5728 IDK 至 AM5728 IDK EVM、一个是 RC、另一个是 EP。 连接速度为 PCIe SS1 x1 @ Gen2。 两端的软件都是 Processor SDK RTOS。 我们还重复执行您的测试序列来执行 PCIe SS1复位、以检查链接稳定性数百次。 我们没有发现任何问题。

    由于硬件连接限制、我们无法在 PCIe SS2上执行相同的操作。 您是否能够使用 PCIe SS1进行 FPGA 测试? 降低到第1代的速度是否有帮助?

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

    上周晚些时候、我 自己深入探讨了这个问题。  我决定查看 PCIe 寄存器0x518000004的 DSP/ARM 访问在哪些条件下会挂起。  当我启动 DSP 并且尚未初始化 PCIe 时、我得到了存储器错误响应。  然后、我单步执行 PCIe 启动代码。  我不记得确切的情况,但是当我执行 PlatformPCIESS1ClockEnable()或 PlatformPCIESS1PllConfig()时,我会遇到内存错误,但从 ARM 读取会挂起。  然后我能够进一步执行 DSP、当 DSP 执行 PlatformPCIESS1Reset()函数时、ARM 上的 hung 命令将完成。  这是一项重大突破。   我可以将其解卡。  是的。

    然后、我看到 RM_PCIESS_RTCTRL 寄存器位于0x4AE07310、而不是在0x51000000地址空间中。  因此、我再次运行测试、直到 DSP 挂起之前。 从 ARM、使用0x4AE07310上的寄存器、我能够复位 PCIe 子系统、并确保 DSP 能够恢复处理。  因此、如果您尝试访问其子系统中寻址的存储器、毫无疑问、PCIe 子系统负责挂起 DSP 内核甚至 ARM 内核。

    一些历史…

    在另一个主题中、我们  一直在讨论 通常反复重新加载 DSP/FPGA 的问题。  尝试解决该问题的部分方法是在 DSP 关闭过程中"重置" PCIe 子系统。  我们希望确保 PCIe 子系统在 DSP 代码空闲时未执行任何可能的内存访问或中断、从而导致内存挂起问题。

    因此、当 DSP 从 ARM (通过 MessageQ)发送关断消息时、我调用了 PCIe 类析构函数。  此代码被编码为调用 PCIe_close() 驱动程序函数。  但是、这只会产生将驱动程序句柄设置为空的效果、这似乎不是一个非常完整的近距离实现。  因此,我查看了示例代码中提供的 Reset 函数,即在 pcieSerdesCfg()中初始化时调用的函数,并创建 了一个名为 PlatformPCIESS1Stop()的新函数。  这与复位版本相同、但最终它没有使子系统退出复位、它保留了 RM_PCIESS_RSTCTRL 集中的 RESET 位。  

    我的应力测试的一部分是调用 init、然后反复关闭、因此我在循环结束时调用这个新的 Stop 函数。  但是,请记住 ,在初始化开始时,PCIe 构造函数,我调用 pcieSerdesCfg(),它又调用 PlatformPCIESS1Reset()。  我本以为将 RESET 位保持为高电平不会影响将来更全面地使用 RESET 功能。  我弄错了。

    在另一个测试中、我调用了 Reset 函数、而不是在析构函数中调用我的 Stop 函数。  当我执行此操作时、我能够运行5000次和7000次以上的迭代而不会出现故障、并且我被告知系统级测试运行得更好。

    但是、我非常担心 PCIe 子系统在出现问题时挂起 DSP 和 ARM 的能力。  DSP 内核挂起错误看起来像是一个真正的黑洞。  我很幸运、我偶然发现了一些让它变得更好的东西。  

    那么、我的问题是、是否需要采取措施来帮助防止这种类型的问题或从这种问题中恢复过来?