• H743 USBHOST协议栈 CPU占用率高的问题。


    经过查看,是因为USBHOST频繁的进入中断导致,单步执行发现,是因为发生了USB_OTG_HCINT_CHH或者USB_OTG_HCINT_NAK中断了,只在CHH中断服务函数里,给USB主线程发了1个消息,又引起了USBH_Process_OS主线程的频繁运行,最终导致整个H743的资源都用在了USB上面,连个printf()打印调试信息都卡。

    1.   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
    2.   {
    3.     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
    4.     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
    5.   }
    6.   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
    7.   {
    8.     if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
    9.     {
    10.       hhcd->hc[ch_num].ErrCnt = 0U;
    11.       __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
    12.       (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
    13.     }
    14.     else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
    15.              (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
    16.     {
    17.       hhcd->hc[ch_num].ErrCnt = 0U;
    18. #if 0
    19.       if (hhcd->Init.dma_enable == 0U)
    20.       {
    21.         hhcd->hc[ch_num].state = HC_NAK;
    22.         __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
    23.         (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
    24.       }
    25. #else       //###### Fri May 26 16:56:16 CST 2023
    26.             /* re-activate the channel */
    27.       hhcd->hc[ch_num].state = HC_NAK;
    28.       tmpreg = USBx_HC(chnum)->HCCHAR;
    29.       tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
    30.       tmpreg |= USB_OTG_HCCHAR_CHENA;
    31.       USBx_HC(chnum)->HCCHAR = tmpreg;
    32. #endif
    33.     }
    34.     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
    35.   }

    解决过程如下:

          这段程序我之间用在F437上,是没有问题的,为了对比起见,专门把F437的相应程序运行起来,确实没有这种情况,经过对比,我发现F437的USB并没有频繁的进入USB_OTG_HCINT_CHH导致的中断,2个工程对应的驱动与上层应用是一样的,唯一不一样的是USB协议栈,一个是F437的USB协议栈,比较老,20年左右的, 而现在用的H743的USB协议栈是最新的。我对比了一下,确实存在不同,由于USB协议栈没有版本记录,所以不能简单的从USB协议栈版本加以区分,但对比程序源码,除了协议栈结构相似外,内容细节还是有很大不同的。于是就慢慢的分析,

    发现只要我一启动接收就会出来卡顿的情况

        USBH_CDC_Receive(modem->phost, modem->bulk_in_buf, MODEM_RX_BUFSIZE);   //启动接收

    说明就是这里引起的,由于这是一个4G模块 驱动 , 4G模块在正常识别后,就会启动接收数据,这种设备不像U盘,发送与接收的字节数都是应用确实好的,发送与接收数据的时刻也是上层应用确定的,这种设备由于接收数据的不确定性,所以上电会就要马上启动接收线程,这本身是没问题的,但是F437也是这种的驱动结构,F437就没有问题,思来想去,还是USB协议栈的问题,

        为什么会进USB_OTG_HCINT_CHH中断呢,官方文档说有2种可能,1是USB事务错误,1是应用关闭USB导致

    我启动USBH_CDC_Receive()接收后,但是4G模块这时没有数据,就会改善NAK包,NAK包也会产生USB_OTG_HCINT_NAK中断,这在F437中也验证了,进入NAK中断是正常的,经过对比2个USB协议栈对NAK的处理,发现点猫腻,就是我上面列出的程序时处理的那样

    F437是如果端点是ctrl 或者bulk的话,重新启动re-activate the channel USB,但是H743确实直接关闭USB通道,我

    猜测正是这个操作,刚好符合”2应用关闭USB导致CHH“,所以后面紧接着就产生了CHH中断,从而造成了系统循环在USB中断中运行,最终导致USB占用CPU奇高的问题,

          解决方法,按F437的方法修改H743的USB协议栈,其实也是不是协议栈,是stm32h7xx_hal_hcd.c,修改如上面代码,问题解决。

  • 相关阅读:
    Java课设设计-酒店管理系统
    略微扒一扒HashMap的源码
    如何将home目录空间扩充到根目录下
    【RocketMQ】RocketMQ 5.0新特性(三)- Controller模式
    【笔者感悟】笔者的工作感悟【二】
    Docker 常用命令使用
    【注释和反射】类加载的过程
    3D人脸关键点和重构调研
    【Pytorch】第 1 章 :强化学习和 PyTorch 入门
    【Linux学习笔记2】-【Linux目录结构及具体介绍,vi和vim的介绍及快捷方式,】
  • 原文地址:https://blog.csdn.net/wandersky0822/article/details/130905323