这个问题的核心原因很可能是CY7C68013A的AUTOINLEN机制以及它对最小包大小的隐式要求。512字节传输正常是因为这通常是一个完整的FIFO块大小,而2字节传输失败是因为它触发了AUTOINLEN但没有满足其最小包要求。
以下是详细分析和解决方案:
根本原因分析:
AUTOINLEN 机制:
AUTOINLEN (由寄存器AUTOINLENH和AUTOINLENL设置)是CY7C68013A用于自动提交批量IN(FX2LP -> Host)数据的强大功能。
- 当软件(固件或驱动)将期望传输的字节数写入
AUTOININLENH:L寄存器后,一旦FPGA写入到EP6 FIFO的数据量达到或超过这个设定的AUTOINLEN值,芯片就会自动将数据打包成一个USB数据包发送出去。
- 关键限制:
AUTOINLEN设定的值必须至少为3字节。 这是芯片设计的一个硬性要求。
512字节成功的原因:
- 当
AUTOINLEN被设置为512时,FPGA向EP6 FIFO写入完整的512字节后,芯片自动触发一次符合最大包长限制(如512)的USB传输。这是完全符合预期的。
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”或超时错误。
FPGA端的行为:
- FPGA在逻辑驱动下不断尝试向EP6 FIFO写入字节。
- 当写入的数据量小于
AUTOINLEN值(或该值无效)时,芯片不会自动提交。如果FPGA持续写入而没有检查FIFO状态(FF和EF),它可能会尝试写入导致FIFO溢出(尽管通常小数据量溢出概率低,但这与故障表现一致)。
- 报告说“fpga端一直在发”表明FPGA侧逻辑是基于某种触发条件或时钟持续工作,而不等待芯片的FIFO状态指示是否允许写入或是否需要发起手动提交(
PKTEND)。
解决方案:
针对短包传输(小于AUTOINLEN最小限制,或者小于512的大包),需要使用手动提交(Manual Commit) 方式,结合PKTEND引脚信号。AUTOINLEN适合流式大数据传输或已知固定长度的较大数据块。
配置固件:禁用端点的AUTOINLEN功能 (仅对短包有效的方式):
- 在固件(
TD_Init()或类似的地方)中,将端点6配置为 FLAGS寄存器中的AUTOINLEN标志位清0 (Disable AutoInLen) 。查找控制EP6 FIFO配置的寄存器(例如EP6CFG或相关的EPxFIFOCFG,具体看文档)并确保禁用AUTOINLEN特性。关键是要让寄存器中控制INPKTEND或AUTOINLEN使能的位处于禁用状态。
启用手动提交 (INPKTEND):
- 在禁用
AUTOINLEN后,需要确保手动提交功能是启用的。FX2LP通常默认允许。确认EPxFIFOCFG中相关的位。现在,数据包的提交将由FPGA通过PKTEND信号(对应芯片引脚)控制。
修改FPGA逻辑 (PKTEND):
- 在FPGA逻辑中,当你有需要发送的数据写入到EP6 FIFO后(无论是2字节还是其他任何长度),必须在一个时钟周期内拉高
PKTEND信号。这个信号的上升沿告诉FX2LP芯片:写入FIFO的数据已经构成一个完整的USB数据包,应立即发起一次IN传输将该包发送给主机。
- 关键点:
- 写入数据 -> 确保
SLWR和IFCLK时序正确。
- 紧接着数据写入之后(确保数据已稳定写入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时):
- FPGA FIFO控制逻辑时序: 确保
SLWR(写选通)、IFCLK(接口时钟)、FD[15:0](数据总线)和PKTEND的时序满足CY7C68013A规格书的要求(建立时间Tsu,保持时间Th)。特别是PKTEND与最后一个数据的写时钟边沿的关系。
FF / EF 标志的监控: 如上述,FPGA必须在断言PKTEND前确保FIFO有空间可写(FF无效),并在断言PKTEND后等待(可能几百纳秒或更长时间)直到FIFO再次准备好接收新数据(FF再次变低)。忽略FIFO满标志强行写入会导致数据丢失或错误。
- 固件端点配置: 再次检查
EP6CFG寄存器,确保端点已启用(VALID = 1),方向是IN (DIR = IN),类型是BULK (TYPE = BULK)。
- 主机端期望与实际包大小: 主机驱动可能期望每个IN传输请求返回特定大小的包(例如预期最大包512)。如果你发送一个非常短的包(比如2字节),你需要确保主机驱动能正确处理这种情况(通常需要主机软件正确处理短包或ZLP作为传输结束的标志)。检查你的主机端应用程序代码或驱动。
- 硬件连接: 再次确认FPGA连接FX2LP的
IFCLK(时钟方向设置是否正确?), FD[15:0], SLWR, PKTEND, FLAGA (EF), FLAGB (FF)等关键信号连接无误。特别注意PKTEND信号是否连接到了FX2LP的对应引脚。如果是用的其他FLAG(如FLAGC/D)需要配置正确。
诊断步骤建议:
- 在固件初始化时禁用
EP6的AUTOINLEN。 (最可能是这一步就能解决核心问题)。
- 在FPGA逻辑中添加
PKTEND生成逻辑: 在写入需要发送的少量数据(如你的2字节)后,精确地在下一个时钟周期拉高PKTEND一个周期。
- 在FPGA逻辑中严格添加对
FF标志的监控: 仅在FF == 0时才允许写入数据到FIFO。可以在逻辑分析仪上观察这些信号。
- 使用调试工具: 如果有USB分析仪,监听实际发生的USB事务,看短包是否被发出以及内容是否正确。使用FX2LP的控制台固件(如有)读取关键寄存器状态(
EP6FIFOBUF开头的寄存器查看标志状态)。
- 简化测试: 让FPGA在满足FIFO非满条件下,仅写入2字节(0xAA, 0x55),然后立即拉高
PKTEND一个周期。反复执行此操作(每次写入前检查FF),看PC端是否能持续收到2字节包。
总结:
最可能的原因是你试图用 AUTOINLEN = 2来自动发送2字节数据,但 AUTOINLEN 必须至少设置为3 才能工作。对于小于AUTOINLEN最小限制(3字节)或任意非AUTOINLEN设定大小的包(包括你的2字节),必须使用 PKTEND信号进行手动提交。 按照上面禁用AUTOINLEN并启用PKTEND的逻辑修改你的固件和FPGA代码,并确保FPGA严格遵守FIFO状态标志进行流控,问题应该可以解决。祝顺利解决!
这个问题的核心原因很可能是CY7C68013A的AUTOINLEN机制以及它对最小包大小的隐式要求。512字节传输正常是因为这通常是一个完整的FIFO块大小,而2字节传输失败是因为它触发了AUTOINLEN但没有满足其最小包要求。
以下是详细分析和解决方案:
根本原因分析:
AUTOINLEN 机制:
AUTOINLEN (由寄存器AUTOINLENH和AUTOINLENL设置)是CY7C68013A用于自动提交批量IN(FX2LP -> Host)数据的强大功能。
- 当软件(固件或驱动)将期望传输的字节数写入
AUTOININLENH:L寄存器后,一旦FPGA写入到EP6 FIFO的数据量达到或超过这个设定的AUTOINLEN值,芯片就会自动将数据打包成一个USB数据包发送出去。
- 关键限制:
AUTOINLEN设定的值必须至少为3字节。 这是芯片设计的一个硬性要求。
512字节成功的原因:
- 当
AUTOINLEN被设置为512时,FPGA向EP6 FIFO写入完整的512字节后,芯片自动触发一次符合最大包长限制(如512)的USB传输。这是完全符合预期的。
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”或超时错误。
FPGA端的行为:
- FPGA在逻辑驱动下不断尝试向EP6 FIFO写入字节。
- 当写入的数据量小于
AUTOINLEN值(或该值无效)时,芯片不会自动提交。如果FPGA持续写入而没有检查FIFO状态(FF和EF),它可能会尝试写入导致FIFO溢出(尽管通常小数据量溢出概率低,但这与故障表现一致)。
- 报告说“fpga端一直在发”表明FPGA侧逻辑是基于某种触发条件或时钟持续工作,而不等待芯片的FIFO状态指示是否允许写入或是否需要发起手动提交(
PKTEND)。
解决方案:
针对短包传输(小于AUTOINLEN最小限制,或者小于512的大包),需要使用手动提交(Manual Commit) 方式,结合PKTEND引脚信号。AUTOINLEN适合流式大数据传输或已知固定长度的较大数据块。
配置固件:禁用端点的AUTOINLEN功能 (仅对短包有效的方式):
- 在固件(
TD_Init()或类似的地方)中,将端点6配置为 FLAGS寄存器中的AUTOINLEN标志位清0 (Disable AutoInLen) 。查找控制EP6 FIFO配置的寄存器(例如EP6CFG或相关的EPxFIFOCFG,具体看文档)并确保禁用AUTOINLEN特性。关键是要让寄存器中控制INPKTEND或AUTOINLEN使能的位处于禁用状态。
启用手动提交 (INPKTEND):
- 在禁用
AUTOINLEN后,需要确保手动提交功能是启用的。FX2LP通常默认允许。确认EPxFIFOCFG中相关的位。现在,数据包的提交将由FPGA通过PKTEND信号(对应芯片引脚)控制。
修改FPGA逻辑 (PKTEND):
- 在FPGA逻辑中,当你有需要发送的数据写入到EP6 FIFO后(无论是2字节还是其他任何长度),必须在一个时钟周期内拉高
PKTEND信号。这个信号的上升沿告诉FX2LP芯片:写入FIFO的数据已经构成一个完整的USB数据包,应立即发起一次IN传输将该包发送给主机。
- 关键点:
- 写入数据 -> 确保
SLWR和IFCLK时序正确。
- 紧接着数据写入之后(确保数据已稳定写入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时):
- FPGA FIFO控制逻辑时序: 确保
SLWR(写选通)、IFCLK(接口时钟)、FD[15:0](数据总线)和PKTEND的时序满足CY7C68013A规格书的要求(建立时间Tsu,保持时间Th)。特别是PKTEND与最后一个数据的写时钟边沿的关系。
FF / EF 标志的监控: 如上述,FPGA必须在断言PKTEND前确保FIFO有空间可写(FF无效),并在断言PKTEND后等待(可能几百纳秒或更长时间)直到FIFO再次准备好接收新数据(FF再次变低)。忽略FIFO满标志强行写入会导致数据丢失或错误。
- 固件端点配置: 再次检查
EP6CFG寄存器,确保端点已启用(VALID = 1),方向是IN (DIR = IN),类型是BULK (TYPE = BULK)。
- 主机端期望与实际包大小: 主机驱动可能期望每个IN传输请求返回特定大小的包(例如预期最大包512)。如果你发送一个非常短的包(比如2字节),你需要确保主机驱动能正确处理这种情况(通常需要主机软件正确处理短包或ZLP作为传输结束的标志)。检查你的主机端应用程序代码或驱动。
- 硬件连接: 再次确认FPGA连接FX2LP的
IFCLK(时钟方向设置是否正确?), FD[15:0], SLWR, PKTEND, FLAGA (EF), FLAGB (FF)等关键信号连接无误。特别注意PKTEND信号是否连接到了FX2LP的对应引脚。如果是用的其他FLAG(如FLAGC/D)需要配置正确。
诊断步骤建议:
- 在固件初始化时禁用
EP6的AUTOINLEN。 (最可能是这一步就能解决核心问题)。
- 在FPGA逻辑中添加
PKTEND生成逻辑: 在写入需要发送的少量数据(如你的2字节)后,精确地在下一个时钟周期拉高PKTEND一个周期。
- 在FPGA逻辑中严格添加对
FF标志的监控: 仅在FF == 0时才允许写入数据到FIFO。可以在逻辑分析仪上观察这些信号。
- 使用调试工具: 如果有USB分析仪,监听实际发生的USB事务,看短包是否被发出以及内容是否正确。使用FX2LP的控制台固件(如有)读取关键寄存器状态(
EP6FIFOBUF开头的寄存器查看标志状态)。
- 简化测试: 让FPGA在满足FIFO非满条件下,仅写入2字节(0xAA, 0x55),然后立即拉高
PKTEND一个周期。反复执行此操作(每次写入前检查FF),看PC端是否能持续收到2字节包。
总结:
最可能的原因是你试图用 AUTOINLEN = 2来自动发送2字节数据,但 AUTOINLEN 必须至少设置为3 才能工作。对于小于AUTOINLEN最小限制(3字节)或任意非AUTOINLEN设定大小的包(包括你的2字节),必须使用 PKTEND信号进行手动提交。 按照上面禁用AUTOINLEN并启用PKTEND的逻辑修改你的固件和FPGA代码,并确保FPGA严格遵守FIFO状态标志进行流控,问题应该可以解决。祝顺利解决!
举报