[已解决] MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Michael2021_esp
Posts: 15
Joined: Mon Oct 04, 2021 3:09 am

[已解决] MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Postby Michael2021_esp » Tue Dec 07, 2021 5:24 am

【现象】
MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误,并且导致之后所有调用hcd_urb_enqueue失败,跟踪到函数hcd_urb_enqueue中,失败原因为下述判断前两个子条件失败
HCD_CHECK_FROM_CRIT(pipe->port->state == HCD_PORT_STATE_ENABLED // The pipe's port must be in the correct state
&& pipe->state == HCD_PIPE_STATE_ACTIVE //The pipe must be in the correct state
&& !pipe->cs_flags.pipe_cmd_processing //Pipe cannot currently be processing a pipe command
&& !pipe->cs_flags.reset_lock, //Pipe cannot be persisting through a port reset
ESP_ERR_INVALID_STATE);

同样的代码,只要发送长度不是64倍数的Bulk传输均能成功。

【代码】
申请URB时,针对长度正好是64倍数的Bulk传输已经设置如下标志

// Bulk Out对于正好MPS长度倍数的传输需要添加一个0长度包
if ((len % USB_EP_BULK_MAX_MPS) == 0) // USB_EP_BULK_MAX_MPS为64
transfer_dummy->flags |= USB_TRANSFER_FLAG_ZERO_PACK;

请问是URB哪里还需要设置吗?

@ESP_ICY

ESP_Dazz
Posts: 308
Joined: Fri Jun 02, 2017 6:50 am

Re: MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Postby ESP_Dazz » Tue Dec 07, 2021 7:25 am

在批量传输首次出现 HCD_PIPE_EVENT_ERROR_XFER 的时候,可以看看此传输的错误结果吗(transfer->status)?

之后的传输失败是正常的。当一个 Pipe 遇到错误,Pipe 会从活动状态 (HCD_PIPE_STATE_ACTIVE)转成停止状态 (HCD_PIPE_STATE_HALTED)。

停止后,Pipe 不会继续执行被入列的传输。处理停止事件通常有调用以下的命令。

1. 调用 hcd_pipe_command(pipe_hdl, HCD_PIPE_CMD_FLUSH); 将所有没执行的传输清除。Flush 之后要将要将每个被清除的传输用 hcd_urb_dequeue() 出列。
2. 用 hcd_pipe_command(pipe_hdl, HCD_PIPE_CMD_CLEAR) 将 pipe 回复到活动状态。

Michael2021_esp
Posts: 15
Joined: Mon Oct 04, 2021 3:09 am

Re: MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Postby Michael2021_esp » Wed Dec 08, 2021 3:22 am

目前最新的现象是,只要发送长度为64倍数的bulk传输,就出现assert失败。暂时无法跟踪看到urb->transfer.status的取值。在usbh_hal_chan_decode_intr函数中assert失败,见红色字体


usbh_hal_chan_event_t usbh_hal_chan_decode_intr(usbh_hal_chan_t *chan_obj)
{
uint32_t chan_intrs = usbh_ll_chan_intr_read_and_clear(chan_obj->regs);
usbh_hal_chan_event_t chan_event;

if (chan_intrs & CHAN_INTRS_ERROR_MSK) { //Note: Errors are uncommon, so we check against the entire interrupt mask to reduce frequency of entering this call path
HAL_ASSERT(chan_intrs & USBH_LL_INTR_CHAN_CHHLTD); //An error should have halted the channel




【Monitor窗口输出】
assert failed: usbh_hal_chan_decode_intr IDF/components/hal/usbh_hal.c:371 (chan_intrs & USBH_LL_INTR_CHAN_CHHLTD)


Backtrace:0x40025872:0x3ffc82b00x4002bfc5:0x3ffc82d0 0x40032cb2:0x3ffc82f0 0x40096abd:0x3ffc8410 0x4008f7c0:0x3ffc8430 0x40026cce:0x3ffc8470 0x400f48df:0x3ff9f940 0x40095d02:0x3ff9f960 0x4002d0c7:0x3ff9f980
0x40025872: panic_abort at ~/esp/esp-idf/components/esp_system/panic.c:402

0x4002bfc5: esp_system_abort at ~/esp/esp-idf/components/esp_system/esp_system.c:129

0x40032cb2: __assert_func at ~/esp/esp-idf/components/newlib/assert.c:85

0x40096abd: usbh_hal_chan_decode_intr at ~/esp/esp-idf/components/hal/usbh_hal.c:371 (discriminator 1)

0x4008f7c0: _intr_hdlr_chan at ~/esp/esp-idf/components/usb/hcd.c:826
(inlined by) intr_hdlr_main at ~/Project/esp/esp-idf/components/usb/hcd.c:916

ESP_Dazz
Posts: 308
Joined: Fri Jun 02, 2017 6:50 am

Re: MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Postby ESP_Dazz » Wed Dec 08, 2021 8:23 am

如果不包括 USB_TRANSFER_FLAG_ZERO_PACK 还会出问题吗?你现在用的设备时什么 Device Class?

Michael2021_esp
Posts: 15
Joined: Mon Oct 04, 2021 3:09 am

Re: MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Postby Michael2021_esp » Wed Dec 08, 2021 9:38 am

如果不包括 USB_TRANSFER_FLAG_ZERO_PACK 还会出问题吗?你现在用的设备时什么 Device Class?
-- 对端设备为市场上的安卓手机。
-- 如果不设置这个USB_TRANSFER_FLAG_ZERO_PACK标志,不会出现assert失败,URB完成状态为USB_TRANSFER_STATUS_COMPLETED,但是再发送新的bulk传输就出现HCD_PIPE_EVENT_ERROR_XFER了,URB完成状态为USB_TRANSFER_STATUS_ERROR。

当前我做了特殊保护,一旦发现是64倍数则自动拆分成两个bulk传输,临时解决了这个问题。
目前,同样的报文,通过PC发出到同一个安卓手机是没问题的
Last edited by Michael2021_esp on Thu Dec 09, 2021 6:12 am, edited 1 time in total.

Michael2021_esp
Posts: 15
Joined: Mon Oct 04, 2021 3:09 am

Re: MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Postby Michael2021_esp » Thu Dec 09, 2021 6:11 am

@ESP_Dazz 长度为64倍数的批量传输拆分为2个批量传输,目前看解决了大多数的情况,但是其中有一个256长度的报文,业务逻辑上不能拆分。还是请指导一下如何解决这个问题。

ESP_Dazz
Posts: 308
Joined: Fri Jun 02, 2017 6:50 am

Re: MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Postby ESP_Dazz » Thu Dec 09, 2021 11:28 am

Michael2021_esp wrote:如果不设置这个USB_TRANSFER_FLAG_ZERO_PACK标志,不会出现assert失败
看起来 USB_TRANSFER_FLAG_ZERO_PACK 可能有点问题。我会再检查。但是需要用 USB_TRANSFER_FLAG_ZERO_PACK 的情况很少。我不是很懂为什么你发bulk传输要加 USB_TRANSFER_FLAG_ZERO_PACK。当 urb->transfer.num_bytes 是端点 MPS (例如 64) 的 N 倍时,HCD 已经会自动加最后的 zero packet。
Michael2021_esp wrote:但是其中有一个256长度的报文,业务逻辑上不能拆分。还是请指导一下如何解决这个问题
我也不是很懂为什么要手动的拆分。如果 urb->transfer.num_bytes = 256,HCD 会自动将 256 拆成 N 个 MPS 长的 packet.

HCD 使用的 URB 时对应 USB2.0 协议里的 Transfer,而不是 Transaction。用户只需配 urb->transfer.num_bytes 然后 HCD 会处理所有拆分 MPS packet 的操作。

Michael2021_esp
Posts: 15
Joined: Mon Oct 04, 2021 3:09 am

Re: MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Postby Michael2021_esp » Thu Dec 09, 2021 12:44 pm

看起来 USB_TRANSFER_FLAG_ZERO_PACK 可能有点问题。我会再检查。但是需要用 USB_TRANSFER_FLAG_ZERO_PACK 的情况很少。我不是很懂为什么你发bulk传输要加 USB_TRANSFER_FLAG_ZERO_PACK。当 urb->transfer.num_bytes 是端点 MPS (例如 64) 的 N 倍时,HCD 已经会自动加最后的 zero packet。
是这样的:
STEP1. 最开始的时候,因为发送4096字节的Transfer的时候出现HCD_PIPE_EVENT_ERROR_XFER错误导致后面流程无法走下去,才尝试去添加USB_TRANSFER_FLAG_ZERO_PACK,结果出现assert失败。然后就去掉USB_TRANSFER_FLAG_ZERO_PACK,进入STEP2的方式进行尝试

STEP2. 然后尝试将4096字节的Transfer拆分为4096-32字节的Transfer1 + 32字节的Transfer2,目的是规避STEP1的错误。两个Transfer执行均成功

然后在上述尝试的过程中,发现只要是长度是64倍数的Transfer都会出现HCD_PIPE_EVENT_ERROR_XFER错误。长
看起来 USB_TRANSFER_FLAG_ZERO_PACK 可能有点问题。我会再检查。
期待这个结果,因为目前有一个256字节的Transfer无法采用上述STEP2拆分为两个Transfer,只能作为一个Transfer发送。如果USB_TRANSFER_FLAG_ZERO_PACK处理有更新,拜托通知一声

Michael2021_esp
Posts: 15
Joined: Mon Oct 04, 2021 3:09 am

Re: MASTER版本USB HOST批量传输时如数据长度正好是64的倍数导致HCD_PIPE_EVENT_ERROR_XFER错误

Postby Michael2021_esp » Wed Dec 15, 2021 3:32 am

问题已经解决,感谢乐鑫工程师

Who is online

Users browsing this forum: No registered users and 29 guests