Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
USB主机_host
USB host设备调试问题
发布于 2020-05-28 18:06:34 浏览:3674
订阅该版
这个RNDIS的已经接近了,ECM的 协议配置还有问题,暂时停止了! 1.想要增加usb host 模式下ECM使用,第一步遇到的问题 当把一个usb device ecm的设备插入 host中,发现没有枚举成功,打开usb log 查看是在usb host进行 获取完整的配置描述符的时候失败了。 170行 ![usb.png](/uploads/202005/28/174330jm9eempm3zm36p68.png) 调用顺序如下: ```c /* get full configuration descriptor */ ret = rt_usbh_get_descriptor(device, USB_DESC_TYPE_CONFIGURATION, device->cfg_desc, cfg_desc.wTotalLength); ``` ```c rt_err_t rt_usbh_get_descriptor(uinst_t device, rt_uint8_t type, void* buffer, int nbytes) { struct urequest setup; int timeout = USB_TIMEOUT_BASIC; RT_ASSERT(device != RT_NULL); setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE; setup.bRequest = USB_REQ_GET_DESCRIPTOR; setup.wIndex = 0; setup.wLength = nbytes; setup.wValue = type << 8; if(rt_usb_hcd_setup_xfer(device->hcd, device->pipe_ep0_out, &setup, timeout) == 8) { if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_in, buffer, nbytes, timeout) == nbytes) { if(rt_usb_hcd_pipe_xfer(device->hcd, device->pipe_ep0_out, RT_NULL, 0, timeout) == 0) { return RT_EOK; } } } return RT_ERROR; } ``` 先发送setup给device,device回复ack,然后进行数据传输,接收device的描述符, ```c int rt_usb_hcd_pipe_xfer(uhcd_t hcd, upipe_t pipe, void* buffer, int nbytes, int timeout) { rt_size_t remain_size; rt_size_t send_size; remain_size = nbytes; rt_uint8_t * pbuffer = (rt_uint8_t *)buffer; do { RT_DEBUG_LOG(RT_DEBUG_USB,("pipe transform remain size,: %d
", remain_size)); send_size = (remain_size > pipe->ep.wMaxPacketSize) ? pipe->ep.wMaxPacketSize : remain_size; if(hcd->ops->pipe_xfer(pipe, USBH_PID_DATA, pbuffer, send_size, timeout) == send_size) { remain_size -= send_size; pbuffer += send_size; } else { return 0; } }while(remain_size > 0); return nbytes; } ``` rt_usb_hcd_pipe_xfer 数据传输的逻辑是,当要发送或者接收的数据小于端点最大长度,直接发送,大于的时候,每次都发送端点最大长度,最后不够端点长度的再发送一次。 `hcd->ops->pipe_xfer`本质调用的是 ```c static int drv_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts) { int timeout = timeouts; while (1) { if (!connect_status) { return -1; } rt_completion_init(&urb_completion); HAL_HCD_HC_SubmitRequest(&stm32_hhcd_fs, pipe->pipe_index, (pipe->ep.bEndpointAddress & 0x80) >> 7, pipe->ep.bmAttributes, token, buffer, nbytes, 0); rt_completion_wait(&urb_completion, timeout); rt_thread_mdelay(1); if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == HC_NAK) { RT_DEBUG_LOG(RT_DEBUG_USB, ("nak
")); if (pipe->ep.bmAttributes == USB_EP_ATTR_INT) { rt_thread_delay((pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) > 0 ? (pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) : 1); } HAL_HCD_HC_Halt(&stm32_hhcd_fs, pipe->pipe_index); HAL_HCD_HC_Init(&stm32_hhcd_fs, pipe->pipe_index, pipe->ep.bEndpointAddress, pipe->inst->address, USB_OTG_SPEED_FULL, pipe->ep.bmAttributes, pipe->ep.wMaxPacketSize); continue; } else if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == HC_STALL) { RT_DEBUG_LOG(RT_DEBUG_USB, ("stall
")); pipe->status = UPIPE_STATUS_STALL; if (pipe->callback != RT_NULL) { pipe->callback(pipe); } return -1; } else if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == URB_ERROR) { RT_DEBUG_LOG(RT_DEBUG_USB, ("error
")); pipe->status = UPIPE_STATUS_ERROR; if (pipe->callback != RT_NULL) { pipe->callback(pipe); } return -1; } else if(URB_DONE == HAL_HCD_HC_GetURBState(&stm32_hhcd_fs, pipe->pipe_index)) { RT_DEBUG_LOG(RT_DEBUG_USB, ("ok
")); pipe->status = UPIPE_STATUS_OK; if (pipe->callback != RT_NULL) { pipe->callback(pipe); } size_t size = HAL_HCD_HC_GetXferCount(&stm32_hhcd_fs, pipe->pipe_index); if (pipe->ep.bEndpointAddress & 0x80) { return size; } else if (pipe->ep.bEndpointAddress & 0x00) { return size; } return nbytes; }else{ RT_DEBUG_LOG(RT_DEBUG_USB, ("other
")); } continue; } } ``` 接下来就出现问题了,当枚举过程中,数据发送/接收的长度小于64(端点最大长度)的时候就会成功,我用U盘和其他usb设备测试了 例如下面一个usb设备的插入打印如下,有一些自己加的打印 ![usb2.png](/uploads/202005/28/175608m5wwq89d461w7maz.png) 红色部分为获取完整配置描述符,这个描述符总长度32,因为小于64,所以返回了OK,枚举成功了,当我换成ecm的device设备的时候(可以使用rtt本身的usb devcie里面的ecm进行测试或者其他的ecm设备,或者找一个完整描述符长度大于63的设备) 打印如下 ![3333333.png](/uploads/202005/28/175857kdc9dmqdqjpap1pp.png) 可以看到这个描述符总长度203 因为大于64,所以第一次接收64个,还剩余139个,再接收64个,还剩余75,应该再接收64个,剩余15,再接收15个 就是正常的,但是接收了一半就出现了nak。 然后一直while循环 nak 退不出去。 以为是超时问题,超时时间我也改大了,还是这个问题。 这个是什么问题呢?有没有什么办法请教下 新增加一个usb设备插入的 log,这个端点最大长度为8,full描述符长度18 ![4.png](/uploads/202005/28/182232sberta5cmt9gtyg5.png)
查看更多
14
个回答
默认排序
按发布时间排序
肉肉肉肉肉肉多
2020-05-29
这家伙很懒,什么也没写!
[i=s] 本帖最后由 肉肉肉肉肉肉多 于 2020-5-29 10:32 编辑 [/i] 看起来是主机这边in方向 收到的是NAK信号,但是nak只有在开始发送setup到设备后,读取设备端点0, 设备端点0还没有准备数据的时候才会收到NAK,当设备收到setup后,然后发送数据给主机,这个时候,主机会读取数据。 情况是主机已经读取到full配置字符的数据一部分数据后,突然收到nak信号了。 时序问题么?
_xiangxi
2020-05-29
这家伙很懒,什么也没写!
配置描述符是一次性获取,然后再解析的。 这个64字节拆包,我印象中,我也遇到过这个情况。 现在拆包的操作是系统做的,试一试不由系统拆包,而由硬件拆包试试。 ```c int rt_usb_hcd_pipe_xfer(uhcd_t hcd, upipe_t pipe, void* buffer, int nbytes, int timeout) { rt_size_t remain_size; rt_size_t send_size; int size; remain_size = nbytes; rt_uint8_t * pbuffer = (rt_uint8_t *)buffer; do { RT_DEBUG_LOG(RT_DEBUG_USB,("control pipe transform remain size: %d\n", remain_size)); send_size = remain_size; size = hcd->ops->pipe_xfer(pipe, USBH_PID_DATA, pbuffer, send_size, timeout); if(size == -1) { return -1; } else if(size == send_size) { remain_size -= send_size; } else { RT_DEBUG_LOG(RT_DEBUG_USB, ("Attention: send failed,send_size = %d, wMaxPacketSize = %d\n", send_size, pipe->ep.wMaxPacketSize)); return 0; } }while(remain_size > 0); return nbytes; } ``` 做一下类似处理。现在,无论是bulk方式的in,out方式都是一致的,感觉有问题。 如果很有必要,可以分开写这些功能。
肉肉肉肉肉肉多
2020-05-30
这家伙很懒,什么也没写!
>配置描述符是一次性获取,然后再解析的。 这个64字节拆包,我印象中,我也遇到过这个情况。 现在拆包的操作 ... 好, 我后天试一试,你host是做什么的?
肉肉肉肉肉肉多
2020-05-30
这家伙很懒,什么也没写!
>配置描述符是一次性获取,然后再解析的。 这个64字节拆包,我印象中,我也遇到过这个情况。 现在拆包的操作 ... rtt这么做,应该是参考usb协议这样写的。
_xiangxi
2020-06-01
这家伙很懒,什么也没写!
>rtt这么做,应该是参考usb协议这样写的。 CDC类的RNDIS,和ECM差不多的; 话说,问题解决了吗?
肉肉肉肉肉肉多
2020-06-02
这家伙很懒,什么也没写!
>CDC类的RNDIS,和ECM差不多的; 话说,问题解决了吗? 今天才有时间,我现在弄,方便给个联系方式么,可以直接联系
肉肉肉肉肉肉多
2020-06-02
这家伙很懒,什么也没写!
>CDC类的RNDIS,和ECM差不多的; 话说,问题解决了吗? 枚举到了,接下来准备实现class类了, rndis 和ecm的host下面 还不知道怎么处理,,,
肉肉肉肉肉肉多
2020-06-02
这家伙很懒,什么也没写!
>CDC类的RNDIS,和ECM差不多的; 话说,问题解决了吗? 我在思考怎么定义rndis的设备结构体比较好。 还有后面的数据收发,协议通信都要看看,可以看下你的怎么定义实现的吗?
肉肉肉肉肉肉多
2020-06-02
这家伙很懒,什么也没写!
>CDC类的RNDIS,和ECM差不多的; 话说,问题解决了吗? 有点奇怪,我到setup config的时候 又不行了, 我再看看,setup的时候 是不是也改改
_xiangxi
2020-06-03
这家伙很懒,什么也没写!
>有点奇怪,我到setup config的时候 又不行了,我再看看,setup的时候 是不是也改改 ... 确实需要一些修改,CDC类有两个bulk端口,和一个中断端口。 现在的USB_HOST只能同时读取一个端口。要不然,信息时发不出去的。 我的邮箱:xiangxistu@foxmail.com
撰写答案
登录
注册新账号
关注者
0
被浏览
3.7k
关于作者
肉肉肉肉肉肉多
这家伙很懒,什么也没写!
提问
4
回答
28
被采纳
0
关注TA
发私信
相关问题
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部