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);
...
}
错误包
正确包
如上所示:
我在基于4.03,4.04版本,使用USB_FS,only_host模式读写U盘时,能够正常识别U盘,但是读写U盘时经常型的陷入无限NAK的循环中。也在论坛中查看了相关的问题分享,参照修改驱动后,并没能解决问题。
后面我又在多个版本下测试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。
前两天在论坛上看到一位大佬提到,使用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协议分析仪
经过一上午的抓包分析,确定每次读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 还请论坛的大佬们帮忙看看,要怎么改…