经过查看,是因为USBHOST频繁的进入中断导致,单步执行发现,是因为发生了USB_OTG_HCINT_CHH或者USB_OTG_HCINT_NAK中断了,只在CHH中断服务函数里,给USB主线程发了1个消息,又引起了USBH_Process_OS主线程的频繁运行,最终导致整个H743的资源都用在了USB上面,连个printf()打印调试信息都卡。
else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
{
__HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
}
else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
{
if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
{
hhcd->hc[ch_num].ErrCnt = 0U;
__HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
(void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
}
else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
(hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
{
hhcd->hc[ch_num].ErrCnt = 0U;
#if 0
if (hhcd->Init.dma_enable == 0U)
{
hhcd->hc[ch_num].state = HC_NAK;
__HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
(void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
}
#else //###### Fri May 26 16:56:16 CST 2023
/* re-activate the channel */
hhcd->hc[ch_num].state = HC_NAK;
tmpreg = USBx_HC(chnum)->HCCHAR;
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
tmpreg |= USB_OTG_HCCHAR_CHENA;
USBx_HC(chnum)->HCCHAR = tmpreg;
#endif
}
__HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
}
解决过程如下:
这段程序我之间用在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,修改如上面代码,问题解决。