Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
STM32
USB设备_Device
winusb
stm32f1使用 usb device 的winusb 设备,无法收到接收回调
发布于 2022-03-04 12:16:17 浏览:1616
订阅该版
[tocm] 实验平台是stm32f103c8t6 最小板,想做个winusb通信。hid和cdc速度太慢了。用winusb的话使用Bulk传输,速度只受usb总线和stm32硬件把控制器的限制。 问题描述 : 使用stm32f1作为usbdevice 然后只开启了一个winusb接口。 ``` list_device device type ref count -------- -------------------- ---------- rtc RTC 0 winusb Miscellaneous Device 1 usbd USB Slave Device 0 ``` 可以看到生成出了usbd和winusb设备。 然后我写代码打开设备,进行读写,并使用python写了上位机测试代码。 python上位机可以收到stm32发过来的数据,但是python写给stm32的数据却一直没有收到 python上位机代码 ```python from usb.backend import libusb1 import usb.core import usb.util # USB_ID_VENDOR = 0x1234 USB_ID_PRODUCT = 0x5678 #print(usb.core.show_devices()) #usb_dev = usb.core.find(find_all=True,idVendor=USB_ID_VENDOR,idProduct=USB_ID_PRODUCT,backend=libusb1.get_backend() ) #for dev in usb_dev : # print(dev) usb_dev = usb.core.find(idVendor=USB_ID_VENDOR,idProduct=USB_ID_PRODUCT,backend=libusb1.get_backend() ) print(usb_dev) usb_dev.write(0x01,"1") while True: data = usb_dev.read(0x81, 64,-1) print(data) usb_dev.write(0x01,data) ``` rtthread代码 ```c #include "stdint.h" #include "stdio.h" #include "string.h" #include "rtthread.h" #include "rtdevice.h" #define DBG_TAG "usb1" #define DBG_LVL DBG_LOG #include
#define USB_DEVICE_NAME "winusb" static rt_device_t usb1_dev; /* usb 设备句柄 */ static struct rt_semaphore usb1_rx_sem; /* 用于接收消息的信号量 */ /* 接收数据回调函数 */ static rt_err_t usb1_rx_call(rt_device_t dev, rt_size_t size) { /* USB 接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */ rt_kprintf("usb1 rx call :%d\n",size); rt_sem_release(&usb1_rx_sem); return RT_EOK; } static rt_err_t usb1_tx_done(rt_device_t dev,void *buffer) { rt_kprintf("usb1 tx done :%p\n",buffer); return RT_EOK; } void usb1_send_0x123(void) { char *text = "123"; int size = rt_device_write(usb1_dev, 0,text, 3); if (size < 0) { rt_kprintf("usb1 dev write data failed rc:%d\n",size); } } static void usb1_thread(void *param) { int rc = 0; usb1_dev = rt_device_find(USB_DEVICE_NAME); if (!usb1_dev) { rt_kprintf("find %s failed!\n", USB_DEVICE_NAME); return ; }else { rt_kprintf("find %s ok!\n", USB_DEVICE_NAME); } rt_sem_init(&usb1_rx_sem, "usb1_rx_sem", 0, RT_IPC_FLAG_FIFO); /* 打开 USB 设备 */ rc = rt_device_open(usb1_dev, 0); RT_ASSERT(rc == RT_EOK); /* 设置回调函数 */ rt_device_set_rx_indicate(usb1_dev, usb1_rx_call); rt_device_set_tx_complete(usb1_dev, usb1_tx_done); uint8_t temp_buff[32] = {0}; while(1) { /* 循环读取数据,直到读取数据小于0表示缓存为空了 */ do{ rt_memset(temp_buff, 0, 32); rc = rt_device_read(usb1_dev, 0, temp_buff, 32); if(rc > 0) { rt_kprintf("usb read:%d\n",rc); for(int i=0; i < rc; i++) { rt_kprintf("0x%02X ",temp_buff[i]); } rt_kprintf("\n"); } }while(rc <= 0); rt_kprintf("usb read wait\n"); /* 阻塞等待接收信号量 */ rt_sem_take(&usb1_rx_sem, RT_WAITING_FOREVER); rt_kprintf("usb read\n"); } } int usb1_test_init(void) { static int usb1_init = 0; rt_thread_t tid; if(usb1_init > 0) { return 0; } usb1_init = 1; tid = rt_thread_create("usb1",usb1_thread, NULL,1024,20, 10); if (tid != RT_NULL) rt_thread_startup(tid); return 0; } void usb1_test(uint8_t argc, char **argv) { rt_kprintf("usb1 test\n"); usb1_send_0x123(); } MSH_CMD_EXPORT(usb1_test, usb1 test); void usb1_debug(uint8_t argc, char **argv) { if(argc > 1) { int val = atoi(argv[1]); rt_kprintf("usb1 debug set %d\n",val); } } MSH_CMD_EXPORT(usb1_debug, usb1 debug); ``` 配置 ![image.png](https://oss-club.rt-thread.org/uploads/20220304/1ffcf53fcdab9c3c15f37a07a538023d.png)
查看更多
3
个回答
默认排序
按发布时间排序
牛在飞001
2023-11-11
这家伙很懒,什么也没写!
**如果你也是遇到使用rtt自带的winusb驱动时遇到设备发送没有问题,接收却不来中断的问题,不妨可以看看我的分析:** - rtt内核版本 V5.0.0 relase - 目标平台 stm32f4系列(底层HAL、LL库) - 驱动层 RTT原生的winusb驱动 - 现象 设备枚举成功,可以主动发送数据,无法接收主机发送的数据PC(连HAL_PCD_IRQHandler()都无法进入) - 原因分析 stm32f4系列的底层usb驱动中的2个数据端点寄存器:OTG_FS_DOEPTSIZx、OTG_FS_DIEPTSIZx需要使用xxx_Transmit和xxx_recive调用后,才能正确设置到Bits 18:0 XFRSIZ字段,继续进行后续的数据传输。因此如果你也遇到这样的问题,不妨对照官方的参考手册确定一下:USB章节关于公共寄存器和设备寄存器中各相关寄存器中值在对应阶段是否符合预期,来快速排查问题吧。 - 解决办法 - 参考adbd软件包中winusb的处理方式修改。 - 在设备连接并枚举成功后,打开设备,并进行一次主动读取,来激活设备的侧的OUT端点size。 - 按照需求自定义魔改rt_err_t _function_enable(ufunction_t func)接口。 ```c static rt_err_t _function_enable(ufunction_t func) { int size; struct winusb_device *wcid; struct uio_request *req; RT_ASSERT(func != RT_NULL); wcid = func->user_data; size = EP_MAXPACKET(wcid->ep_out); req = &wcid->ep_out->request; req->buffer = rt_malloc(size); req->size = EP_MAXPACKET(wcid->ep_out); req->req_type = UIO_REQUEST_READ_BEST; rt_usbd_io_request(func->device, wcid->ep_out, req); //配置端点size rt_free(req->buffer); req->buffer = RT_NULL; return RT_EOK; } ``` - 好了下面就是一些代码极的分析了: ```c #define FUNC_ENABLE(func) do{ \ if(func->ops->enable != RT_NULL && \ func->enabled == RT_FALSE) \ { \ if(func->ops->enable(func) == RT_EOK) \ func->enabled = RT_TRUE; \ } /* * 在设备枚举完成的最后,主机会发送设置设备端配置描述,此时设备端应该在激活端点同时,配置端点的一些属性, * 即调用FUNC_ENABLE(func)里面会调用具体设备侧注册的rt_err_t _function_enable(ufunction_t func)接口 */ static rt_err_t _set_config(struct udevice* device, ureq_t setup) { //........ for (i=cfg->func_list.next; i!=&cfg->func_list; i=i->next) { /* run all functiones and their endpoints in the configuration */ ufunction_t func = (ufunction_t)rt_list_entry(i, struct ufunction, list); for(j=func->intf_list.next; j!=&func->intf_list; j=j->next) { intf = (uintf_t)rt_list_entry(j, struct uinterface, list); setting = intf->curr_setting; for(k=setting->ep_list.next; k != &setting->ep_list; k=k->next) { ep = (uep_t)rt_list_entry(k, struct uendpoint, list); /* first disable then enable an endpoint */ dcd_ep_disable(device->dcd, ep); dcd_ep_enable(device->dcd, ep); } } /* after enabled endpoints, then enable function */ FUNC_ENABLE(func); } //....... return RT_EOK; } /* * winusb 默认_function_enable里面没有调用 _ep_read_prepare * 此时的ep->out->buffer和ep->in->buffer都为空 */ static rt_err_t _function_enable(ufunction_t func) { RT_ASSERT(func != RT_NULL); return RT_EOK; } /* * winusb 默认_function_enable里面没有调用 _ep_read_prepare, * 而其他设备驱动都会调用rt_usbd_io_request()去激活数据端点的size */ static rt_ssize_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size) { HAL_PCD_EP_Receive(&_stm_pcd, address, buffer, size); if (size > 0) usb_debug_info_record(address | 0xF0, buffer, size); return size; } /* * stm32 usb在使用数据端点进行通讯时,关键是要调用USB_EPStartXfe ,设置2个关键寄存器: * ① OTG_FS device OUT endpoint-x transfer size register (OTG_FS_DOEPTSIZx) * (x = 1..3, where x = Endpoint_number) * ② OTG_FS device endpoint-x transfer size register (OTG_FS_DIEPTSIZx) * (x = 1..3, where x = Endpoint_number) * 中的 * Bits 18:0 XFRSIZ: Transfer size * This field contains the transfer size in bytes for the current endpoint. The core only *interrupts * the application after it has exhausted the transfer size amount of data. The transfer size can * be set to the maximum packet size of the endpoint, to be interrupted at the end of each * packet. * The core decrements this field every time a packet from the external memory is written to the * TxFIFO. * 即当前端点传输的size。 * * 注意:如果OTG_FS_DOEPTSIZx中的XFRSIZ为0,那么主机/pc发送数据给设备时,设备端硬件层直接返回错误码 * USBD_STATUS_CANCELED(0xc0010000),取消本次传输,导致主机端发送超时(send timeout) */ HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len) { //....... if ((ep_addr & EP_ADDR_MSK) == 0U) { (void)USB_EP0StartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable); } else { (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable); } return HAL_OK; } ``` - 最后,预祝你能够快速解决这个问题。
文武斌
2022-03-04
这家伙很懒,什么也没写!
![image.png](https://oss-club.rt-thread.org/uploads/20220304/62c4193a3175cd86a0f41968be4939e0.png.webp) ![image.png](https://oss-club.rt-thread.org/uploads/20220304/ea1490e84c28b0d7b70fee14e8490833.png.webp)
kami
2022-04-04
这家伙很懒,什么也没写!
兄弟弄好了吗? 我跟你一样. 也是中断函数不中断. 发送可以.
撰写答案
登录
注册新账号
关注者
0
被浏览
1.6k
关于作者
文武斌
这家伙很懒,什么也没写!
提问
27
回答
74
被采纳
2
关注TA
发私信
相关问题
1
裸机工程移植 RT-Thread
2
Keil MDK 移植 RT-Thread Nano
3
移植 Nano,rt_thread_mdelay()延迟时间不对
4
裸机工程移植 RT-Thread内核
5
关于利用0x68000000作为扩展sram?
6
STM32F413 SD 卡写入速度提升方法
7
STM32 RTC 闹钟
8
http_ota 提示no memory
9
studio中怎么把PB3 和PA15引脚设置为普通IO口使用?
10
求一份基于RTT系统封装好的STM32F1系列的FLASH操作程序
推荐文章
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
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
7
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部