打印
[STM32F4]

USB Device 传输问题

[复制链接]
13566|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
syptt100|  楼主 | 2018-8-8 12:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我使用STM32CubeMx生成了Custom Hid的工程,三个端点,0,81,01.配置好后,设备的枚举正常。
我用上位机,向01发送数据,上位机返回成功。mcu也收到了,mcu设置的buffer里有传来的数据。
但是有一个问题,按理说我应该收到一个回调函数,在数据接受完后调用到我自己的程序。而我始终得不到这个回调。
USB的中断函数如下(有点长,抱歉),我理解接受完后,会调用HAL_PCD_DataOutStageCallback回调,在测试中,发现始终调用不到。
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
{
  USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
  uint32_t i = 0U, ep_intr = 0U, epint = 0U, epnum = 0U;
  uint32_t fifoemptymsk = 0U, temp = 0U;
  USB_OTG_EPTypeDef *ep;
  uint32_t hclk = 180000000U;
  
  /* ensure that we are in device mode */
  if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
  {   
    /* avoid spurious interrupt */
    if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
    {
      return;
    }
   
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
    {
     /* incorrect mode, acknowledge the interrupt */
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
    }
   
        printf("before \r\n");
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
    {
      epnum = 0U;
      printf("after \r\n");
      /* Read in the device interrupt bits */
      ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
      printf("outep ep_intr = %x \r\n",ep_intr);
      while ( ep_intr )
      {
                  
        if (ep_intr & 0x1U)
        {
                        printf("num = %d\r\n",epnum);
          epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum);
         
          if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
          {
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
            
            if(hpcd->Init.dma_enable == 1U)
            {
              hpcd->OUT_ep[epnum].xfer_count = hpcd->OUT_ep[epnum].maxpacket- (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);
              hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket;            
            }
            
            HAL_PCD_DataOutStageCallback(hpcd, epnum);
            if(hpcd->Init.dma_enable == 1U)
            {
              if((epnum == 0U) && (hpcd->OUT_ep[epnum].xfer_len == 0U))
              {
                 /* this is ZLP, so prepare EP0 for next setup */
                USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
              }              
            }
          }
         
          if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
          {
            /* Inform the upper layer that a setup packet is available */
            HAL_PCD_SetupStageCallback(hpcd);
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
          }
         
          if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
          {
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
          }

#ifdef USB_OTG_DOEPINT_OTEPSPR
          /* Clear Status Phase Received interrupt */
          if(( epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
          {
            CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
          }
#endif /* USB_OTG_DOEPINT_OTEPSPR */
        }
        epnum++;
        ep_intr >>= 1U;
      }
    }
   
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
    {
                printf("USB_OTG_GINTSTS_IEPINT \r\n");
      /* Read in the device interrupt bits */
      ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
      
      epnum = 0U;
      
      while ( ep_intr )
      {
                  printf("epnum = %d\r\n",epnum);
        if (ep_intr & 0x1U) /* In ITR */
        {
          epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum);

           if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
          {
            fifoemptymsk = 0x1U << epnum;
            USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
            
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
            
            if (hpcd->Init.dma_enable == 1U)
            {
              hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
            }
                                      
            HAL_PCD_DataInStageCallback(hpcd, epnum);

            if (hpcd->Init.dma_enable == 1U)
            {
              /* this is ZLP, so prepare EP0 for next setup */
              if((epnum == 0U) && (hpcd->IN_ep[epnum].xfer_len == 0U))
              {
                /* prepare to rx more setup packets */
                USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
              }
            }           
          }
           if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
          {
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
          }
          if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
          {
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
          }
          if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
          {
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
          }
          if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
          {
            CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
          }      
          if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
          {
            PCD_WriteEmptyTxFifo(hpcd , epnum);
          }
        }
        epnum++;
        ep_intr >>= 1U;
      }
    }
   
    /* Handle Resume Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
    {   
                printf("USB_OTG_GINTSTS_WKUINT \r\n");
      /* Clear the Remote Wake-up Signaling */
      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;

#ifdef USB_OTG_GLPMCFG_LPMEN
      if(hpcd->LPM_State == LPM_L1)
      {
        hpcd->LPM_State = LPM_L0;
        HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
      }
      else
#endif /* USB_OTG_GLPMCFG_LPMEN */
      {
        HAL_PCD_ResumeCallback(hpcd);
      }
      
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
    }
   
    /* Handle Suspend Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
    {
                printf("USB_OTG_GINTSTS_USBSUSP \r\n");
      if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
      {
        
        HAL_PCD_SuspendCallback(hpcd);
      }
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
    }

#ifdef USB_OTG_GLPMCFG_LPMEN
    /* Handle LPM Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
    {
                printf("USB_OTG_GINTSTS_LPMINT \r\n");
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);      
      if( hpcd->LPM_State == LPM_L0)
      {
        hpcd->LPM_State = LPM_L1;
        hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >> 2U;
        HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
      }
      else
      {
        HAL_PCD_SuspendCallback(hpcd);
      }
    }
#endif /* USB_OTG_GLPMCFG_LPMEN */

    /* Handle Reset Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
    {
                printf("USB_OTG_GINTSTS_USBRST \r\n");
      USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
      USB_FlushTxFifo(hpcd->Instance , 0x10U);
      
      for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
      {
        USBx_INEP(i)->DIEPINT = 0xFFU;
        USBx_OUTEP(i)->DOEPINT = 0xFFU;
      }
      USBx_DEVICE->DAINT = 0xFFFFFFFFU;
      USBx_DEVICE->DAINTMSK |= 0x10001U;
      
      if(hpcd->Init.use_dedicated_ep1)
      {
        USBx_DEVICE->DOUTEP1MSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
        USBx_DEVICE->DINEP1MSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);  
      }
      else
      {
#ifdef USB_OTG_DOEPINT_OTEPSPR
        USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM | USB_OTG_DOEPMSK_OTEPSPRM);
#else
        USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
#endif /* USB_OTG_DOEPINT_OTEPSPR */
        USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
      }
      
      /* Set Default Address to 0 */
      USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
      
      /* setup EP0 to receive SETUP packets */
      USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
        
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
    }
   
    /* Handle Enumeration done Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
    {
                printf("USB_OTG_GINTSTS_ENUMDNE \r\n");
      USB_ActivateSetup(hpcd->Instance);
      hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
      
      if ( USB_GetDevSpeed(hpcd->Instance) == USB_OTG_SPEED_HIGH)
      {
        hpcd->Init.speed            = USB_OTG_SPEED_HIGH;
        hpcd->Init.ep0_mps          = USB_OTG_HS_MAX_PACKET_SIZE ;   
        hpcd->Instance->GUSBCFG |= (uint32_t)((USBD_HS_TRDT_VALUE << 10U) & USB_OTG_GUSBCFG_TRDT);
      }
      else
      {
        hpcd->Init.speed            = USB_OTG_SPEED_FULL;
        hpcd->Init.ep0_mps          = USB_OTG_FS_MAX_PACKET_SIZE ;  
        
        /* The USBTRD is configured according to the tables below, depending on AHB frequency
        used by application. In the low AHB frequency range it is used to stretch enough the USB response
        time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access
        latency to the Data FIFO */
        
        /* Get hclk frequency value */
        hclk = HAL_RCC_GetHCLKFreq();
        
        if((hclk >= 14200000U)&&(hclk < 15000000U))
        {
          /* hclk Clock Range between 14.2-15 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0xFU << 10U) & USB_OTG_GUSBCFG_TRDT);
        }
        
        else if((hclk >= 15000000U)&&(hclk < 16000000U))
        {
          /* hclk Clock Range between 15-16 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0xEU << 10U) & USB_OTG_GUSBCFG_TRDT);
        }
        
        else if((hclk >= 16000000U)&&(hclk < 17200000U))
        {
          /* hclk Clock Range between 16-17.2 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0xDU << 10U) & USB_OTG_GUSBCFG_TRDT);
        }
        
        else if((hclk >= 17200000U)&&(hclk < 18500000U))
        {
          /* hclk Clock Range between 17.2-18.5 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0xCU << 10U) & USB_OTG_GUSBCFG_TRDT);
        }
        
        else if((hclk >= 18500000U)&&(hclk < 20000000U))
        {
          /* hclk Clock Range between 18.5-20 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0xBU << 10U) & USB_OTG_GUSBCFG_TRDT);
        }
        
        else if((hclk >= 20000000U)&&(hclk < 21800000U))
        {
          /* hclk Clock Range between 20-21.8 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0xAU << 10U) & USB_OTG_GUSBCFG_TRDT);
        }
        
        else if((hclk >= 21800000U)&&(hclk < 24000000U))
        {
          /* hclk Clock Range between 21.8-24 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0x9U << 10U) & USB_OTG_GUSBCFG_TRDT);
        }
        
        else if((hclk >= 24000000U)&&(hclk < 27700000U))
        {
          /* hclk Clock Range between 24-27.7 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0x8U << 10U) & USB_OTG_GUSBCFG_TRDT);
        }
        
        else if((hclk >= 27700000U)&&(hclk < 32000000U))
        {
          /* hclk Clock Range between 27.7-32 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0x7U << 10U) & USB_OTG_GUSBCFG_TRDT);
        }
        
        else /* if(hclk >= 32000000) */
        {
          /* hclk Clock Range between 32-180 MHz */
          hpcd->Instance->GUSBCFG |= (uint32_t)((0x6U << 10U) & USB_OTG_GUSBCFG_TRDT);
        }  
      }
      
      HAL_PCD_ResetCallback(hpcd);
      
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
    }

    /* Handle RxQLevel Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
    {
                printf("USB_OTG_GINTSTS_RXFLVL \r\n");
      USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
      
      temp = USBx->GRXSTSP;
      
      ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
      
      if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17U) ==  STS_DATA_UPDT)
      {
        if((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
        {
          USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4U);
          ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4U;
          ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4U;
        }
      }
      else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17U) ==  STS_SETUP_UPDT)
      {
        USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
        ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4U;
      }
      USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
    }
   
    /* Handle SOF Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
    {
                printf("USB_OTG_GINTSTS_SOF \r\n");
      HAL_PCD_SOFCallback(hpcd);
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
    }
   
    /* Handle Incomplete ISO IN Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
    {
                printf("USB_OTG_GINTSTS_IISOIXFR \r\n");
      HAL_PCD_ISOINIncompleteCallback(hpcd, epnum);
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
    }
   
    /* Handle Incomplete ISO OUT Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
    {
                printf("USB_OTG_GINTSTS_PXFR_INCOMPISOOUT \r\n");
      HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum);
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
    }
   
    /* Handle Connection event Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
    {
                printf("USB_OTG_GINTSTS_SRQINT \r\n");
      HAL_PCD_ConnectCallback(hpcd);
      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
    }
   
    /* Handle Disconnection event Interrupt */
    if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
    {
                printf("USB_OTG_GINTSTS_OTGINT \r\n");
      temp = hpcd->Instance->GOTGINT;
      
      if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
      {
        HAL_PCD_DisconnectCallback(hpcd);
      }
      hpcd->Instance->GOTGINT |= temp;
    }
  }
}


沙发
wakayi| | 2018-8-8 13:00 | 只看该作者
有没有卡死在某个报错的函数里边

使用特权

评论回复
板凳
syptt100|  楼主 | 2018-8-8 13:10 | 只看该作者
wakayi 发表于 2018-8-8 13:00
有没有卡死在某个报错的函数里边

没有,所有都正常,单步也没问题。
我打印了的端点信息,发现在调用HAL_PCD_DataOutStageCallback的地方,从来没有出现过端点1的中断。

使用特权

评论回复
地板
syptt100|  楼主 | 2018-8-8 13:17 | 只看该作者
我觉得可能还是寄存器的设置上,
当主机发出数据时候,
USB_OTG_GINTSTS_RXFLVL,这个是能够收到的,也能正确读出端点中的数据。
但是
USB_OTG_GINTSTS_OEPINT,这个信号,一直收不到,不知道什么鬼。

使用特权

评论回复
5
desertsailor| | 2018-8-8 13:21 | 只看该作者
你mcu设置的buffer里面有数据了,说明USB-OUT得到了处理,查看一下你的回调函数在哪里调用的

使用特权

评论回复
6
syptt100|  楼主 | 2018-8-8 13:27 | 只看该作者
desertsailor 发表于 2018-8-8 13:21
你mcu设置的buffer里面有数据了,说明USB-OUT得到了处理,查看一下你的回调函数在哪里调用的 ...

接收数据,是在USB_OTG_GINTSTS_RXFLVL标志理做的。
我看回调函数在USB_OTG_GINTSTS_OEPINT标志里,而这个状态一直没有发生,只有端点0不断能调用进来
这是CUBEMX生成的工程,这一块不该出问题呀~

使用特权

评论回复
7
syptt100|  楼主 | 2018-8-8 13:33 | 只看该作者
或者说,在主机向usb-endpoint 1 发送数据的时候,该端点没有产生中断(USB_OTG_GINTSTS_OEPINT)!!!
请高手们指点~

使用特权

评论回复
8
天灵灵地灵灵| | 2018-8-8 19:14 | 只看该作者
确认一下,中断配置是不是正确。

使用特权

评论回复
9
renzheshengui| | 2018-8-9 09:42 | 只看该作者
看样子是收到数据了 但是好像不知道怎么处理的啊

使用特权

评论回复
10
wakayi| | 2018-8-9 09:43 | 只看该作者
syptt100 发表于 2018-8-8 13:10
没有,所有都正常,单步也没问题。
我打印了的端点信息,发现在调用HAL_PCD_DataOutStageCallback的地方 ...

难道是你中断处理函数没有写好?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

5

帖子

0

粉丝