Exemple #1
0
/**
* @brief  USB_OTG_HandleUSBSuspend_ISR
*         Indicates that SUSPEND state has been detected on the USB
* @param  pdev: device instance
* @retval status
*/
static uint32_t DCD_HandleUSBSuspend_ISR(USB_OTG_CORE_HANDLE *pdev)
{
  USB_OTG_GINTSTS_TypeDef  gintsts;
  USB_OTG_PCGCCTL_TypeDef  power;
  USB_OTG_DSTS_TypeDef     dsts;
  __IO uint8_t prev_status = 0;
  
  prev_status = pdev->dev.device_status;
  USBD_DCD_INT_fops->Suspend (pdev);      
  
  dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS);
    
  /* Clear interrupt */
  gintsts.d32 = 0;
  gintsts.b.usbsuspend = 1;
  USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, gintsts.d32);
  
  if((pdev->cfg.low_power) && (dsts.b.suspsts == 1)  && 
    (pdev->dev.connection_status == 1) && 
    (prev_status  == USB_OTG_CONFIGURED))
  {
	/*  switch-off the clocks */
    power.d32 = 0;
    power.b.stoppclk = 1;
    USB_OTG_MODIFY_REG32(pdev->regs.PCGCCTL, 0, power.d32);  
    
    power.b.gatehclk = 1;
    USB_OTG_MODIFY_REG32(pdev->regs.PCGCCTL, 0, power.d32);
    
    /* Request to enter Sleep mode after exit from current ISR */
    SCB->SCR |= (SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk);
  }
  return 1;
}
Exemple #2
0
/**
* @brief  USB_OTG_USBH_handle_rx_qlvl_ISR 
*         Handles the Rx Status Queue Level Interrupt
* @param  pdev: Selected device
* @retval status 
*/
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma optimize = none
#endif /* __CC_ARM */
static uint32_t USB_OTG_USBH_handle_rx_qlvl_ISR (USB_OTG_CORE_HANDLE *pdev)
{
  USB_OTG_GRXFSTS_TypeDef       grxsts;
  USB_OTG_GINTMSK_TypeDef       intmsk;
  USB_OTG_HCTSIZn_TypeDef       hctsiz; 
  USB_OTG_HCCHAR_TypeDef        hcchar;
  __IO uint8_t                  channelnum =0;  
  uint32_t                      count;    
  
  /* Disable the Rx Status Queue Level interrupt */
  intmsk.d32 = 0;
  intmsk.b.rxstsqlvl = 1;
  USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, intmsk.d32, 0);
  
  grxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GRXSTSP);
  channelnum = grxsts.b.chnum;  
  hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[channelnum]->HCCHAR);
  
  switch (grxsts.b.pktsts)
  {
  case GRXSTS_PKTSTS_IN:
    /* Read the data into the host buffer. */
#ifdef USE_HOST_MODE
    if ((grxsts.b.bcnt > 0) && (pdev->host.hc[channelnum].xfer_buff != (void  *)0))
    {  
      
      USB_OTG_ReadPacket(pdev, pdev->host.hc[channelnum].xfer_buff, grxsts.b.bcnt);
      /*manage multiple Xfer */
      pdev->host.hc[grxsts.b.chnum].xfer_buff += grxsts.b.bcnt;           
      pdev->host.hc[grxsts.b.chnum].xfer_count  += grxsts.b.bcnt;
      
      
      count = pdev->host.hc[channelnum].xfer_count;
      pdev->host.XferCnt[channelnum]  = count;
      
      hctsiz.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[channelnum]->HCTSIZ);
      if(hctsiz.b.pktcnt > 0)
      {
        /* re-activate the channel when more packets are expected */
        hcchar.b.chen = 1;
        hcchar.b.chdis = 0;
        USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[channelnum]->HCCHAR, hcchar.d32);
      }
    }
#endif
    break;
    
  case GRXSTS_PKTSTS_IN_XFER_COMP:
    
  case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
  case GRXSTS_PKTSTS_CH_HALTED:
  default:
    break;
  }
  
  /* Enable the Rx Status Queue Level interrupt */
  intmsk.b.rxstsqlvl = 1;
  USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, 0, intmsk.d32);
  return 1;
}
Exemple #3
0
//--------------------------------------------------------------
void USB_OTG_ActiveRemoteWakeup(USB_OTG_CORE_HANDLE * pdev)
{

    USB_OTG_DCTL_TypeDef dctl;
    USB_OTG_DSTS_TypeDef dsts;
    USB_OTG_PCGCCTL_TypeDef power;

    if (pdev->dev.DevRemoteWakeup) {
        dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS);
        if (dsts.b.suspsts == 1) {
            if (pdev->cfg.low_power) {
                /* un-gate USB Core clock */
                power.d32 = USB_OTG_READ_REG32(&pdev->regs.PCGCCTL);
                power.b.gatehclk = 0;
                power.b.stoppclk = 0;
                USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, power.d32);
            }
            /* active Remote wakeup signaling */
            dctl.d32 = 0;
            dctl.b.rmtwkupsig = 1;
            USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, 0, dctl.d32);
            USB_OTG_BSP_mDelay(5);
            USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, dctl.d32, 0);
        }
    }
}
Exemple #4
0
/**
  * @brief  USB_OTG_HandleConnectorIDStatusChange_ISR
  *         handles the Connector ID Status Change Interrupt
  * @param  None
  * @retval : status
  */
static uint32_t USB_OTG_HandleConnectorIDStatusChange_ISR(USB_OTG_CORE_HANDLE *pdev)
{
  USB_OTG_GINTMSK_TypeDef  gintmsk;
  USB_OTG_GOTGCTL_TypeDef   gotgctl;
  USB_OTG_GINTSTS_TypeDef  gintsts;

  gintsts.d32 = 0 ;
  gintmsk.d32 = 0 ;
  gotgctl.d32 = 0 ;
  gintmsk.b.sofintr = 1;

  USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, gintmsk.d32, 0);
  gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL);

  /* B-Device connector (Device Mode) */
  if (gotgctl.b.conidsts)
  {
    USB_OTG_DisableGlobalInt(pdev);
    USB_OTG_CoreInitDev(pdev);
    USB_OTG_EnableGlobalInt(pdev);
    pdev->otg.OTG_State = B_PERIPHERAL;
  }
  else
  {
    USB_OTG_DisableGlobalInt(pdev);
    USB_OTG_CoreInitHost(pdev);
    USB_OTG_EnableGlobalInt(pdev);
    pdev->otg.OTG_State = A_HOST;
  }
  /* Set flag and clear interrupt */
  gintsts.b.conidstschng = 1;
  USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, gintsts.d32);
  return 1;
}
Exemple #5
0
/*******************************************************************************
* Function Name  : OTGD_FS_EPDeactivate
* Description    : Deactivates an EP
* Input          : ep
* Output         : None
* Return         : num_in_ep
*******************************************************************************/
USB_OTG_Status OTGD_FS_EPDeactivate(USB_OTG_EP *ep)
{

  USB_OTG_Status status = USB_OTG_OK;
  USB_OTG_DEPCTLx_TypeDef depctl;
  __IO uint32_t *addr;
  USB_OTG_DAINT_TypeDef daintmsk;

  depctl.d32 = 0;
  daintmsk.d32 = 0;
  
  /* Read DEPCTLn register */
  if (ep->is_in == 1)
  {
    addr = &USB_OTG_FS_regs.DINEPS[ep->num]->DIEPCTLx;
    daintmsk.ep.in = 1 << ep->num;
  }
  else
  {
    addr = &USB_OTG_FS_regs.DOUTEPS[ep->num]->DOEPCTLx;
    daintmsk.ep.out = 1 << ep->num;
  }

  depctl.b.usbactep = 0;
  USB_OTG_WRITE_REG32(addr, depctl.d32);

  /* Disable the Interrupt for this EP */
  USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DAINTMSK, daintmsk.d32, 0);
  return status;
}
Exemple #6
0
//--------------------------------------------------------------
USB_OTG_STS USB_OTG_EPActivate(USB_OTG_CORE_HANDLE * pdev, USB_OTG_EP * ep)
{
    USB_OTG_STS status = USB_OTG_OK;
    USB_OTG_DEPCTL_TypeDef depctl;
    USB_OTG_DAINT_TypeDef daintmsk;
    __IO uint32_t *addr;


    depctl.d32 = 0;
    daintmsk.d32 = 0;
    /* Read DEPCTLn register */
    if (ep->is_in == 1) {
        addr = &pdev->regs.INEP_REGS[ep->num]->DIEPCTL;
        daintmsk.ep.in = 1 << ep->num;
    } else {
        addr = &pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL;
        daintmsk.ep.out = 1 << ep->num;
    }
    /* If the EP is already active don't change the EP Control
     * register. */
    depctl.d32 = USB_OTG_READ_REG32(addr);
    if (!depctl.b.usbactep) {
        depctl.b.mps = ep->maxpacket;
        depctl.b.eptype = ep->type;
        depctl.b.txfnum = ep->tx_fifo_num;
        depctl.b.setd0pid = 1;
        depctl.b.usbactep = 1;
        USB_OTG_WRITE_REG32(addr, depctl.d32);
    }
    /* Enable the Interrupt for this EP */

    USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DAINTMSK, 0, daintmsk.d32);
    return status;
}
Exemple #7
0
//--------------------------------------------------------------
USB_OTG_STS USB_OTG_EPDeactivate(USB_OTG_CORE_HANDLE * pdev, USB_OTG_EP * ep)
{
    USB_OTG_STS status = USB_OTG_OK;
    USB_OTG_DEPCTL_TypeDef depctl;
    USB_OTG_DAINT_TypeDef daintmsk;
    __IO uint32_t *addr;

    depctl.d32 = 0;
    daintmsk.d32 = 0;
    /* Read DEPCTLn register */
    if (ep->is_in == 1) {
        addr = &pdev->regs.INEP_REGS[ep->num]->DIEPCTL;
        daintmsk.ep.in = 1 << ep->num;
    } else {
        addr = &pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL;
        daintmsk.ep.out = 1 << ep->num;
    }
    depctl.b.usbactep = 0;
    USB_OTG_WRITE_REG32(addr, depctl.d32);
    /* Disable the Interrupt for this EP */


    USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DAINTMSK, daintmsk.d32, 0);
    return status;
}
Exemple #8
0
//--------------------------------------------------------------
USB_OTG_STS USB_OTG_EnableDevInt(USB_OTG_CORE_HANDLE * pdev)
{
    USB_OTG_STS status = USB_OTG_OK;
    USB_OTG_GINTMSK_TypeDef intmsk;

    intmsk.d32 = 0;

    /* Disable all interrupts. */
    USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTMSK, 0);
    /* Clear any pending interrupts */
    USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, 0xFFFFFFFF);
    /* Enable the common interrupts */
    USB_OTG_EnableCommonInt(pdev);

    if (pdev->cfg.dma_enable == 0) {
        intmsk.b.rxstsqlvl = 1;
    }

    /* Enable interrupts matching to the Device mode ONLY */
    intmsk.b.usbsuspend = 1;
    intmsk.b.usbreset = 1;
    intmsk.b.enumdone = 1;
    intmsk.b.inepintr = 1;
    intmsk.b.outepintr = 1;
    intmsk.b.sofintr = 1;

    intmsk.b.incomplisoin = 1;
    intmsk.b.incomplisoout = 1;

    intmsk.b.sessreqintr = 1;
    intmsk.b.otgintr = 1;

    USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, intmsk.d32, intmsk.d32);
    return status;
}
Exemple #9
0
//--------------------------------------------------------------
USB_OTG_STS USB_OTG_EP0Activate(USB_OTG_CORE_HANDLE * pdev)
{
    USB_OTG_STS status = USB_OTG_OK;
    USB_OTG_DSTS_TypeDef dsts;
    USB_OTG_DEPCTL_TypeDef diepctl;
    USB_OTG_DCTL_TypeDef dctl;

    dctl.d32 = 0;
    /* Read the Device Status and Endpoint 0 Control registers */
    dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS);
    diepctl.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[0]->DIEPCTL);
    /* Set the MPS of the IN EP based on the enumeration speed */
    switch (dsts.b.enumspd) {
    case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
    case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
    case DSTS_ENUMSPD_FS_PHY_48MHZ:
        diepctl.b.mps = DEP0CTL_MPS_64;
        break;
    case DSTS_ENUMSPD_LS_PHY_6MHZ:
        diepctl.b.mps = DEP0CTL_MPS_8;
        break;
    }
    USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[0]->DIEPCTL, diepctl.d32);
    dctl.b.cgnpinnak = 1;
    USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, dctl.d32, dctl.d32);
    return status;
}
Exemple #10
0
/**
* @brief  This Function set USB device address
* @param pdev: device instance
* @param address: new device address
* @retval : status
*/
void  DCD_EP_SetAddress (USB_OTG_CORE_HANDLE *pdev, uint8_t address)
{
  USB_OTG_DCFG_TypeDef  dcfg;
  dcfg.d32 = 0;
  dcfg.b.devaddr = address;
  USB_OTG_MODIFY_REG32( &pdev->regs.DREGS->DCFG, 0, dcfg.d32);
}
Exemple #11
0
/**
* @brief  DCD_HandleResume_ISR
*         Indicates that the USB_OTG controller has detected a resume or
*                 remote Wake-up sequence
* @param  pdev: device instance
* @retval status
*/
static uint32_t DCD_HandleResume_ISR(USB_OTG_CORE_HANDLE *pdev)
{
  USB_OTG_GINTSTS_TypeDef  gintsts;
  USB_OTG_DCTL_TypeDef     devctl;
  USB_OTG_PCGCCTL_TypeDef  power;
  
  if(pdev->cfg.low_power)
  {
    /* un-gate USB Core clock */
    power.d32 = USB_OTG_READ_REG32(&pdev->regs.PCGCCTL);
    power.b.gatehclk = 0;
    power.b.stoppclk = 0;
    USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, power.d32);
  }
  
  /* Clear the Remote Wake-up Signaling */
  devctl.d32 = 0;
  devctl.b.rmtwkupsig = 1;
  USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, devctl.d32, 0);
  
  /* Inform upper layer by the Resume Event */
  USBD_DCD_INT_fops->Resume (pdev);
  
  /* Clear interrupt */
  gintsts.d32 = 0;
  gintsts.b.wkupintr = 1;
  USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, gintsts.d32);
  return 1;
}
//--------------------------------------------------------------
USB_OTG_STS USB_OTG_EnableHostInt(USB_OTG_CORE_HANDLE *pdev)
{
  USB_OTG_STS       status = USB_OTG_OK;
  USB_OTG_GINTMSK_TypeDef  intmsk;
  intmsk.d32 = 0;
  /* Disable all interrupts. */
  USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTMSK, 0);
  
  /* Clear any pending interrupts. */
  USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, 0xFFFFFFFF);
  
  /* Enable the common interrupts */
  USB_OTG_EnableCommonInt(pdev);
  
  if (pdev->cfg.dma_enable == 0)
  {  
    intmsk.b.rxstsqlvl  = 1;
  }  
  intmsk.b.portintr   = 1;
  intmsk.b.hcintr     = 1;
  intmsk.b.disconnect = 1;  
  intmsk.b.sofintr    = 1;  
  intmsk.b.incomplisoout  = 1; 
  USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, intmsk.d32, intmsk.d32);
  return status;
}
Exemple #13
0
/**
* @brief  DCD_HandleRxStatusQueueLevel_ISR
*         Handles the Rx Status Queue Level Interrupt
* @param  pdev: device instance
* @retval status
*/
static uint32_t DCD_HandleRxStatusQueueLevel_ISR(USB_OTG_CORE_HANDLE *pdev)
{
  USB_OTG_GINTMSK_TypeDef  int_mask;
  USB_OTG_DRXSTS_TypeDef   status;
  USB_OTG_EP *ep;
  
  /* Disable the Rx Status Queue Level interrupt */
  int_mask.d32 = 0;
  int_mask.b.rxstsqlvl = 1;
  USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, int_mask.d32, 0);
  
  /* Get the Status from the top of the FIFO */
  status.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GRXSTSP );
  
  ep = &pdev->dev.out_ep[status.b.epnum];
  
  switch (status.b.pktsts)
  {
  case STS_GOUT_NAK:
    break;
  case STS_DATA_UPDT:
    if (status.b.bcnt)
    {
      USB_OTG_ReadPacket(pdev,ep->xfer_buff, status.b.bcnt);
      ep->xfer_buff += status.b.bcnt;
      ep->xfer_count += status.b.bcnt;
    }
    break;
  case STS_XFER_COMP:
    break;
  case STS_SETUP_COMP:
    break;
  case STS_SETUP_UPDT:
    /* Copy the setup packet received in FIFO into the setup buffer in RAM */
    USB_OTG_ReadPacket(pdev , pdev->dev.setup_packet, 8);
    ep->xfer_count += status.b.bcnt;
    break;
  default:
    break;
  }
  
  /* Enable the Rx Status Queue Level interrupt */
  USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, 0, int_mask.d32);
  
  return 1;
}
/**
  * @brief  USB_OTG_BSP_Suspend
  *         Handles the Enter USB to Suspend Mode
  * @param  pdev: Selected device
  * @retval Status
  */
void USB_OTG_BSP_Suspend(USB_OTG_CORE_HANDLE *pdev)
{
  USB_OTG_HPRT0_TypeDef    hprt0;
  USB_OTG_PCGCCTL_TypeDef  power;
  hprt0.d32  = 0;
  hprt0.d32  = USB_OTG_ReadHPRT0(pdev);
  hprt0.b.prtsusp = 1; 
  USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32);
  
  /*  switch-off the clocks */
  power.d32 = 0;
  power.b.stoppclk = 1;
  USB_OTG_MODIFY_REG32(pdev->regs.PCGCCTL, 0, power.d32);  
  
  power.b.gatehclk = 1;
  USB_OTG_MODIFY_REG32(pdev->regs.PCGCCTL, 0, power.d32);
}
Exemple #15
0
//--------------------------------------------------------------
USB_OTG_STS USB_OTG_DisableGlobalInt(USB_OTG_CORE_HANDLE * pdev)
{
    USB_OTG_STS status = USB_OTG_OK;
    USB_OTG_GAHBCFG_TypeDef ahbcfg;
    ahbcfg.d32 = 0;
    ahbcfg.b.glblintrmsk = 1;   /* Enable interrupts */
    USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GAHBCFG, ahbcfg.d32, 0);
    return status;
}
Exemple #16
0
/*******************************************************************************
* Function Name  : OTGD_FS_DisableGlobalInt
* Description    : Disables the controller's Global Int in the AHB Config reg
* Input          : None
* Output         : None
* Return         : Status
*******************************************************************************/
USB_OTG_Status OTGD_FS_DisableGlobalInt(void)
{
  USB_OTG_Status status = USB_OTG_OK;
  USB_OTG_GAHBCFG_TypeDef ahbcfg;

  ahbcfg.d32 = 0;
  ahbcfg.b.gintmsk = 1; /* Enable interrupts */
  USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.GREGS->GAHBCFG, ahbcfg.d32, 0);
  return status;
}
Exemple #17
0
/*******************************************************************************
* Function Name  : PCD_EP_SetAddress
* Description    : This Function set USB device address
* Input          : The new device Address to be set.
* Output         : None
* Return         : status
*******************************************************************************/
void  PCD_EP_SetAddress (uint8_t address)
{

  USB_OTG_DCFG_TypeDef dcfg;

  dcfg.d32 = 0;
  
  dcfg.b.devaddr = address;
  USB_OTG_MODIFY_REG32( &USB_OTG_FS_regs.DEV->DCFG, 0, dcfg.d32);
}
Exemple #18
0
/**
* @brief  DCD_WriteEmptyTxFifo
*         check FIFO for the next packet to be loaded
* @param  pdev: device instance
* @retval status
*/
static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev, uint32_t epnum)
{
  USB_OTG_DTXFSTSn_TypeDef  txstatus;
  USB_OTG_EP *ep;
  uint32_t len = 0;
  uint32_t len32b;
  txstatus.d32 = 0;

  ep = &pdev->dev.in_ep[epnum];

  len = ep->xfer_len - ep->xfer_count;

  if (len > ep->maxpacket)
  {
    len = ep->maxpacket;
  }

  len32b = (len + 3) / 4;
  txstatus.d32 = USB_OTG_READ_REG32( &pdev->regs.INEP_REGS[epnum]->DTXFSTS);



  while  (txstatus.b.txfspcavail > len32b &&
          ep->xfer_count < ep->xfer_len &&
            ep->xfer_len != 0)
  {
    /* Write the FIFO */
    len = ep->xfer_len - ep->xfer_count;

    if (len > ep->maxpacket)
    {
      len = ep->maxpacket;
    }
    len32b = (len + 3) / 4;

    USB_OTG_WritePacket (pdev , ep->xfer_buff, epnum, len);

    ep->xfer_buff  += len;
    ep->xfer_count += len;

    txstatus.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DTXFSTS);

    // clear TXEmpty, to prevent endless stream of irq from hanging system. per:
    // https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex%5fmx%5fstm32%2fYet%20another%20STM32F1057%20USB%20OTG%20driver%20issue%20%28VCP%20device%29&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=3190

    if( ep->xfer_count >= ep->xfer_len){
      uint32_t fifoemptymsk = 1 << ep->num;
      USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);
      break;
    }

  }

  return 1;
}
/**
* @brief  DCD_WriteEmptyTxFifo
*         check FIFO for the next packet to be loaded
* @param  pdev: device instance
* @retval status
*/
static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev, uint32_t epnum)
{
  USB_OTG_DTXFSTSn_TypeDef  txstatus;
  USB_OTG_EP *ep;
  uint32_t len = 0;
  uint32_t len32b;
  txstatus.d32 = 0;
  
  ep = &pdev->dev.in_ep[epnum];    
  
  len = ep->xfer_len - ep->xfer_count;
  
  if (len > ep->maxpacket)
  {
    len = ep->maxpacket;
  }
  
  len32b = (len + 3) / 4;
  txstatus.d32 = USB_OTG_READ_REG32( &pdev->regs.INEP_REGS[epnum]->DTXFSTS);
  
  
  
  while  (txstatus.b.txfspcavail > len32b &&
          ep->xfer_count < ep->xfer_len &&
            ep->xfer_len != 0)
  {
    /* Write the FIFO */
    len = ep->xfer_len - ep->xfer_count;
    
    if (len > ep->maxpacket)
    {
      len = ep->maxpacket;
    }
    len32b = (len + 3) / 4;
    
    USB_OTG_WritePacket (pdev , ep->xfer_buff, epnum, len);
    
    ep->xfer_buff  += len;
    ep->xfer_count += len;
    
    // this code turns off the "empty interrupt"
    // without it the USB is subject to perpetual interrupts
    // see my.st.com, "Yet another STM32F105/7 USB OTG driver issue (VCP device)"
    // this code might also work if put in DCD_HandleInEP_ISR
    if (ep->xfer_count >= ep->xfer_len) {
      uint32_t fifoemptymsk = 1 << ep->num;
      USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);
      break;
    }

    txstatus.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DTXFSTS);
  }
  
  return 1;
}
Exemple #20
0
/**
* @brief  DCD_WriteEmptyTxFifo
*         check FIFO for the next packet to be loaded
* @param  pdev: device instance
* @retval status
*/
static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev, uint32_t epnum)
{
  USB_OTG_DTXFSTSn_TypeDef  txstatus;
  USB_OTG_EP *ep;
  uint32_t len = 0;
  uint32_t len32b;
  txstatus.d32 = 0;
  uint32_t fifoemptymsk;  // HJI Patch from STM Forum, Tags: usb vcp stm32_usb-s-device_lib
  
  ep = &pdev->dev.in_ep[epnum];    
  
  len = ep->xfer_len - ep->xfer_count;
  
  if (len > ep->maxpacket)
  {
    len = ep->maxpacket;
  }
  
  len32b = (len + 3) / 4;
  txstatus.d32 = USB_OTG_READ_REG32( &pdev->regs.INEP_REGS[epnum]->DTXFSTS);
  
  
  
  while  (txstatus.b.txfspcavail > len32b &&
          ep->xfer_count < ep->xfer_len &&
            ep->xfer_len != 0)
  {
    /* Write the FIFO */
    len = ep->xfer_len - ep->xfer_count;
    
    if (len > ep->maxpacket)
    {
      len = ep->maxpacket;
    }
    len32b = (len + 3) / 4;
    
    USB_OTG_WritePacket (pdev , ep->xfer_buff, epnum, len);
    
    ep->xfer_buff  += len;
    ep->xfer_count += len;
    
    if( ep->xfer_count >= ep->xfer_len)                                      // HJI Patch from STM Forum, Tags: usb vcp stm32_usb-s-device_lib
    {                                                                        // HJI Patch from STM Forum, Tags: usb vcp stm32_usb-s-device_lib
      fifoemptymsk = 1 << ep->num;                                           // HJI Patch from STM Forum, Tags: usb vcp stm32_usb-s-device_lib
      USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);  // HJI Patch from STM Forum, Tags: usb vcp stm32_usb-s-device_lib
      break;                                                                 // HJI Patch from STM Forum, Tags: usb vcp stm32_usb-s-device_lib
    }                                                                        // HJI Patch from STM Forum, Tags: usb vcp stm32_usb-s-device_lib

    txstatus.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DTXFSTS);
  }
  
  return 1;
}
Exemple #21
0
/**
* @brief  DCD_WriteEmptyTxFifo
*         check FIFO for the next packet to be loaded
* @param  pdev: device instance
* @retval status
*/
static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev, uint32_t epnum)
{
  USB_OTG_DTXFSTSn_TypeDef  txstatus;
  USB_OTG_EP *ep;
  uint32_t len = 0;
  uint32_t len32b;
  txstatus.d32 = 0;
  
  ep = &pdev->dev.in_ep[epnum];    
  
  len = ep->xfer_len - ep->xfer_count;
  
  if (len > ep->maxpacket)
  {
    len = ep->maxpacket;
  }
  
  len32b = (len + 3) / 4;
  txstatus.d32 = USB_OTG_READ_REG32( &pdev->regs.INEP_REGS[epnum]->DTXFSTS);
  
  
  
  while  (txstatus.b.txfspcavail > len32b &&
          ep->xfer_count < ep->xfer_len &&
            ep->xfer_len != 0)
  {
    /* Write the FIFO */
    len = ep->xfer_len - ep->xfer_count;
    
    if (len > ep->maxpacket)
    {
      len = ep->maxpacket;
    }
    len32b = (len + 3) / 4;
    
    USB_OTG_WritePacket (pdev , ep->xfer_buff, epnum, len);
    
    ep->xfer_buff  += len;
    ep->xfer_count += len;
    
    // FIXME THIS FOLLOWING FOUR LINES ARE A WORKAROUND FOR THE INFINITY EMPTY BUFFER INTERRUPT BUG
    if( ep->xfer_count >= ep->xfer_len)
    {
	  uint32_t fifoemptymsk = 1 << ep->num;
	  USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);
	  break;
	}

    txstatus.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DTXFSTS);
  }
  
  return 1;
}
/**
 * @brief  USBD_OTG_EP1IN_ISR_Handler
 *         handles all USB Interrupts
 * @param  pdev: device instance
 * @retval status
 */
uint32_t USBD_OTG_EP1IN_ISR_Handler (USB_OTG_CORE_HANDLE *pdev)
{

	USB_OTG_DIEPINTn_TypeDef diepint;
	uint32_t fifoemptymsk, msk, emp;

	msk = USB_OTG_READ_REG32(&pdev->regs.DREGS->DINEP1MSK);
	emp = USB_OTG_READ_REG32(&pdev->regs.DREGS->DIEPEMPMSK);
	msk |= ((emp >> 1 ) & 0x1) << 7;
	diepint.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[1]->DIEPINT) & msk;

	if ( diepint.b.xfercompl )
	{
		fifoemptymsk = 0x1 << 1;
		USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);
		CLEAR_IN_EP_INTR(1, xfercompl);
		/* TX COMPLETE */
		USBD_DCD_INT_fops->DataInStage(pdev , 1);
	}
	if ( diepint.b.ahberr )
	{
		CLEAR_IN_EP_INTR(1, ahberr);
	}
	if ( diepint.b.epdisabled )
	{
		CLEAR_IN_EP_INTR(1, epdisabled);
	}
	if ( diepint.b.timeout )
	{
		CLEAR_IN_EP_INTR(1, timeout);
	}
	if (diepint.b.intktxfemp)
	{
		CLEAR_IN_EP_INTR(1, intktxfemp);
	}
	if (diepint.b.intknepmis)
	{
		CLEAR_IN_EP_INTR(1, intknepmis);
	}
	if (diepint.b.inepnakeff)
	{
		CLEAR_IN_EP_INTR(1, inepnakeff);
	}
	if (diepint.b.emptyintr)
	{
		DCD_WriteEmptyTxFifo(pdev , 1);
		// <--------- fix: from here
		fifoemptymsk = 0x1 << 1;
		USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0)
		//CLEAR_IN_EP_INTR(1, emptyintr);

		// <--------- fix: to here
	}
Exemple #23
0
static uint32_t USB_OTG_USBH_handle_nptxfempty_ISR(USB_OTG_CORE_HANDLE*pdev)
{
	USB_OTG_GINTMSK_TypeDef intmsk;
	USB_OTG_HNPTXSTS_TypeDef hnptxsts;
	uint16_t len_words, len;

	hnptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS);
	
	#ifdef DEBUG
	if (hnptxsts.b.chnum > 0)
		p_err("nptxfempty:%d\n", hnptxsts.b.nptxfspcavail);

	if (pdev->host.hc[hnptxsts.b.chnum].xfer_len == 0)
	{
		p_err("%s xfer_len == 0, %d\n", __FUNCTION__, hnptxsts.b.chnum);
		USB_OTG_HC_Halt(pdev, hnptxsts.b.chnum); //test
		return 0;
	}
	#endif

	

	len_words = (pdev->host.hc[hnptxsts.b.chnum].xfer_len + 3) / 4;

	while ((hnptxsts.b.nptxfspcavail > len_words) && (pdev
	->host.hc[hnptxsts.b.chnum].xfer_len != 0))
	{

		len = hnptxsts.b.nptxfspcavail * 4;

		if (len > pdev->host.hc[hnptxsts.b.chnum].xfer_len)
		{
			/* Last packet */
			len = pdev->host.hc[hnptxsts.b.chnum].xfer_len;

			intmsk.d32 = 0;
			intmsk.b.nptxfempty = 1;
			USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, intmsk.d32, 0);
		}

		len_words = (pdev->host.hc[hnptxsts.b.chnum].xfer_len + 3) / 4;

		USB_OTG_WritePacket(pdev, pdev->host.hc[hnptxsts.b.chnum].xfer_buff,
	hnptxsts.b.chnum, len);

		pdev->host.hc[hnptxsts.b.chnum].xfer_buff += len;
		pdev->host.hc[hnptxsts.b.chnum].xfer_len -= len;
		pdev->host.hc[hnptxsts.b.chnum].xfer_count += len;
		hnptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS);
	}

	return 1;
}
Exemple #24
0
/**
* @brief  DCD_WriteEmptyTxFifo
*         check FIFO for the next packet to be loaded
* @param  pdev: device instance
* @retval status
*/
static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev, uint32_t epnum)
{
  USB_OTG_DTXFSTSn_TypeDef  txstatus;
  USB_OTG_EP *ep;
  uint32_t len = 0;
  uint32_t len32b;
  txstatus.d32 = 0;

  ep = &pdev->dev.in_ep[epnum];

  len = ep->xfer_len - ep->xfer_count;

  if (len > ep->maxpacket)
  {
    len = ep->maxpacket;
  }

  len32b = (len + 3) / 4;
  txstatus.d32 = USB_OTG_READ_REG32( &pdev->regs.INEP_REGS[epnum]->DTXFSTS);



  while  (txstatus.b.txfspcavail > len32b &&
          ep->xfer_count < ep->xfer_len &&
            ep->xfer_len != 0)
  {
    /* Write the FIFO */
    len = ep->xfer_len - ep->xfer_count;

    if (len > ep->maxpacket)
    {
      len = ep->maxpacket;
    }
    len32b = (len + 3) / 4;

    USB_OTG_WritePacket (pdev , ep->xfer_buff, epnum, len);

    ep->xfer_buff  += len;
    ep->xfer_count += len;

    //According to "bil.til" from ST E2E Community
    if( ep->xfer_count >= ep->xfer_len)
    {
      uint32_t fifoemptymsk = 1 << ep->num;
      USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);
      break;
    }

    txstatus.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DTXFSTS);
  }

  return 1;
}
/*******************************************************************************
* Function Name  : PCD_WriteEmptyTxFifo
* Description    : Checks Fifo for the next packet to be loaded.
* Input          : None
* Output         : None
* Return         : Status
*******************************************************************************/
static uint32_t PCD_WriteEmptyTxFifo(uint32_t epnum)
{
  USB_OTG_DTXFSTS_TypeDef txstatus;
  USB_OTG_EP *ep;
  uint32_t len = 0;
  uint32_t dwords = 0;
  uint32_t fifoemptymsk = 0;
  
  txstatus.d32 = 0;
  
  ep = PCD_GetInEP(epnum); 
  
  len = ep->xfer_len - ep->xfer_count;

  if (len > ep->maxpacket)
  {
    len = ep->maxpacket;
  }
  
  dwords = (len + 3) / 4;
  txstatus.d32 = USB_OTG_READ_REG32( &USB_OTG_FS_regs.DINEPS[epnum]->DTXFSTSx);

  
  while  ((txstatus.b.txfspcavail > dwords) &&
          (ep->xfer_count < ep->xfer_len) &&
          (ep->xfer_len) != 0)
  {
    len = ep->xfer_len - ep->xfer_count;

    if (len > ep->maxpacket)
    {
      len = ep->maxpacket;
    }
    dwords = (len + 3) / 4;

    OTGD_FS_WritePacket(ep->xfer_buff, epnum, len);    
    
    ep->xfer_count += len;
    ep->xfer_buff += len; 

    txstatus.d32 = USB_OTG_READ_REG32(&USB_OTG_FS_regs.DINEPS[epnum]->DTXFSTSx); 
    
    /* Mask the TxFIFOEmpty interrupt to prevent re-entring this routine */
    if (ep->xfer_len == ep->xfer_count)
    {
      fifoemptymsk = 0x1 << ep->num;
      USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DIEPEMPMSK, fifoemptymsk, 0);    
    }
  }
  
  return 1;
}
Exemple #26
0
/**
* @brief  USBD_OTG_EP1IN_ISR_Handler
*         handles all USB Interrupts
* @param  pdev: device instance
* @retval status
*/
uint32_t USBD_OTG_EP1IN_ISR_Handler (USB_OTG_CORE_HANDLE *pdev)
{
  
  USB_OTG_DIEPINTn_TypeDef  diepint;
  uint32_t fifoemptymsk, msk, emp;
  
  msk = USB_OTG_READ_REG32(&pdev->regs.DREGS->DINEP1MSK);
  emp = USB_OTG_READ_REG32(&pdev->regs.DREGS->DIEPEMPMSK);
  msk |= ((emp >> 1 ) & 0x1) << 7;
  diepint.d32  = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[1]->DIEPINT) & msk;  
  
  if ( diepint.b.xfercompl )
  {
    fifoemptymsk = 0x1 << 1;
    USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);
    CLEAR_IN_EP_INTR(1, xfercompl);
    /* TX COMPLETE */
    USBD_DCD_INT_fops->DataInStage(pdev , 1);
  }
  if ( diepint.b.epdisabled )
  {
    CLEAR_IN_EP_INTR(1, epdisabled);
  }  
  if ( diepint.b.timeout )
  {
    CLEAR_IN_EP_INTR(1, timeout);
  }
  if (diepint.b.intktxfemp)
  {
    CLEAR_IN_EP_INTR(1, intktxfemp);
  }
  if (diepint.b.inepnakeff)
  {
    CLEAR_IN_EP_INTR(1, inepnakeff);
  }
  if (diepint.b.emptyintr)
  {
    DCD_WriteEmptyTxFifo(pdev , 1);
    CLEAR_IN_EP_INTR(1, emptyintr);
    /*
    Notice: this probabbly needs the same fix as DCD_HandleInEP_ISR(), but
    leaving this out, we don't use this part of code
    fifoemptymsk = 0x1 << 1;
    USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);
    */
  }
  return 1;
}
/*******************************************************************************
* Function Name  : OTGD_FS_Handle_EOPF_ISR
* Description    : Handles the Expected End Of Periodic Frame interrupt.
* Input          : None
* Output         : None
* Return         : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_EOPF_ISR(void) {
    USB_OTG_GINTSTS_TypeDef gintsts;
    USB_OTG_GINTMSK_TypeDef gintmsk;

    gintsts.d32 = 0;
    gintmsk.d32 = 0;

    gintmsk.b.eopframe = 1;
    USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.GREGS->GINTMSK, gintmsk.d32, 0);

    /* Call user function */
    INTR_EOPFRAME_Callback();

    /* Clear interrupt */
    gintsts.b.eopframe = 1;
    USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.GREGS->GINTSTS, gintsts.d32);
    return 1;
}
Exemple #28
0
/*******************************************************************************
* Function Name  : OTGD_FS_EP0Activate
* Description    : enables EP0 OUT to receive SETUP packets and configures EP0
                   IN for transmitting packets
* Input          : None
* Output         : None
* Return         : status
*******************************************************************************/
USB_OTG_Status  OTGD_FS_EP0Activate(void)
{
  USB_OTG_Status          status = USB_OTG_OK;
  USB_OTG_DEPCTLx_TypeDef diepctl;
  USB_OTG_DCTL_TypeDef    dctl;

  diepctl.d32 = 0;
  dctl.d32 = 0;
  
  diepctl.d32 = USB_OTG_READ_REG32(&USB_OTG_FS_regs.DINEPS[0]->DIEPCTLx);
  diepctl.b.mps = DEP0CTL_MPS_64;
  USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.DINEPS[0]->DIEPCTLx, diepctl.d32);

  dctl.b.cgnpinnak = 1;
  USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DCTL, dctl.d32, dctl.d32);
  
  return status;
}
Exemple #29
0
static uint32_t USB_OTG_USBH_handle_nptxfempty_ISR(USB_OTG_CORE_HANDLE*pdev)
{
	int free_space;
	USB_OTG_HNPTXSTS_TypeDef hnptxsts;
	uint32_t write_len;
	char *write_buff;

	hnptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS);
	hnptxsts.b.chnum = pdev->cur_bulk_out_ch;


	write_len = (pdev->host.hc[hnptxsts.b.chnum].xfer_len + 3) / 4;

	free_space = hnptxsts.b.nptxfspcavail - 16;

	if (free_space < write_len)
	{
		write_len = free_space * 4;
		write_buff = (char*)pdev->host.hc[hnptxsts.b.chnum].xfer_buff;
		pdev->host.hc[hnptxsts.b.chnum].xfer_len -= write_len;
		pdev->host.hc[hnptxsts.b.chnum].xfer_buff += write_len;
	}
	else
	{
		USB_OTG_GINTMSK_TypeDef intmsk;
		intmsk.d32 = 0;
		intmsk.b.nptxfempty = 1;
		USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, intmsk.d32, 0);

		write_buff = (char*)pdev->host.hc[hnptxsts.b.chnum].xfer_buff;
		write_len = write_len * 4;
		pdev->host.hc[hnptxsts.b.chnum].xfer_len = 0;
		pdev->bulk_out_irq_pending = 0;
	}
	USB_OTG_WritePacket(pdev, (uint8_t*)write_buff, hnptxsts.b.chnum, write_len);

	if (pdev->host.hc[hnptxsts.b.chnum].xfer_len < 0)
	{
		pdev->host.hc[hnptxsts.b.chnum].xfer_len = 0;
	}

	return 1;
}
Exemple #30
0
static uint32_t USB_OTG_USBH_handle_ptxfempty_ISR(USB_OTG_CORE_HANDLE *pdev)
{

	USB_OTG_HPTXSTS_TypeDef hptxsts;
	uint32_t write_len;
	char *write_buff;

	hptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HPTXSTS);


	write_len = (pdev->host.hc[hptxsts.b.chnum].xfer_len + 3) / 4;

	if (hptxsts.b.ptxfspcavail <= write_len)
	{
		write_len = hptxsts.b.ptxfspcavail * 4;
		write_buff = (char*)pdev->host.hc[hptxsts.b.chnum].xfer_buff;
		pdev->host.hc[hptxsts.b.chnum].xfer_len -= write_len;
		pdev->host.hc[hptxsts.b.chnum].xfer_buff += write_len;
	}
	else
	{
		USB_OTG_GINTMSK_TypeDef intmsk;
		intmsk.d32 = 0;
		intmsk.b.ptxfempty = 1;
		USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, intmsk.d32, 0);

		write_buff = (char*)pdev->host.hc[hptxsts.b.chnum].xfer_buff;
		write_len = pdev->host.hc[hptxsts.b.chnum].xfer_len;

		pdev->host.hc[hptxsts.b.chnum].xfer_len = 0;
		pdev->host.hc[hptxsts.b.chnum].xfer_buff += write_len;
	}


	USB_OTG_WritePacket(pdev, (uint8_t*)write_buff, hptxsts.b.chnum, write_len);

	if (pdev->host.hc[hptxsts.b.chnum].xfer_len < 0)
	{
		pdev->host.hc[hptxsts.b.chnum].xfer_len = 0;
	}

	return 1;
}