USB论坛
直播中

李皓圳

8年用户 1179经验值
私信 关注
[问答]

USB芯片CY7C68013A和FPGA进行通信,从EP6读取512字节是正常的,但是读取2个字节失败,为什么?

大家好,USB芯片CY7C68013A和FPGA进行通信,从EP6读取512字节是正常的,但是读取2个字节失败(fpga端一直在发)Bulk IN failed,谢谢

回帖(1)

陈存楼

2025-6-5 17:53:21

这个问题的核心原因很可能是CY7C68013A的AUTOINLEN机制以及它对最小包大小的隐式要求。512字节传输正常是因为这通常是一个完整的FIFO块大小,而2字节传输失败是因为它触发了AUTOINLEN但没有满足其最小包要求。


以下是详细分析和解决方案:


根本原因分析:




  1. AUTOINLEN 机制:



    • AUTOINLEN (由寄存器AUTOINLENHAUTOINLENL设置)是CY7C68013A用于自动提交批量IN(FX2LP -> Host)数据的强大功能。

    • 当软件(固件或驱动)将期望传输的字节数写入AUTOININLENH:L寄存器后,一旦FPGA写入到EP6 FIFO的数据量达到或超过这个设定的AUTOINLEN值,芯片就会自动将数据打包成一个USB数据包发送出去。

    • 关键限制: AUTOINLEN设定的值必须至少为3字节。 这是芯片设计的一个硬性要求。




  2. 512字节成功的原因:



    • AUTOINLEN被设置为512时,FPGA向EP6 FIFO写入完整的512字节后,芯片自动触发一次符合最大包长限制(如512)的USB传输。这是完全符合预期的。




  3. 2字节失败的原因:



    • AUTOINLEN被设置为2(或小于3的值)时:

      • 芯片内部检测到AUTOINLEN值小于3,它不会将这个无效设置用于自动提交

      • 即使FPGA持续向FIFO写入2字节数据,芯片永远不会因为达到了“2”这个设定值而自动发起一个USB传输。

      • 结果就是,FPGA一直发数据(状态可能显示FF(FIFO满)短暂为0然后又变1),但FIFO中的数据(只有2字节或者更多但未达到AUTOINLEN要求的>=3字节)没有被实际发送

      • PC主机端: 当PC主机尝试发起一个IN传输读取数据时,它期望接收数据,但芯片根本没有准备好有效的数据包。因为数据卡在FIFO里没发出去(要么是因为AUTOINLEN设置无效不触发发送,要么是发送机制在等待满足>=3字节的条件)。这导致主机驱动报告“Bulk IN failed”或超时错误。





  4. FPGA端的行为:



    • FPGA在逻辑驱动下不断尝试向EP6 FIFO写入字节。

    • 当写入的数据量小于AUTOINLEN值(或该值无效)时,芯片不会自动提交。如果FPGA持续写入而没有检查FIFO状态(FFEF),它可能会尝试写入导致FIFO溢出(尽管通常小数据量溢出概率低,但这与故障表现一致)。

    • 报告说“fpga端一直在发”表明FPGA侧逻辑是基于某种触发条件或时钟持续工作,而不等待芯片的FIFO状态指示是否允许写入或是否需要发起手动提交(PKTEND)。




解决方案:


针对短包传输(小于AUTOINLEN最小限制,或者小于512的大包),需要使用手动提交(Manual Commit) 方式,结合PKTEND引脚信号。AUTOINLEN适合流式大数据传输或已知固定长度的较大数据块。




  1. 配置固件:禁用端点的AUTOINLEN功能 (仅对短包有效的方式):



    • 在固件(TD_Init()或类似的地方)中,将端点6配置为 FLAGS寄存器中的AUTOINLEN标志位清0 (Disable AutoInLen) 。查找控制EP6 FIFO配置的寄存器(例如EP6CFG或相关的EPxFIFOCFG,具体看文档)并确保禁用AUTOINLEN特性。关键是要让寄存器中控制INPKTENDAUTOINLEN使能的位处于禁用状态。




  2. 启用手动提交 (INPKTEND):



    • 在禁用AUTOINLEN后,需要确保手动提交功能是启用的。FX2LP通常默认允许。确认EPxFIFOCFG中相关的位。现在,数据包的提交将由FPGA通过PKTEND信号(对应芯片引脚)控制。




  3. 修改FPGA逻辑 (PKTEND):



    • 在FPGA逻辑中,当你有需要发送的数据写入到EP6 FIFO后(无论是2字节还是其他任何长度),必须在一个时钟周期内拉高PKTEND信号。这个信号的上升沿告诉FX2LP芯片:写入FIFO的数据已经构成一个完整的USB数据包,应立即发起一次IN传输将该包发送给主机。

    • 关键点:

      • 写入数据 -> 确保SLWRIFCLK时序正确。

      • 紧接着数据写入之后(确保数据已稳定写入FIFO),在一个时钟周期内断言PKTEND

      • 断言PKTEND后,短包(即使是0字节包,称为ZLP)也会被立刻发送。

      • 在等待主机读取或完成传输期间,FPGA不能持续无脑写入数据。它需要:

        • 监控FIFO状态标志FF (Full Flag) 和 EF (Empty Flag)。在断言PKTEND发送数据包期间或主机读取期间,FIFO可能变得不可写。

        • 等待FF为低(表明FIFO有空间)再写入下一批数据。

        • 对于短包,写入数据后立即PKTEND。对于大包,可以选择一次写满再PKTEND(但需保证不超过USB max packet size限制),或者自己实现类似AUTOINLEN的逻辑,累积到一定字节数再手动PKTEND(此时大于等于3字节的限制就没有了)。






其他可能原因及检查点(即使在用PKTEND时):



  1. FPGA FIFO控制逻辑时序: 确保SLWR(写选通)、IFCLK(接口时钟)、FD[15:0](数据总线)和PKTEND的时序满足CY7C68013A规格书的要求(建立时间Tsu,保持时间Th)。特别是PKTEND与最后一个数据的写时钟边沿的关系。

  2. FF / EF 标志的监控: 如上述,FPGA必须在断言PKTEND前确保FIFO有空间可写(FF无效),并在断言PKTEND后等待(可能几百纳秒或更长时间)直到FIFO再次准备好接收新数据(FF再次变低)。忽略FIFO满标志强行写入会导致数据丢失或错误。

  3. 固件端点配置: 再次检查EP6CFG寄存器,确保端点已启用(VALID = 1),方向是IN (DIR = IN),类型是BULK (TYPE = BULK)。

  4. 主机端期望与实际包大小: 主机驱动可能期望每个IN传输请求返回特定大小的包(例如预期最大包512)。如果你发送一个非常短的包(比如2字节),你需要确保主机驱动能正确处理这种情况(通常需要主机软件正确处理短包或ZLP作为传输结束的标志)。检查你的主机端应用程序代码或驱动。

  5. 硬件连接: 再次确认FPGA连接FX2LP的IFCLK(时钟方向设置是否正确?), FD[15:0], SLWR, PKTEND, FLAGA (EF), FLAGB (FF)等关键信号连接无误。特别注意PKTEND信号是否连接到了FX2LP的对应引脚。如果是用的其他FLAG(如FLAGC/D)需要配置正确。


诊断步骤建议:



  1. 在固件初始化时禁用EP6AUTOINLEN (最可能是这一步就能解决核心问题)。

  2. 在FPGA逻辑中添加PKTEND生成逻辑: 在写入需要发送的少量数据(如你的2字节)后,精确地在下一个时钟周期拉高PKTEND一个周期。

  3. 在FPGA逻辑中严格添加对FF标志的监控: 仅在FF == 0时才允许写入数据到FIFO。可以在逻辑分析仪上观察这些信号。

  4. 使用调试工具: 如果有USB分析仪,监听实际发生的USB事务,看短包是否被发出以及内容是否正确。使用FX2LP的控制台固件(如有)读取关键寄存器状态(EP6FIFOBUF开头的寄存器查看标志状态)。

  5. 简化测试: 让FPGA在满足FIFO非满条件下,仅写入2字节(0xAA, 0x55),然后立即拉高PKTEND一个周期。反复执行此操作(每次写入前检查FF),看PC端是否能持续收到2字节包。


总结:


最可能的原因是你试图用 AUTOINLEN = 2来自动发送2字节数据,但 AUTOINLEN 必须至少设置为3 才能工作。对于小于AUTOINLEN最小限制(3字节)或任意非AUTOINLEN设定大小的包(包括你的2字节),必须使用 PKTEND信号进行手动提交。 按照上面禁用AUTOINLEN并启用PKTEND的逻辑修改你的固件和FPGA代码,并确保FPGA严格遵守FIFO状态标志进行流控,问题应该可以解决。祝顺利解决!

举报

更多回帖

发帖
×
20
完善资料,
赚取积分