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:AM6442 PRU 以太网接收数据包 DMA 环访问问题

Guru**** 2457760 points
Other Parts Discussed in Thread: PROCESSOR-SDK-AM64X

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1473811/am6442-am6442-pru-ethernet-receive-packet-dma-ring-acc-question

器件型号:AM6442
主题中讨论的其他器件:PROCESSOR-SDK-AM64X

工具与软件:

尊敬的 Expert:  

我们将调试一个 PRU-Etherent 接收问题、并发现在失败的情况下、振铃占用寄存器(RINGRT[A]_RT_OCC)为0。  3个问题:

1) 1)由于有多种队列模式(TRM 11.2.2.3.2.1)、Linux SDK uBoot 中使用哪种模式来处理 PRU 以太网接收? 第一个是"振铃模式"吗?

2) 2)确认到以下说明"软件的优化是以较少的频率读取 RINGRT[A]_RT_OCC 寄存器、并保留一个本地副本、以保证允许的弹出次数达到最大。 当 RINGRT[A]_RT_OCC 的软件副本达到0时、或者定期读取寄存器以刷新值。 这必须降低寄存器读取的频率、而不是每次软件弹出时读取寄存器。" 在11.2.2.3.2.1.1环形模式章节中、这是在 Linux uBoot 源代码中实现的软件优化、还是需要由应用程序级别?处理

3)2号描述的含义是什么? 您能解释更多吗? 我们将检查我们的问题是否与此器件有关。

谢谢

-玉川

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

    尊敬的玉川

    我现在要研究这个。 我会尽快答复你。  

    BR
    JC

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

    嗨、Jayachandran

    我还有一些其他问题:

    1)在  PROCESSOR-SDK-AM64X 9.0 soc 的 uboot 中,我看到了 ti-u-boot-2023.04/drivers/navss-ringacc.c 的以下代码:

    结构 k3_nav_ring_rt_REGS
    u32 resv_16[4]
    u32 db/* RT 环 N 门铃寄存器*/
    u32 resv_4[1]
    U32 OCC/* RT 环 N 占位寄存器*/
    u32 indx/* RT Ring N Current Index 寄存器*/
    u32 hwocc/* RT 环 N 硬件占用寄存器*/
    u32 hwindx/* RT 环 N 电流指数寄存器*/
    };

    OCC 和 hwocc 之间的区别是什么?  它们的具体含义是什么?

    2)我认为  上面代码应该与 TRM 中的表11-438 ringacc_RT、DMASS0_RINGACC_0_RINGACC_RT 寄存器对应、是正确的?

    表11-458显示了 RT_OCC 寄存器字段说明、代码环更新 OCC 如下所示

    静态 k3_nav_ringacc_ring_update_OCC (结构 k3_nav_ring *ring)
    u32 val

    Val = readl(&ring->RT->OCC);

    Ring->state.OCC = val & KNAV_RINGACC_RT_OCC_MASK
    Ring->state.tdown_complete =!(val & k3_DMARING_RING_RT_OCC_TDOWN_COMPLETE);
    }

    在什么情况下 OCC 始终为0? 、、RT_OCC 的 Bit31被保留在 TRM 中、但上面代码中的 ring->state.down_complete?是正确的

    3)我正在调试 icssg 显示链接、如果 OCC 始终为0、 它表示什么?可能的原因是什么?

    谢谢

    -玉川

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

    尊敬的玉川:

    回答您的 第一个查询。

    [报价 userid="641250" url="~/support/processors-group/processors/f/processors-forum/1473811/am6442-am6442-pru-ethernet-receive-packet-dma-ring-acc-question 具有多种队列模式(TRM 11.2.2.3.2.3.2.1)、Linux SDK uBoot 中使用哪种模式来处理 PRU 以太网接收? 第一个是"振铃模式"吗?[/QUOT]

    我们使用振铃模式。  PRU 以太网 TX/RX 使用 PKTDMA。 PKTDMA 有专用环。  您在此指出的部分中使用的是环形 ACC、它独立于 DMA 工作。 我认为您可能会在查看错误的寄存器。 您必须从连接的中找到 PKTDMA 通道关联的振铃。 TX 情况如何?

    [quote userid="641250" url="~/support/processors-group/processors/f/processors-forum/1473811/am6442-am6442-pru-ethernet-receive-packet-dma-ring-acc-question)这对#2描述意味着什么? 您能解释更多吗? 我们将检查我们的问题是否与此器件有关。

    这意味着"没有可供软件服务的元素"

    RINGRT[A]_RT_DB =>用户可以提交要弹出的元素数量、其中 RINGRT[A]_RT_DB 不能大于 RINGRT[A]_RT_OCC 。

    RINGRT[A]_RT_OCC =>环占位寄存器保存准备由软件提供服务的有效元素数量(PoP)

     此处的优化是"一次弹出的最大数量"

    • 在 OCC 寄存器准备好由应用程序提供服务时、DMA 将递增该寄存器(软件只能读取)
      应用程序将通过读取 Ring 内容从 Ring 弹出描述符
    • 然后、当软件 完成对检索到的描述符的服务时、它将负整数(不是更大的 OCC)压入 DB 寄存器。

    假设软件不断轮询 OCC 寄存器来了解是否有任何描述符已准备好提供服务、那么 优化路径现在就是了

    • 读取 OCC 寄存器一次并在软件中保持计数(在软件中开始递减计数、同时逐个处理数据包)、然后一次性将 DB 寄存器中的所有负整数压入、以便将其清除/出队。

    BR
    JC

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

    嗨、Jayachandran

    感谢您的回答、希望您能尽快回答以下问题。
    此外、我还有很多其他问题、例如:
    1)您是否能够为 ELF 固件提供三个 PRU/RTU/txpru 内核(PRU/RTU/txpru)的调试信息? 在此基础上、我们可以获取有关三个 Pru 内核是否正常运行的信息以及主要错误消息。
    2)在 MII_g 模块以及 RT 环占用寄存器中定期读取 Rx 和 TX 良好帧计数,结果显示 Rx 和 TX 良好帧计数增加,而 RT 环占用寄存器没有变化。 因此、故障可能发生在 MII_g 模块和环之间、对吗? 如何进行下一步调试?
    3)是否有任何我们可以读取的密钥寄存器来帮助我们找到 Pru 内核、PKDMA、RingAcc 或 PSIL 等中发生的问题
    4)也许你也在查看一些技术手册或材料。 您能给我们分享一些可帮助解决此问题的关键 TRM 或工具吗

    谢谢

    -玉川

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [报价 userid="641250" url="~/support/processors-group/processors/f/processors-forum/1473811/am6442-am6442-pru-ethernet-receive-packet-dma-ring-acc-question/5674061 #5674061"]1)您能否为 elf 固件提供三个 Pru 内核(prU/RTU/txpru)的调试信息? 在此基础上、我们可以获得有关三个 Pru 内核是否正常运行以及关键错误消息的信息。

    我们的 SDK 包含固件二进制文件/接头(对于 RTOS SDK 为.h 、对于 Linux SDK 为.elf)。 假设您使用的是 10.01.00.32 RTOS SDK。

    2)定期读取 MII_g 模块中的 Rx 和 TX 良好帧计数以及 RT 环占用寄存器中的帧计数、结果显示 Rx 和 TX 良好帧计数有所增加、而 RT 环占用寄存器没有变化。 因此、故障可能发生在 MII_g 模块和环之间、对吗? 如何进行下一步调试?[/QUOT]

    PRU ICSSG 固件在固件中实现了调试统计信息。 您应该 在以下路径中找到 fw_mem_map.h:mcu_plus_sdk_am64x_10_01_00_32\source\networking\enet\core\cme\firmware\icssg src

    请按照以下步骤操作:

    1.根据您的 ICSSG 实例从 CCS 内存浏览器中转储 PRU ICSSG 统计内存范围。  

    ICSSG0:0x030027000 - 0x0300277FF

    ICSSG1:0x0300A7000 - 0x0300A77FF

    2.现在打开  fw_mem_map.h  文件并找到下面的偏移量。   

    如果您在开关模式下使用 PRU ICSSG:  

    /*Number of valid bytes sent by Rx PRU to Host on PSI.*/
    #define NRT_HOST_RX_BYTE_COUNT_PASTATID                    0x0000

    如果您在 双 Mac 模式下使用 PRU ICSSG:  

    /*Number of valid bytes sent by Rx PRU to Host on PSI.*/
    #define NRT_HOST_RX_BYTE_COUNT_MAC_SLICE0_PASTATID         0x0010
    /*Number of valid bytes sent by Rx PRU to Host on PSI.*/
    #define NRT_HOST_RX_BYTE_COUNT_MAC_SLICE1_PASTATID         0x0018

    例如:如果您使用的是 ICSSG1和 双 Mac 模式、请在 PRU ICSSG 转储文件中找到以下内容。

    0x0300A7000 + NRT_HOST_RX_BYTE_COUNT_MAC_SLICE0_PASSATID = 0x0300A7010   

    这将报告 Rx PRU 通过 PSI (PKTDMA)发送到主机的有效字节数。 这意味着固件已成功处理数据包并移交给 DMA。 类似地、您可以在固件 标头中关联许多错误/丢弃统计数据、并与存储器转储进行比较。

    [报价 userid="641250" url="~/support/processors-group/processors/f/processors-forum/1473811/am6442-am6442-pru-ethernet-receive-packet-dma-ring-acc-question/5674061 #5674061"] RT 振铃占用寄存器[/QUOT]

    注意:如果您仍在引用此随附的 RT 环占用寄存器快照、则这是正确的。 请参阅我上面的答复。  

    对于 A53的 ICSSG 0、PKTDMA RX 环号从160开始

     对于 A53、ICSSG 1、PKTDMA RX 环号从224开始

    示例:检查反向振铃占用情况:

    DMASS0_PKTDMA_0_RT_ROCC:0x4b801018 +(160 * 0x2000)

    您应该会看到 此寄存器中的计数增加。  

    如果上述 step:2为真、还可以监控 PKTDMA RX 通道统计信息:

    对于 A53的 ICSSG 0、PKTDMA 通道编号从21开始

    对于  A53的 ICSSG 1、PKTDMA 通道编号从25开始

    RXchannel 字节统计= 0x4A800400 +( * 0x1000)

    更正了:对于 AM64x、PKTDMA 处于消息模式、而不是 ring_mode。 我对器件感到困惑。 我已经指出了上述所有指标、它们都是关于资源分配的。 您还可以 在调试时确认 UDMA_ringDequeueRaw ()中的 RX_CHANNEL_NUM/RING_NUM。

    上面是我要跟踪的关键寄存器。

    BR
    JC

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

    感谢您的回答、我们使用的是 PROCESSOR-SDK-LINUX UBOOT-AM64X  版本:09.00.00.03、我们的驱动程序代码从 uboot 移植。

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

    嗨、Jayachandran

       感谢 您  的 答复。关于  步骤 1,我 已经 转储  ICSSG 统计 内存 0x0300A7000 -0x0300A77FF,   我比较了正常和异常的结果,发现了以下几点:
    a)在异常情况下、从 NRT_HOST_RX_BYTE_COUNT_MAC_SLICE1_PASTATID 读取的偏移地址值(0x0018、Rx PRU 在 PSI 上发送到主机的有效字节数)始终为0、并且在正常情况下会自动增加。
    b)在异常情况下、从 NRT_DROPPED_PKT_SLICE1_PASSATID 读取的偏移地址值(如果由于规则违规而在 PRU1上丢弃数据包、则0x00FC、递增)将自动增加、在正常情况下始终为0
    c)在异常情况下、从 NRT_INF_PORT_DISABLE_SLICE1_PASSATID (0x013C、PRU1诊断错误计数器、该计数器在 RX 帧因端口被禁用而丢失时递增)将自动增加、并且在正常条件下始终为0

    以上结果是否可以确定问题在 occurred.in 上的位置、我们使用的是 PROCESSOR-SDK-LINUX - AM64X 版本:09.00.00.03、我们的驱动程序代码是从 uboot 移植的。

    如果我需要根据上述步骤继续调试、您能告诉我在代码中设置 PKTDMA RX 环号和 PKTDMA 通道号的位置吗?

    我热切地期待着你的答复。
    谢谢。
    -玉川

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

    尊敬的 Yuchan:  

    b)在异常情况下、从 NRT_dropped_PKT_SLICE1_PASSATID 读取的偏移地址值将自动增加(如果由于规则违规而丢弃 PRU1中的数据包、0x00FC、递增)、在正常条件下始终为0

    固件正在丢弃数据包。  

    在异常情况下、从 NRT_INF_PORT_DISABLE_SLICE1_PASTATID 读取的偏移地址值(0x013C、PRU1诊断错误计数器由于端口被禁用而丢失 RX 帧时递增)将自动增加、在正常情况下始终为0

    因为端口状态已被阻止。 端口状态应因三种不同的条件(来自 Linux POV)而被阻止:

    1. 维持高阻抗状态
    2.  切换到双 MAC 模式时所需的时间。 固件需要重新启动。  
    3. 使用以下 IOCTL 从用户请求禁用状态

    这些是 Linux 中用于禁用和转发 STP 端口状态的 IOCTL。 在您的情况下、您必须启用"转发"返回。  

    			emac_set_port_state(emac, ICSSG_EMAC_PORT_FORWARD);
    			emac_set_port_state(emac, ICSSG_EMAC_PORT_DISABLE);

    我想、由于某种原因、端口状态并没有改变。 您可以在链路接通时运行以下 API、还是手动运行以下 IOCTL?

    EMAC_SET_PORT_STATE (EMAC、ICSSG_EMAC_PORT_FORWARD);

    如果我说对、您是在引用 Linux ICSSG 驱动程序代码库、并且 有您自己的实现、而不是工厂 AM64x Linux SDK?

    如果我需要根据上述步骤继续调试、您能告诉我代码中设置了 PKTDMA RX 环号和 PKTDMA 通道号的位置吗?

    此代码未硬编码。 SYSFW 用于在运行时期间为 SoC 外设分配资源。 以下是参考:

    对于 Ex (RESASG_SUBTYPE_PKTDMA_RING_ICSSG_0_RX_CHAN ): 为 PKTDMA_ICSSG_0_RX 保留了64个环,其中每个环专用于1倍 RX 流量。

    https://software-dl.ti.com/tisci/esd/latest/5_soc_doc/am64x/resasg_types.html

    我建议您在进一步调试之前解决上述问题、因为很明显、固件由于端口 禁用状态而下降。   

    BR
    JC

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

    嗨、Jayachandran

    感谢您的指导。 我们的软件环境是自行开发的 RTOS。 ICSSG 相关驱动程序从 uboot (path 是 uboot/drivers/net/ti/)移植、只对驱动程序进行了微小的修改。

    与 uboot 类似、是在 icssg_update_link 函数中调用的 RTOS EMAC_SET_PORT_STATE (priv、ICSSG_EMAC_PORT_FORWARD)。 根据您的建议、我在网络接口初始化结束时反复调用 EMAC_SET_PORT_STATE (priv、ICSSG_EMAC_PORT_FORWARD)三次、然后进行测试。 其结果是 icssg 网络 正常工作。 因此、我们可以推断、 有时可能未成功设置 EMAC_SET_PORT_STATE 函数。

    我们仅修改了 EMAC_SET_PORT_STATE 函数内的 udelay 实现、它  也已正常返回。 如何进行下一步的定位?

    谢谢。


    -玉川

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

    尊敬的玉川:  

    emac_r30_is_done () 

    看起来是原始 DMEM 读取、并且此 API 中没有超时。 看看屏幕截图、超时= 10并且它不断递减、因此没有实际的周期性轮询和超时非常紧凑的循环。
    建议添加具有超时功能的定期轮询。
    我回顾了 Linux 的实现、看到 DMEM 读取之间定期轮询处于1ms 睡眠状态、PORT_STATE 命令超时为10ms。

    +int emac_set_port_state(struct prueth_emac *emac,
    +			enum icssg_port_state_cmd cmd)
    +{
    +	struct icssg_r30_cmd __iomem *p;
    +	int ret = -ETIMEDOUT;
    +	int done = 0;
    +	int i;
    +
    +	p = emac->dram.va + MGR_R30_CMD_OFFSET;
    +
    +	if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) {
    +		netdev_err(emac->ndev, "invalid port command\n");
    +		return -EINVAL;
    +	}
    +
    +	/* only one command at a time allowed to firmware */
    +	mutex_lock(&emac->cmd_lock);
    +
    +	for (i = 0; i < 4; i++)
    +		writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]);
    +
    +	/* wait for done */
    +	ret = read_poll_timeout(emac_r30_is_done, done, done == 1,
    +				1000, 10000, false, emac);


    我还会回顾 uBoot 代码。 我建议您遵循这里的 Linux 实施。
    端口链路上行/下行转换期间端口上是否有任何流量/数据包?


    BR

    JC

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

    嗨、Jayachandran

    感谢您的指导、我们的文章如下:
    #define writel (b、addr)\
    (void)((*(volatile unsigned int *)(addr))=(b))

    当我使用来自 Linux 内核代码的 arch/arm64/include/asm/ io.h 中的__raw_writel 函数来替换 emac_set_port_state 中的 writel 时

    静态__总是_inline void __ RAW_writel (u32 val、volatile void __iomem * addr)

    asm volatile ("str %W0、[%1]":"rz"(val)、"r"(addr));
    }

    经过全面测试后、结果表明问题不再可重现。因此我会通过编译工具检查 asm 代码。
    顺便说一下、需要注意的是、我们的编译工具是 llvm+clang 16.0.0

    48flf8:8b0d0129、添加 x9、x9、x13
    48f1fc:3900052c strb W12、[x9、#0x1]
    48f200:3900012b strb w1l、[x9]
    48f204:39000d2A STRT W10、[x9、#0x3]
    48f208:53107d08 1sr W8、W8、#16
    48f20c:39000928 STRT W8、[x9、#0x2]

    asm 代码显示、当使用 writel 时、它使用 strb 四次来传输 u32值。 这可能会导致问题发生?

    此外,奇怪的是,这里只有'writel'代码编译为四个'strb',而代码的其余部分是正常' str'

    谢谢
    -玉川

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

    尊敬的 Yuchan:

    asm 代码显示、当使用 writel 时、它使用 strb 四次来传输 u32值。 它可能会导致此问题?

    是的、这也是一个问题。 即使写入了1字节、固件也会向异步请求发送确认。 R30命令必须以"字"发出、它应该是"str"而不是"strb"。

    BTW、如上文所建议、保持 IOCTL 超时、这 是必需的。

    BR
    JC

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

    嗨、Jayachandran
    最后,我发现了上述问题的原因。
    位于 uboot\drivers\net\ti\icssg_config.h 中
    结构 icssg_r30_cmd{
    u32 cmd[4];
    }__packed;

    struct icssg_r30_cmd 使用 packed 属性、在我看来、它会导致存储器按一个字节对齐、因此我添加了 alignment 属性或删除__packed 属性 、测试结果是正常的。

    结构 icssg_r30_cmd{
    u32 cmd[4];
    }__alignment(16)__packed;
    或者
    结构 icssg_r30_cmd{
    u32 cmd[4];
    }

    这是 uboot 源代码中的错误吗?

    谢谢!
    -玉川

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

    尊敬的 玉川:

    仅供参考、JC 本周不在办公室

    请在下周之前收到一些回复。

    此致

    Ashwani