usbhost驱动相关疑问与调试记录

发布者:星尘之泪最新更新时间:2024-01-08 来源: elecfans关键字:usbhost  驱动  调试记录 手机看文章 扫描二维码
随时随地手机看文章

前言

rtt 里的 usbhost 驱动有问题这是众所周知的事情了,很多人在论坛上提问,也出现了各种解决方案。这里做个汇总,同时把我最终的解决方法说一下。


平台环境:STM32F429 正点原子阿波罗



usbhost 驱动相关疑问

第一个疑问

https://club.rt-thread.org/ask/question/430499.html


关于这里的延时,好像 stm32 官方的某个手册或者 usb 规范里有讲,因为这里 https://bbs.21ic.com/icview-106567-1-1.html 也提到了这个 1ms 延时是必需的。


我曾经去掉过这个延时,去掉是有严重问题的。识别不出 U盘还是小事儿,还可能严重的搞坏系统,这一点儿下面细讲。


第二个疑问

https://club.rt-thread.org/ask/question/425072.html


出现死循环的原因只有一个,usb 控制器出现 nak 并且自己不可恢复。原驱动中相关代码如下:


if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == HC_NAK)

{

   RT_DEBUG_LOG(RT_DEBUG_USB, ("nakn"));

   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;

}

即便这里有初始化操作,但是实际上并不能恢复,也不能 continue 实现重新提交请求。


其它疑问

不识别,枚举设备失败,无法挂载。。。

其它各种问题都和 drv_usbh.c 的 `drv_pipe_xfer` 函数有千丝万缕的联系。


调试记录

删 `drv_pipe_xfer` 中的延时

这个延时应该是硬件的硬性要求,去掉它会很容易 nak,然后进入上面的死循环里面。我去掉了延时,所以在 nak 死循环了。接下来去掉 nak 的死循环。


修改一个 bug

原代码是这么写的 `else if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == URB_ERROR)` ,`HAL_HCD_HC_GetState` 返回值是 `HCD_HCStateTypeDef` 类型,而 `URB_ERROR` 是 `HCD_URBStateTypeDef` 类型的,明显调用的函数和比较值类型不一样。

修改后 `else if (HAL_HCD_HC_GetURBState(&stm32_hhcd_fs, pipe->pipe_index) == URB_ERROR)`。


重写任何可能引起**死循环**的代码

死循环可不是什么好东西,如果有这个可能,就必须改掉它,比如通过计数,重试有限次之后退出尝试。


nak retry

把 `continue` 改成重试 10 ,感觉把错误转移了,也没见有多少改善。


nak 退出

去掉 `continue` ,去掉 retry,直接返回错误退出 `drv_pipe_xfer` 函数。那么,问题来了。


首先说明,`drv_pipe_xfer` 函数被 `rt_usb_hcd_setup_xfer` 和 `rt_usb_hcd_pipe_xfer` 两个函数直接调用,然后被其它几十个函数间接调用。

`drv_pipe_xfer` 函数的第三个参数 `void *buffer`,用于传递输入输出数据缓存地址指针。输出数据过程没有多大问题,当它扮演接收数据缓存时就存在潜在的隐患。


因为接收数据的内存缓存多半不是全局的,而是临时申请的内存,或者是从栈上分配的。假如 `drv_pipe_xfer` 函数“假”失败返回,而 stm32 的 usb 控制器还在工作。比如上面的 nak,当我直接错误返回退出 `drv_pipe_xfer` 函数后,开始发现各种内存异常修改。比如返回上层调用函数的过程中发现局部变量(栈)莫名变成其它随机值。从这里我猜测虽然是 nak,但是并不一定表示有什么严重的问题。既然 usb 控制器仍然使用传递给他的寄存器地址,如果再稍微等待一下是不是变成完成状态了?


nak 超时

处理 HC 状态和 URB 状态前先判断是否是 nak,如果是 nak 就等待,等待 timeout 个 tick 超时,然后交给下面处理;不是 nak, ok 的可能性很大,直接交给下面处理。


       tick = rt_tick_get();

       while(HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == HC_NAK)

       {

           if ((rt_tick_get() - tick) >= timeout)

           {

               break;

           }

           else

           {

               rt_thread_yield();

           }

       }

这么处理以后,nak 少多了,但是还是有,而且一经出现就很难再继续。


阶段小结

修改了状态比较的错误,添加上 `drv_pipe_xfer` 中的 1ms 延时,同时添加了 nak 状态等待。去掉任何死循环操作,如果 nak 等待超时后还是 nak 就错误退出。到此,U 盘失败和 sd 卡识别已经有明显的改观了,大多时候可以走到 df_mount 之前(修改前走到 rt_udisk_run 就很难,rt_udisk_run 和 df_mount 中间有几个地方都可能出错终止)。


下面继续 debug。


上层操作 retry

`drv_pipe_xfer` 里 retry 的操作尝试过了,经过测试才知道,底层的工作原理不允许这么暴力 retry,这样可能引起 usb 控制器工作异常。

换个思路 retry,把 retry 往上层移动,找最容易出错误的函数调用路径中的某个接口,比如 `rt_usbh_storage_read10` 或 `rt_usbh_storage_write10` ,读操作最多返回错误,应用层操作失败。写操作失败意味着可能写 U 盘的任意节点出现问题了,这个时候放任不管可能会丢失数据的。

于是 `rt_usb_bulk_only_xfer(intf, &cmd, buffer, timeout);` 返回值不是 OK 就重试。这种尝试好像有效果,但是还是有多次重试后失败的。


继续查找原因

最底层的和比较上层的部分都使用各种方法尝试过了,问题还是存在。而且,让人头疼的是出现问题后 U 盘的文件系统有被损坏的概率。经过多次格式化 U 盘后发现也只有 `rt_usbh_storage_write10` -> `rt_usb_bulk_only_xfer` 出错概率最大,写坏 U 盘的操作也出现在这里。

那么,进入 `rt_usb_bulk_only_xfer` 函数寻找机会。


rt_usb_bulk_only_xfer

这个函数大概率出错,肯定有它自己的独特的操作。 `rt_usbh_storage_read10` 也调用了这个函数但是不出错,由此,我把可疑范围缩小到


   if(cmd->xfer_len != 0)

   {

       ...

       size = rt_usb_hcd_pipe_xfer(pipe->inst->hcd, pipe, (void*)buffer,

           cmd->xfer_len, timeout);

       ...

   }

`cmd->xfer_len` 比较大的时候,也就是说读写数据量大的时候,`rt_usb_hcd_pipe_xfer` 函数执行就容易出错。


为什么呢?数据量多少直接影响了出错概率。其它地方调用 `drv_pipe_xfer` 能正常工作,这里出错,能说明硬件配置有问题吗?


`rt_usb_hcd_pipe_xfer` 里面把大数据分包,分成 64 字节的小包一次次发送,这个包能改大一点儿吗?发大包会有影响吗?


多处判断包大小和 wMaxPacketSize 的关系, wMaxPacketSize 能修改大一点吗?


加延时,还是 retry ?哪种解决方法更高效?


最终方案

调用 `rt_usb_hcd_pipe_xfer` 之前加个短延时,比如 3ms 的延时。因为其它方法都尝试过,暂时没找到能解决问题的。

如果对延时引起的性能降低比较在意,先判断发送的包大小有多大,如果一包处理不完,延时一下;如果一包就可以处理完不需要延时。

读和写延时也不一样,写操作要求延时时间长,读操作可能不延时也没问题。

当这里加延时后,手头的 U 盘和读卡器识别和读写文件都正常了。

因为这里的延时是经验值,有的需要延时时间短,有的需要延时时间长。不确定延时多少怎么办?可以如下动态调整延时时间。


   ...

   if(cmd->xfer_len > pipe->ep.wMaxPacketSize)

   {

       rt_thread_mdelay(wr_delay);

   }

   size = rt_usb_hcd_pipe_xfer(pipe->inst->hcd, pipe, (void*)buffer,

       cmd->xfer_len, timeout);

   if(size != cmd->xfer_len)

   {

       if (wr_delay < 5)

       {

           wr_delay += 2;

       }

       ...

   }

其它

不知道这个算不算问题,无论从理论上还是实际应用中,读写 U 盘的时候是禁止拔掉 U 盘的。

不说写 U 盘,假设读 U 盘的时候拔掉 U 盘,原驱动有一定的机率在读操作过程中清理掉了对应通道的设备。因为,监测 usb 端口在一个独立线程,然后读写接口被文件系统调用,肯定是另外的应用层线程操作的了。两个不同的线程,一个使用 usb 通道时,另一个清理掉了它!

所以,在 `rt_usbh_hub_port_change` `rt_udisk_read` `rt_udisk_write` 等接口出添加互斥操作避免上述情况出现。这个对读写都是有效的。


> 本文所有提到的更改已经提交到 gitee ,欢迎大家测试 https://gitee.com/thewon/rt_thread_repo


关键字:usbhost  驱动  调试记录 引用地址:usbhost驱动相关疑问与调试记录

上一篇:CANOpen系列教程06_ 结合代码理解CAN底层收发数据
下一篇:STM32的中断及是如何使用

推荐阅读最新更新时间:2024-11-01 22:15

针对IGBT和MOSFET可再生能源应用的驱动器设计
引言 对电能转换而言,可再生 能源 电子细分市场是一个复杂且多样化的竞技场。在一些负载点应用中,开关型功率转换器通常为非隔离式,功率水平相当低( 200 W),并且常常会把电源从一个DC电压转换到另一个,例如:12V转换为3.3V。另外,功率级开关为集成式,也即能够通过低电流控制器或者晶体管驱动。今天,控制器和功率级之间的整合正在成为现实。硅(Si)MOSFET在这一市场中起主导作用,因为人们喜欢更高的开关频率,它可以达到1MHz以上的速度。这些功率开关通常均由一个5V或者12V IC栅极 驱动器 或类似解决方案来驱动。 高效管理可再生能源系统的挑战 在某个风或者光伏发电机的电力系统中,存在一些特殊的性能问题。使用微型逆变
[电源管理]
针对IGBT和MOSFET可再生能源应用的<font color='red'>驱动</font>器设计
高亮度LED照明的驱动电路
  高亮度LED 在照明应用中的使用越来越广泛。在这里将介绍一种简单的“气氛照明灯”,其仅使用了少量的组件。所有这三种LED 均由使用开关调节器的恒定电流来供电,同时亮度控制由能够产生三种 PWM 信号的 MSP430 微控制器来完成。可以用磨砂玻璃外壳将印刷电路板安装到台灯中,或者也可以和 LED 聚光灯一起使用来进行间接照明。   无论其功耗有多大,现在的 LED 通常都使用一个恒定电流源来驱动。这是因为以流明 为单位的光输出量和电流量成正比例 关系。因此,所有的 LED 厂商都规定了诸如光输出、可视角度和波长等参数,作为正向电流 IF 的函数,而非像人们所期望的那样作为正向电压 VF 的函数。所以,我们在电路中使用了适当的恒
[电源管理]
高亮度LED照明的<font color='red'>驱动</font>电路
智能家居将驱动物联网设备达到500亿个
Strategy Analytics的最新研究报告指出,物联网继续快速扩张,智能家居将在2020年成为物联网进一步发展的关键。 报告《互联世界:智能家居是未来物联网成长的关键》指出,截至今年年底,近200亿个物联网和联网设备将在全球被部署,未来四年将会再增加100亿。 企业近年来一直是物联网使用的关键市场,但长期预测表明,2020年代智能家居将可能成为联网和物联网设备部署增长的主要驱动力,连接数将会达到500亿。 该报告的关键研究发现包括: 作为部署的联网/ IoT设备份额的一部分,智能家居设备将在2021年超过智能手机 2017年物联网将增长17%,但2021年,年增长率将下降至9% 企业物联网目前占总联网
[物联网]
智能家居将<font color='red'>驱动</font>物联网设备达到500亿个
可穿戴设备要靠价格驱动还是功能驱动
小米正式售价仅为79元的小米手环,支持计步、睡眠监测等等一系列主流手环所具备的功能,可以说是一款诚意之作。业界评论称雷军将一款千元级的产品定价瞬间降至百元以内。“雷军一招就把所有智能手环玩家吓跑了,”有人在新浪微博上如此吐槽。 当然,小米的智能手环并没有显示屏,应该属于最简单的产品,作为一个基础参考价格,别人做得更好,价格当然可以往高了定。 不过,有人愁就有人欢喜。例如,ADI和TI这两家半导体公司。之前小米的移动电源采用了TI的电源管理IC,这款智能手环用了ADI的加速度传感器,由于这两款产品的定价都只有区区几十元,供不应求的概率会很高。雷军在发布会上就表示,拥有30天续航并达到IP67防尘防水的小米手环会成为全
[物联网]
12/24V 恒流升压LED驱动电源解决方案
产品特点: 1、性能高度稳定可靠,产品在模拟恶劣环境下长时间老化,没有出现任何负面影响; 2、产品品种规格齐全,可普遍适用于太阳能照明用LED灯具; 3、具有短路、电流温度补偿功能,可在-20~+60℃下工作; 4、设计采用稳定PWM控制芯片技术,减少光衰; 5、低发热,稳定可靠,产品使用优质元器件确保电源寿命更长,更安全可靠; 产品概述
[电源管理]
12/24V 恒流升压LED<font color='red'>驱动</font>电源解决方案
低成本LED驱动IC促进了照明领域的革新
当今,商用LED的发光效率正接近荧光灯70~80lm/W的效率。荧光光源是非常成熟的技术,未来很可能会有一些改进,而LED的发光效率(lm/W)每10年就以20倍的速度增加,并且这种趋势还会继续。 LED照明光源已经开始渗透到像户外广告、建筑照明、交通信号以及汽车内部灯光、仪表盘、尾灯和前照灯等这样的照明市场。虽然还处于起步阶段,但根据最近的DOE报告,在2002年并网的LED照明设备将会节省8.3TW/h:“……超过一个大型发电站的输出功率。” 建筑照明节能的潜力是巨大的。在建筑中,照明是最终使用的第二大能源,占全美国所有电能的22%,估计每年将达到8.2×1015 BTU。 目前,相对过高的LED照明光源初始安装
[电源管理]
低成本LED<font color='red'>驱动</font>IC促进了照明领域的革新
stm32驱动液晶(ILI9320) 源自正点原子
FSMC笔记: STM32 的 FSMC 存储块 1( Bank1)被分为 4 个区,每个区管理 64M 字节空间,每个区都有独立的寄存器对所连接的存储器进行配置。 Bank1 的 256M 字节空间由 28 根地址线( HADDR )寻址。这里 HADDR 是内部 AHB 地址 总线,其 中 HADDR 来自外部存储器地 址FSMC_A ,而 HADDR 对 4 个区进行寻址 。 当 Bank1 接的是 16 位宽度存储器的时候: HADDR 指向 FSMC 。因此HADDR需要左移一位,才能使 HADDR 指向 FSMC 。因为HADDR增加或者减少是从最低位开始的, HADDR 指向 FSMC ,所以HADDR 指向
[单片机]
stm32<font color='red'>驱动</font>液晶(ILI9320) 源自正点原子
开发可统计单词个数的Android驱动程序(1)
Android本质上是基于Linux内核的系统,也就是说Android就是一种Linux操作系统。只不过大多数时候都会运行在ARM架构的设备上,例如,Android手机、平板等。Android驱动实际上就是Linux驱动,只是这里使用 Android深度探索(卷1):安装C/C++交叉编译环境 介 绍的交叉编译器将Linux驱动编译成了ARM架构的,所以驱动可以安装在Android模拟器、Android手机(需要root)或平板上(这些设备 都要使用给予ARM架构的CPU),当然,使用传统的GCC也可以编译成X86架构的驱动(并不需要修改代码),这样也可以在Ubuntu Linux上安装Linux驱动。 本文及后面几篇文
[单片机]
开发可统计单词个数的Android<font color='red'>驱动</font>程序(1)
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved