RT-Thread论坛
直播中

麻酱

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

YModem下载文件到U盘失败,文件0字节,是哪里的问题?

MCU芯片STM32f407vet6,系统为RTThread最新版本,片外spi flash采用elm文件系统,USB栈为系统带的CherryUSB。
现在有两个问题:
1)采用CherryUSB栈,能够正常探测较新的U盘,访问正常(从spi到U盘cp正常,反之也正常,rm正常)较旧的U盘不能访问,报错

  • [E/usbh_msc] csw transfer error
  • [E/usbh_msc] msc data transfer error
  • [E/usbh_msc] Fail to scsi_testunitready
  • [E/usbh_hub] Port 1 enumerate failed.


2)通过Ymodem往U盘下载文件失败,(正常结束,U盘文件长度0字节,然后访问U盘报错

  • [E/usbh_msc] cbw transfer error usb mass_storage write failed),


通过Ymodem从U盘上传文件失败,无法正常启动。采用老的USB协议栈Ymodem操作是正常实现的。
调试很久没有头绪,请各位多多帮忙。


回帖(1)

张燕

2025-10-20 17:06:45

针对您描述的YModem下载文件到U盘失败及U盘兼容性问题,以下是详细分析和解决方案:


问题1:旧U盘无法识别(枚举失败)


错误日志关键信息:


[E/usbh_msc] csw transfer error
[E/usbh_msc] msc data transfer error
[E/usbh_msc] Fail to scsi_testunitready
[E/usbh_hub] Port 1 enumerate failed

根本原因分析:



  1. USB协议兼容性问题

    旧U盘可能使用USB 1.1协议或非标准的SCSI指令集,而CherryUSB默认配置可能未完全兼容。

  2. 供电不足

    旧U盘功耗较高(如>100mA),STM32F4的USB端口供电能力有限(标准为500mA,但设计不足时易触发问题)。

  3. 枚举阶段超时

    旧设备响应速度慢,默认USB枚举超时时间不足。

  4. 描述符处理异常

    旧U盘的设备描述符、配置描述符或SCSI指令格式与CherryUSB栈预期不符。


解决方案:



  1. 增加USB枚举重试机制

    usbh_core.c中修改枚举逻辑,增加重试次数:
    // 找到枚举失败的位置(如usbh_enumerate函数)
    for (uint8_t retry = 0; retry < 3; retry++) {  // 增加重试至3次
       if (usbh_parse_cfgdesc(&hub->dev) == 0) {
           break; // 成功则退出
       }
       rt_thread_mdelay(50); // 每次重试间隔50ms
    }

  2. 调整USB主机控制器参数

    usbh_conf.h中增加以下配置:
    #define CONFIG_USBHOST_REQUEST_TIMEOUT 5000 // 将超时时间从默认500ms改为5000ms
    #define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 3000

  3. 增强供电稳定性  

    • 硬件:在USB_VBUS线路增加470μF电容缓冲,并确认电源芯片能提供≥500mA电流。

    • 软件:在初始化代码中使能USB电源过流保护(如有设计):
      __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
      HAL_PWREx_EnableUSBVoltageDetector();


  4. 扩展MSC类兼容性

    usbh_msc.c中修改SCSI指令处理逻辑:
    // 在msc_scsi_testunitready函数中增加旧设备支持
    if (retry_count < 2) {
       msc->bot_state = USBMSC_BS_SEND_CBW;
       return 0; // 忽略首次失败
    }




问题2:YModem下载文件失败(0字节 + 后续U盘访问错误)


错误日志关键信息:


文件0字节 -> [E/usbh_msc] cbw transfer error

根本原因分析:



  1. 文件系统与USB传输冲突

    YModem持续写入时,文件系统(elmfat)与USB MSC传输竞争SPI Flash资源,导致USB响应超时。

  2. USB批量传输超时

    大文件传输时U盘响应延迟,CherryUSB默认超时设置不足。

  3. 缓存区不足

    YModem接收缓冲区与USB MSC缓冲区共用,导致数据覆盖。

  4. 未正确处理USB断开

    传输失败后USB状态机未正确复位,导致后续操作失败。


解决方案:



  1. 优化文件写入流程

    在YModem接收线程中分块写入并加入流量控制:
    // 在YModem接收回调函数中
    while (received_size > 0) {
       int write_size = MIN(received_size, 512); // 每次写512字节
       if (dfs_file_write(file, buffer, write_size) < 0) {
           // 错误处理
           break;
       }
       received_size -= write_size;
       buffer += write_size;
       rt_thread_mdelay(5); // 每次写入后释放CPU
    }

  2. 增大USB传输缓冲区

    usbh_core.h中调整:
    #define CONFIG_USBHOST_RX_BUFSIZE  (4 * 1024) // 默认1KB改为4KB
    #define CONFIG_USBHOST_TX_BUFSIZE  (4 * 1024)

  3. 复位USB端口状态机

    在传输失败后强制复位USB端口:
    // 在YModem传输失败的回调中
    usbh_reset_port(port_num); // 重置对应USB端口
    usbh_msc_storage_reset();  // 重置MSC类状态

  4. 添加U盘写入延迟

    在文件关闭前同步文件系统:
    dfs_file_flush(file); // 确保数据写入物理设备
    rt_thread_mdelay(100); // 等待100ms
    dfs_file_close(file);




综合改进建议




  1. 硬件检查:



    • 测量USB_VBUS电压(需稳定在5.0V±0.25V)

    • 检查DM/DP线是否串联22Ω阻抗匹配电阻

    • 确认U盘插入时VBUS电流(使用万用表串联测试)




  2. 软件升级:



    • 更新CherryUSB到GitHub最新版本(修复旧commit中的MSC类bug)

    • 使用RTT Studio配置USB主机参数(可视化调整超时/缓冲区)




  3. 测试用例:


    # 在Finsh中执行压力测试
    msh />cp /spi/file.bin /udisk/ # SPI->U盘复制
    msh />cp /udisk/file.bin /spi/ # U盘->SPI复制
    msh />md5sum /spi/file.bin /udisk/file.bin # 校验一致性



  4. 备用方案:
    若仍存在问题,可切换USB协议栈:


    RT-Thread Online Packages → USB → [ ] CherryUSB → [*] RT-Thread USB Host Stack




关键调整总结:  



  • 增加USB枚举超时和重试 → 解决旧U盘识别  

  • 分块写入+写入延迟 → 避免文件0字节  

  • 传输失败后复位USB端口 → 恢复后续访问  

  • 增大USB缓冲区 → 提升大数据传输稳定性



通过上述步骤应能解决U盘兼容性和YModem传输问题。建议先从软件修改开始测试,若旧U盘仍无法识别再检查硬件供电设计。

举报

更多回帖

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