你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

不知是否是HAL库USB模块的bug,记录一下

[复制链接]
buyadong 提问时间:2017-11-5 05:22 /
    在使用HAL库的USB模块时,使用了自定义的USB设备,发现了一个问题,    库版本为1.1.1,
    芯片为STM32F103T8
    USB类型:自定义USB FS Device
    问题现象:
           当设置要接收的数据长度为大于64字节时,无法从接收结束回调函数(USBD_xxx_DataOut)中获取已接收数据的字节数。
    原因分析:
            当使用语句:
                USBD_LL_PrepareReceive(pdev,
                             MY_EPOUT_ADDR,
                             hmyusb->RxBuffer,
                             300);
             配置要接收的字节数为300,此时ep.xfer_len = 300-64=236 ,HAL库本身对设置高于max_packet的包可以进行组包,这个可以从USB的中断函数处理中看出来。
  1. <font color="#ff0000">/*multi-packet on the NON control OUT endpoint*/</font>
  2.         ep->xfer_count+=count;
  3.         ep->xfer_buff+=count;
  4.       
  5. <font color="#ff0000">        if ((ep->xfer_len == 0U) || (count < ep->maxpacket))</font>
  6.         {
  7.       /* RX COMPLETE */
  8.      HAL_PCD_DataOutStageCallback(hpcd, ep->num);
  9.         }
  10.         else
  11.         {
  12.      <font color="#ff0000">HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);</font>
  13.         }
复制代码
          说明两个方面:1、HAL包调用接收结束的回调函数的条件为:接收完预设的数据长度 或者 接收到小于max_packet长度的包。
           当接收到第一个64字节后,因为还不满要求接收的长度,因此HAL库调用了HAL_PCD_EP_Receive进行再接收数据包。问题出在HAL_PCD_EP_Receive函数中,对ep->xfer_count 清0了。
  1. HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  2. {
  3.   PCD_EPTypeDef *ep = NULL;
  4.   
  5.   ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
  6.   
  7.   /*setup and start the Xfer */
  8.   ep->xfer_buff = pBuf;  
  9.   ep->xfer_len = len;
  10. <font color="#ff0000">  ep->xfer_count = 0U;</font>
  11.   ep->is_in = 0U;
  12.   ep->num = ep_addr & 0x7FU;

  13.   if ((ep_addr & 0x7FU) == 0U)
  14.   {
  15.      USB_EP0StartXfer(hpcd->Instance , ep);
  16.   }
  17.   else
  18.   {
  19.       USB_EPStartXfer(hpcd->Instance , ep);
  20.   }

  21.   return HAL_OK;
  22. }
复制代码
              而在cube的USB例程中,在接收结束回调函数中,均是调用 USBD_LL_GetRxDataSize (pdev, epnum)函数来获取接收到的数据长度,
  1. uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
  2. {
  3.       return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*)pdev->pData, ep_addr);
  4. }
复制代码

  1. uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  2. {
  3.      return <font color="#ff0000">hpcd->OUT_ep[ep_addr & 0xF].xfer_count;</font>
  4. }
复制代码
            可以看出,实际上就是直接返回的xfer_count。 也就是说,我设置了接收300个,但实际上主机只发了100个过来,那么会导致调用USBD_LL_GetRxDataSize函数判断接收到的长度只有 36个(主要是因为HAL库在设置连续接收时,对xfer_count进行了清0)。
      暂时解决方案:
             拷贝了一个HAL_PCD_EP_Receive函数改名成HAL_PCD_EP_ReceiveContinue,在里面把xfer_count = 0删除。并把USB中断中当需要继续接收时的设置函数改成HAL_PCD_EP_ReceiveContinue。

  1. HAL_StatusTypeDef HAL_PCD_EP_ReceiveContinue(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  2. {
  3.   PCD_EPTypeDef *ep = NULL;
  4.   
  5.   ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
  6.   
  7.   /*setup and start the Xfer */
  8.   ep->xfer_buff = pBuf;  
  9.   ep->xfer_len = len;
  10.   ep->is_in = 0U;
  11.   ep->num = ep_addr & 0x7FU;

  12.   if ((ep_addr & 0x7FU) == 0U)
  13.   {
  14.      USB_EP0StartXfer(hpcd->Instance , ep);
  15.   }
  16.   else
  17.   {
  18.         USB_EPStartXfer(hpcd->Instance , ep);
  19.   }

  20.   return HAL_OK;
  21. }
复制代码
            
  1. /*multi-packet on the NON control OUT endpoint*/
  2.         ep->xfer_count+=count;
  3.         ep->xfer_buff+=count;
  4.       
  5.         if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
  6.         {
  7.     /* RX COMPLETE */
  8.     HAL_PCD_DataOutStageCallback(hpcd, ep->num);
  9.         }
  10.         else
  11.         {
  12.       HAL_PCD_EP_ReceiveContinue(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
  13.         }
复制代码






收藏 1 评论2 发布时间:2017-11-5 05:22

举报

2个回答
shuihehe 回答时间:2019-6-13 09:48:06
这个你调试了么,能保证收到字节数是累加的么?
makeWorks 回答时间:2020-7-31 16:14:13
接收的数据个数是maxpacket的整数倍时会出错,收不到zero-length包,所以不会结束,囧

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版