CH552的EP0设置为STALL以后如何恢复比较好?

最近使用CH552遇到一个枚举失败的问题。大概过程如下:

枚举过程中,主机请求了一个设备不存在的描述符。

实际为:`80 06 00 06 00 00 0A 00`请求描述符`USB_DESCR_TYP_QUALIF`

SETUP事务触发中断,大约22us以后,将EP0设置为STALL

SETUP事务在设备ACK以后大约2us,主机又发起了一个IN事务,由于此时EP0还没有设置为STALL,设备应答NAK

ISR中将EP0设置为STALL以后,主机再发起IN事务,设备应答STALL,然后主机重新请求设备描述符。过程如下图所示:

1634652752597523.jpg

主机发起SETUP事务请求设备描述符,设备应答ACK并触发中断,在中断设置EP0之前,主机又发起来了一个IN事务,由于EP0还是STALL没有改变,设备应答STALL,枚举就失败了。

1634652752190404.jpg

主要是主机的IN请求发送的太快,而MCU响应中断又太慢,有没有比较好的解决方法呢?

如果需要可以提供完整的逻辑分析仪抓包数据。

是这个问题,原作者给出了解决方案,但是感觉并不是太好。

https://whycan.com/files/members/1510/_20200127113747.png


通常我会建议客户在进入USB中断前,不管进入原因是什么,先将用到的端点的状态都改成NAK,因为NAK肯定不是一种错误状态,改成NAK之后就有充足的时间来处理事务本身,再改成ACK或者STALL。

同样的这个问题也会存在于连续数据传输过程,如果不及时将ACK状态改回NAK,可能会发生意外的数据传输。

一般这样可以解决问题。


Thats a problem which occures in all WCH usbsamples. Whenever a STALL handshake 

is send back for any reason the next Setup request is stalled too because the chip

does not automatically unstall on recieving the next Setup. For that reason no example

(including the bootloader) will pass USB2CV tests from usb.org.


For me the following works:

...

case SETUP:

        UEP0_CTRL &=0xF2; 

....


现在看来,似乎只能进SETUP的时候清除STALL来解决,如果USB的IP在STALL以后能发一个中断请求,在STALL的中断响应中处理会更优雅一些。这是我最终的处理方案:

case UIS_TOKEN_SETUP | 0:
    if((UEP0_CTRL & MASK_UEP_T_RES) == UEP_T_RES_STALL)
    {
        // STALL -> NAK
        // xxxxxx11 -> xxxxxx10
        UEP0_CTRL--;
    }



只有登录才能回复,可以选择微信账号登录