嵌入式技术william hill官网
直播中

糖栗子

8年用户 666经验值
擅长:MEMS/传感技术
私信 关注
[问答]

测试USBHOST读写U盘出错是何原因

rt_err_t rt_usbh_storage_read10(struct uhintf* intf, rt_uint8_t buffer,
rt_uint32_t sector, rt_size_t count, int timeout)
{
struct ustorage_cbw cmd;
rt_base_t level;
/
parameter check /
if(intf == RT_NULL)
{
rt_kprintf("interface is not available\n");
return -RT_EIO;
}
RT_ASSERT(intf->device != RT_NULL);
RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_storage_read10\n"));
/
construct the command block wrapper /
level = rt_hw_interrupt_disable();
rt_memset(&cmd, 0, sizeof(struct ustorage_cbw));
cmd.signature = CBW_SIGNATURE;
cmd.tag = CBW_TAG_VALUE;
cmd.xfer_len = SECTOR_SIZE * count;
cmd.dflags = CBWFLAGS_DIR_IN;
cmd.lun = 0;
cmd.cb_len = 10;
cmd.cb[0] = SCSI_READ_10;
cmd.cb[1] = 0;
cmd.cb[2] = (rt_uint8_t)(sector >> 24);
cmd.cb[3] = (rt_uint8_t)(sector >> 16);
cmd.cb[4] = (rt_uint8_t)(sector >> 8);
cmd.cb[5] = (rt_uint8_t)sector;
cmd.cb[6] = 0;
cmd.cb[7] = (count & 0xff00) >> 8;
cmd.cb[8] = (rt_uint8_t) count & 0xff;
rt_hw_interrupt_enable(level);
return rt_usb_bulk_only_xfer(intf, &cmd, buffer, timeout);
}
static rt_err_t rt_usb_bulk_only_xfer(struct uhintf
intf,
ustorage_cbw_t cmd, rt_uint8_t* buffer, int timeout)
{
...
do
{
/* send the cbw /
size = rt_usb_hcd_pipe_xfer(stor->pipe_out->inst->hcd, stor->pipe_out,
cmd, SIZEOF_CBW, timeout);
if(size != SIZEOF_CBW)
{
rt_kprintf("CBW size error\n");
return -RT_EIO;
}
if (cmd->xfer_len != 0)
{
pipe = (cmd->dflags == CBWFLAGS_DIR_IN) ? stor->pipe_in :
stor->pipe_out;
size = rt_usb_hcd_pipe_xfer(pipe->inst->hcd, pipe, (void
)buffer,
cmd->xfer_len, timeout);
if(size != cmd->xfer_len)
{
rt_kprintf("request size %d, transfer size %d\n",
cmd->xfer_len, size);
break;
}
}
/* receive the csw */
size = rt_usb_hcd_pipe_xfer(stor->pipe_in->inst->hcd, stor->pipe_in,
&csw, SIZEOF_CSW, timeout);
if(size != SIZEOF_CSW)
{
rt_kprintf("csw size error\n");
return -RT_EIO;
}
}while(0);
...
}
错误包

1.jpg

正确包

2.jpg

如上所示:

我在基于4.03,4.04版本,使用USB_FS,only_host模式读写U盘时,能够正常识别U盘,但是读写U盘时经常型的陷入无限NAK的循环中。也在william hill官网 中查看了相关的问题分享,参照修改驱动后,并没能解决问题。

后面我又在多个版本下测试USBHOST 读写U盘
(1)TM官方的裸机USBhost读写U盘工程,U盘热插拔,读写均无问题
(2)裸机工程加入nano3.15,U盘热插拔,读写无问题;
(3)裸机工程中的usbhost 的相关驱动,完整移植到4.04中,u盘识别要十几秒的时间,无法正常读写。
(4)裸机工程中的usbhost 的相关驱动,完整移植到4.02中,U盘热插拔,读写均无问题
(5) 4.02下使用rtt的usb驱动,U盘读写无问题;
(6)将4.02的内核替换至4.03下,U盘读写异常,仍然是无限NAK。

前两天在william hill官网 上看到一位大佬提到,使用usb协议抓包分析,发现是主机在提交一个读请求时被中断打断,导致U盘回复NAK。后经仿真调试确定每次都是在

size = rt_usb_hcd_pipe_xfer(stor->pipe_out->inst->hcd, stor->pipe_out,
                                cmd, SIZEOF_CBW, timeout);
    if(size != SIZEOF_CBW) 
    {
        rt_kprintf("CBW size error\n");
        return -RT_EIO;
    }
    if (cmd->xfer_len != 0)
    {
        pipe = (cmd->dflags == CBWFLAGS_DIR_IN) ? stor->pipe_in :
            stor->pipe_out;
        size = rt_usb_hcd_pipe_xfer(pipe->inst->hcd, pipe, (void*)buffer, 
            cmd->xfer_len, timeout);
        if(size != cmd->xfer_len)
        {
            rt_kprintf("request size %d, transfer size %d\n", 
                cmd->xfer_len, size);
            break;
        }    
    }

发生CBW命令后,传输出错。

下单购买了一个USB协议分析仪

Dingtalk_20220823141122.jpg

经过一上午的抓包分析,确定每次读U盘陷入无限nak错误的时候,就是因为发送 CBW 指令出错。

正确的一包 读数据的时候 CBW 指令
55 53 42 43 78 56 34 12 00 02 00 00 80 00 0A 28
00 00 00 88 00 00 00 01 00 00 00 00 00 00 00

而出错时,分析仪抓包到的 数据是
EE 6D FA EB DA 8D (不固定,但确实不是上面那个正确的包)

尝试修复这个bug

level = rt_hw_interrupt_disable();
        HAL_HCD_HC_SubmitRequest(&stm32_hhcd_fs,
                                 pipe->pipe_index, //通道号
                                 direction,
                                 pipe->ep.bmAttributes,
                                 token,
                                 buffer,
                                 nbytes,
                                 0);
        rt_thread_mdelay(1);
        rt_hw_interrupt_enable(level);

在发送包的时候,关闭中断,甚至加入延时,都无法避免这个问题。

本人由于不是很熟悉STM32 USB数据发送过程,不知道怎么去避免USB数据发送出错的情况,所以这个bug 还请william hill官网 的大佬们帮忙看看,要怎么改…

回帖(6)

李俊

2022-8-23 14:13:08
结论是啥?是因为中断吗?
举报

糖栗子

2022-8-23 14:13:23
不清楚,我关中断了也不行,还是会出现数据包错误
举报

李俊

2022-8-23 14:13:44
nak 其实可以多等一会儿,多等一会儿变成正常状态也可以。
还有就是改变那个包大小。
举报

刘桂英

2022-8-23 14:13:52
看你的分析,看样子是os调度影响了 usb通信,NAK的行为是device的,所以主机发送错误以后,device才会nack,主机发送错误,主要可能是os调度卡在了某个位置,使得complete irq么有完成,但是可能是完成了,调度没有结束,又重新走了一遍。
举报

刘桂英

2022-8-23 14:13:59
数据错误根据我的经验,一般是crc16错误,引起的turnaround timeout。(高级的usb分析仪是这么说的)
举报

刘桂英

2022-8-23 14:14:07
还有一些可能是 device的usb信号太差,或者寄存器优化等配置以后,导致总线上信号差,识别要十几秒,基本别玩了。
举报

更多回帖

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