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

不知是否是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管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版