完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
热插拔后,pc主机端可以识别设备,可以打开->关闭->打开串口,但是,一旦主动发送数据就提示
串口号故障!自动修复中… 关闭串口… 打开串口… 但是,同时,mcu的usbd端主动发送数据给pc端的host,host正常接收数据 即,热插拔前 usbd(mcu) <—> host(pc) 可以正常双向收发 但是,热插拔后 usbd(mcu) —> host(pc),只能usbd往host发(dtr的控制可以host -> usbd) |
|
相关推荐
1个回答
|
|
|
我们遇到的问题是在使用cdc_acm_template.c进行测试时,热插拔后出现的问题。具体表现为: 热插拔后,PC主机端可以识别设备,可以打开->关闭->打开串口,但是当PC主机端主动发送数据时,就提示串口号故障,然后尝试自动修复(关闭再打开串口)。而与此同时,从MCU的USB设备端(usbd)主动发送数据到PC主机端,主机却能正常接收。另外,DTR控制信号(属于控制传输)也能正常从主机发送到设备。 热插拔前,双向通信都正常;热插拔后,只有设备到主机的通信正常,主机到设备的数据传输出现故障。 根据描述,问题可能出现在以下几个方面: 1. **USB设备配置**:热插拔后,设备重新枚举,但可能存在配置不正确的地方,特别是端点配置。 2. **端点状态**:热插拔后,主机到设备的端点(通常是OUT端点)可能没有正确配置或激活。 3. **主机驱动问题**:主机端的CDC驱动程序在热插拔后可能没有正确处理OUT端点。 4. **设备固件处理**:设备固件在热插拔后可能没有正确重置端点或重新初始化。 在cdc_acm_template.c中,我们需要关注以下几个部分: - **配置描述符**:确保端点的地址和属性设置正确。 - **端点最大包长度**:必须与主机端期望的一致(CDC通常使用64字节)。 - **重新枚举的处理**:设备在热插拔后需要重新枚举,固件中应该正确处理复位事件和设置配置事件。 根据问题描述,热插拔后设备能够被识别,说明枚举过程基本成功,而且控制传输(如DTR)正常,说明控制端点是正常的。问题出在主机发送数据(即OUT传输)时。 在CDC ACM中,主机到设备的数据传输使用BULK OUT端点,设备到主机使用BULK IN端点。 因此,我们需要检查: 1. 在热插拔后,当主机发送数据时,设备是否收到了OUT端点的数据?如果没有,可能是主机没有发送,也可能是设备没有正确接收。 但是问题描述中,主机在发送数据时出现故障提示,所以更可能是主机端驱动在准备发送时遇到了问题。 然而,我们注意到设备端发送数据到主机是正常的,说明IN端点工作正常。 所以,我们可以将问题定位在OUT端点上。 可能的原因: - 热插拔后,主机驱动试图使用一个无效的端点句柄或管道。 - 设备在重新枚举后,OUT端点的状态没有被正确重置(比如NAK状态,导致主机无法发送)。 - 在设备重新连接后,主机驱动在打开串口时没有正确配置串口参数(如波特率、数据位等),但是描述中提到可以打开关闭打开串口,而且控制传输正常,所以这个可能性较小。 在设备固件中,我们需要确保: - 在USB复位事件中,重新初始化端点,特别是OUT端点,使其准备好接收数据(即置为有效状态,等待主机发送)。 - 检查端点描述符是否正确。 在cdc_acm_template.c中,通常会有以下复位处理: 在`USBD_CDC_ACM_Reset`函数中,应该重新配置端点,包括设置OUT端点为接收状态。 例如,在STM32的USB设备库中,复位回调函数中会重新打开端点: ```c static int8_t CDC_DeInit(void) { /* ... */ } static int8_t CDC_Reset(void) { /* Open EP IN */ USBD_LL_OpenEP(&hUsbDeviceFS, CDC_IN_EP, USBD_EP_TYPE_BULK, CDC_DATA_HS_MAX_PACKET_SIZE); /* Open EP OUT */ USBD_LL_OpenEP(&hUsbDeviceFS, CDC_OUT_EP, USBD_EP_TYPE_BULK, CDC_DATA_HS_MAX_PACKET_SIZE); /* ... */ } ``` 但是,请注意:在热插拔后,设备会经历一次复位,然后重新枚举。因此,确保复位函数中正确打开端点非常重要。 另外,检查一下在枚举完成后,主机在设置配置(SET_CONFIGURATION)后,设备是否准备好OUT端点。通常,在设置配置后,设备应该准备好OUT端点以接收数据。 在模板中,可能有`CDC_Setup`函数处理设置配置请求。在设置配置请求中,应该打开端点。 如果复位函数中已经打开了端点,那么设置配置中可能不需要再次打开。但具体要看实现。 另一种可能是,主机在热插拔后,尝试发送数据时使用了之前的管道(pipe)配置,而新枚举的设备使用了不同的配置(比如端点地址相同,但上下文已经改变),导致主机发送失败。 但是,根据CDC ACM规范,端点地址在重新枚举后应该是一样的(固件中定义不变),所以主机应该能够正确使用。 建议的调试步骤: 1. **检查复位回调**:确保在USB复位时,端点被正确关闭然后重新打开。在复位回调中,应该关闭所有非0端点(除了控制端点0),然后在后续的枚举过程中重新打开。有些实现是在设置配置时打开端点的。 2. **检查设置配置回调**:当主机发送设置配置请求(SetConfiguration)时,设备应该打开端点。 3. **检查主机端**:使用USB分析仪或软件(如WireShark+USBPcap)捕获USB数据包,观察热插拔后枚举过程是否正常,以及当主机发送数据时发生了什么错误(比如主机是否发送了OUT令牌包,设备是否响应NAK或其他)。 4. **设备端调试**:在设备端,检查当主机发送数据时,是否进入了OUT端点回调函数。如果没有,说明主机根本就没有发送数据,或者端点没有正确配置。 5. **检查端点最大包长度**:确保在描述符中定义的OUT端点最大包长度与主机期望的一致(一般是64字节)。如果描述符中定义的长度与主机驱动期望的不一致,可能会导致问题。 6. **主机驱动日志**:在主机端,查看设备管理器中串口设备的属性,确认无错误;同时可以查看系统日志,看是否有驱动程序错误。 由于问题描述中热插拔前正常,热插拔后出现问题,重点应放在设备在复位和重新枚举后的状态恢复上。 在cdc_acm_template.c中,通常有一个结构体用于管理CDC状态,比如: ```c typedef struct { uint8_t data[CDC_DATA_HS_MAX_PACKET_SIZE]; uint32_t len; uint8_t ep_in; uint8_t ep_out; uint8_t ctrl_line_state; } USBD_CDC_HandleTypeDef; ``` 在重新枚举后,这个结构体是否被正确初始化?特别是`len`和缓冲区,以及控制线状态。 在收到复位事件时,应该重置这个结构体。 另外,在打开OUT端点时,应该准备好接收数据,即提交一个OUT请求(对于某些USB库,需要调用函数来接收数据)。例如,在STM32的USB设备库中,通常在初始化OUT端点后立即调用`USBD_LL_PrepareReceive`。 例如: ```c USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->data, CDC_DATA_HS_MAX_PACKET_SIZE); ``` 在复位回调或设置配置完成后,应该提交这个请求。这样,当主机发送数据时,设备才能接收。 如果热插拔后没有提交OUT端点的接收请求,那么设备将不会响应主机的OUT事务(即不会提供缓冲区),主机就会认为设备没有准备好,进而导致传输失败。 所以,请检查在热插拔后(即复位和重新枚举后),设备是否重新提交了OUT端点的接收请求。 总结: 可能的原因是热插拔后,设备没有重新为OUT端点提交接收请求,导致主机发送数据时设备没有响应(NAK),主机驱动在多次尝试后认为设备故障,从而报告串口故障并尝试重新打开。 请检查设备固件中,在复位事件处理或设置配置事件处理中,是否调用了准备接收数据的函数(如`USBD_LL_PrepareReceive`)。 在cdc_acm_template.c中,查找`CDC_Reset`或`CDC_Init`函数,看是否有提交OUT端点的接收请求。 如果没有,则需要在枚举完成后(比如在设置配置完成后)提交。 在`CDC_Setup`函数中,处理设置配置请求(通常请求号为`USB_REQ_SET_CONFIGURATION`)时,可以提交OUT端点的接收请求。 或者,在复位处理中,除了打开端点,还需要提交接收请求吗?注意:复位后端点处于关闭状态,需要先打开端点,然后才能提交接收请求。但是复位处理中打开端点后,紧接着的枚举过程会设置配置,在设置配置后提交接收请求更为合理。 因此,建议在设置配置处理中提交OUT端点的接收请求。 示例: 在`CDC_Setup`函数中: ```c if (req->bRequest == USB_REQ_SET_CONFIGURATION) { // 打开端点(如果之前没打开) // 然后,准备接收 USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->data, CDC_DATA_HS_MAX_PACKET_SIZE); } ``` 或者,在`CDC_Init`函数中(如果有这个回调函数的话,它会在设置配置后被调用)进行接收请求的提交。 请根据具体的模板实现进行调整。 如果问题仍然存在,请检查端点描述符是否正确,以及端点地址是否一致。 希望这些分析能帮助解决问题。 根据您的描述,问题出现在热插拔后主机到设备(PC到MCU)的数据传输失败,而设备到主机(MCU到PC)的传输正常。结合 问题根本原因
解决方案1. 检查端点初始化代码在USB复位( 2. 验证控制信号处理确保 3. 端点描述符检查确认配置描述符中端点的方向和类型正确: 4. 主机端清理操作热插拔后执行以下步骤清除主机驱动状态:
调试建议
关键代码修正示例在 通过以上修正,热插拔后OUT端点将正确接收主机数据,解决单向通信问题。 |
|
|
|
|
只有小组成员才能发言,加入小组>>
184个成员聚集在这个小组
加入小组rtstudio是否可像keil加载ini解决虚拟串口与mcu串口通讯?
1212 浏览 0 评论
【Vision Board创客营连载体验】基于RA8D1-Vision Board的自动路径规划小车
1776 浏览 1 评论
【Vision Board创客营连载体验】基于Vision Board的垃圾分类
2156 浏览 0 评论
【Vision Board创客营连载体验】使用 Vision Board 做一个 UVC Camera
1777 浏览 0 评论
【Vision Board创客营连载体验】TinyMaix进行手写数字识别
2006 浏览 0 评论
1464浏览 5评论
在RT-Thread Studio中新建的stm32f407-atk-explorer工程运行qemu失败,是什么原因引起的?
1766浏览 3评论
为什么rt_device_read()只能读取到两个字节数据?
363浏览 3评论
连得上热点,但是ping baidu.com出现timeout,请问跟什么有关?
421浏览 3评论
420浏览 2评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-1 22:17 , Processed in 0.768650 second(s), Total 74, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
7121
