IR-controller/old/usb_lib/otgd_fs_int.c
2015-04-22 12:35:38 +03:00

746 lines
21 KiB
C

/**
******************************************************************************
* @file otgd_fs_int.c
* @author MCD Application Team
* @version V3.4.0
* @date 29-June-2012
* @brief Endpoint interrupt's service routines.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
#ifdef STM32F10X_CL
/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"
#include "usb_type.h"
#include "otgd_fs_int.h"
#include "usb_lib.h"
#include "usb_istr.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t USBD_Data_Buffer [RX_FIFO_SIZE];
__IO uint8_t IsocBuff [(ISOC_BUFFER_SZE * NUM_SUB_BUFFERS)];
__IO uint32_t IsocBufferIdx = 0;
extern USB_OTG_CORE_REGS USB_OTG_FS_regs;
__IO uint16_t SaveRState;
__IO uint16_t SaveTState;
/* Extern variables ----------------------------------------------------------*/
extern void (*pEpInt_IN[7])(void); /* Handles IN interrupts */
extern void (*pEpInt_OUT[7])(void); /* Handles OUT interrupts */
/* Private function prototypes -----------------------------------------------*/
static uint32_t PCD_ReadDevInEP( USB_OTG_EP *ep);
static uint32_t PCD_WriteEmptyTxFifo(uint32_t epnum);
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : OTGD_FS_Handle_Sof_ISR
* Description : Handles the Start Of Frame detected interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_Sof_ISR(void)
{
USB_OTG_GINTSTS_TypeDef GINTSTS ;
GINTSTS.d32 = 0;
/* Call user function */
INTR_SOFINTR_Callback();
/* Clear interrupt */
GINTSTS.b.sofintr = 1;
USB_OTG_WRITE_REG32 (&USB_OTG_FS_regs.GREGS->GINTSTS, GINTSTS.d32);
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_RxStatusQueueLevel_ISR
* Description : Handles the Rx Status Queue Level Interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_RxStatusQueueLevel_ISR(void)
{
USB_OTG_GINTMSK_TypeDef int_mask;
USB_OTG_GRXSTSP_TypeDef status;
USB_OTG_EP *ep;
int_mask.d32 = 0;
status.d32 = 0;
/* Disable the Rx Status Queue Level interrupt */
int_mask.b.rxstsqlvl = 1;
USB_OTG_MODIFY_REG32( &USB_OTG_FS_regs.GREGS->GINTMSK, int_mask.d32, 0);
/* Get the Status from the top of the FIFO */
status.d32 = USB_OTG_READ_REG32( &USB_OTG_FS_regs.GREGS->GRXSTSP );
/* Get the related endpoint structure */
ep = PCD_GetOutEP(status.b.epnum);
switch (status.b.pktsts)
{
case STS_GOUT_NAK:
break;
case STS_DATA_UPDT:
if (status.b.bcnt)
{
if (ep->type == EP_TYPE_ISOC)
{
/* Call user function */
INTR_RXSTSQLVL_ISODU_Callback();
/* Copy the received buffer to the RAM */
OTGD_FS_ReadPacket((uint8_t*)(IsocBuff + (ISOC_BUFFER_SZE * IsocBufferIdx)), status.b.bcnt);
ep->xfer_buff = (uint8_t*)(IsocBuff + (ISOC_BUFFER_SZE * IsocBufferIdx));
/* Check if the end of the global buffer has been reached */
if (IsocBufferIdx == (NUM_SUB_BUFFERS - 1))
{
/* Reset the buffer index */
IsocBufferIdx = 0;
}
else
{
/* Increment the buffer index */
IsocBufferIdx ++;
}
}
else
{
/* Copy the received buffer to the RAM */
OTGD_FS_ReadPacket(USBD_Data_Buffer, status.b.bcnt);
ep->xfer_buff = USBD_Data_Buffer;
}
/* Update the endpoint structure */
ep->xfer_len = status.b.bcnt;
ep->xfer_count += status.b.bcnt;
}
else
{
ep->xfer_len = 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 */
OTGD_FS_ReadPacket(USBD_Data_Buffer, 8);
ep->xfer_buff = USBD_Data_Buffer;
ep->xfer_count += status.b.bcnt;
ep->xfer_len = status.b.bcnt;
break;
default:
break;
}
/* Call the user function */
INTR_RXSTSQLVL_Callback();
/* Enable the Rx Status Queue Level interrupt */
USB_OTG_MODIFY_REG32( &USB_OTG_FS_regs.GREGS->GINTMSK, 0, int_mask.d32);
/* Clear interrupt: this is a read only bit, it cannot be cleared by register
access */
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_GInNakEff_ISR
* Description : Handles the Global IN Endpoints NAK Effective interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_GInNakEff_ISR(void)
{
/* Call user function */
INTR_GINNAKEFF_Callback();
/* Clear interrupt: This is a read only bit, it cannot be cleared by register
access */
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_GOutNakEff_ISR
* Description : Handles the Global OUT Endpoints NAK Effective interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_GOutNakEff_ISR(void)
{
/* Call user function */
INTR_GOUTNAKEFF_Callback();
/* Clear interrupt: This is a read only bit, it cannot be cleared by register
access */
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_EarlySuspend_ISR
* Description : Handles the Early Suspend detected interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_EarlySuspend_ISR(void )
{
USB_OTG_GINTSTS_TypeDef gintsts;
USB_OTG_GINTMSK_TypeDef gintmsk;
gintsts.d32 = 0;
gintmsk.d32 = 0;
/* Call user function */
INTR_ERLYSUSPEND_Callback();
gintmsk.b.erlysuspend = 1;
USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.GREGS->GINTMSK, gintmsk.d32, 0 );
/* Clear interrupt */
gintsts.b.erlysuspend = 1;
USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.GREGS->GINTSTS, gintsts.d32);
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_USBSuspend_ISR
* Description : Handles the Suspend condition detected interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_USBSuspend_ISR(void)
{
USB_OTG_GINTSTS_TypeDef gintsts;
gintsts.d32 = 0;
/* Call user function */
INTR_USBSUSPEND_Callback();
/* Clear interrupt */
gintsts.b.usbsuspend = 1;
USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.GREGS->GINTSTS, gintsts.d32);
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_UsbReset_ISR
* Description : This interrupt occurs when a USB Reset is detected.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_UsbReset_ISR(void)
{
USB_OTG_DAINT_TypeDef daintmsk;
USB_OTG_DOEPMSKx_TypeDef doepmsk;
USB_OTG_DIEPMSKx_TypeDef diepmsk;
USB_OTG_DCFG_TypeDef dcfg;
USB_OTG_DCTL_TypeDef dctl;
USB_OTG_GINTSTS_TypeDef gintsts;
uint32_t i = 0;
daintmsk.d32 = 0;
doepmsk.d32 = 0;
diepmsk.d32 = 0;
dcfg.d32 =0;
dctl.d32 = 0;
gintsts.d32 = 0;
/* Clear the Remote Wakeup Signalling */
dctl.b.rmtwkupsig = 1;
USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DCTL, dctl.d32, 0 );
/* Flush the NP Tx FIFO */
OTGD_FS_FlushTxFifo( 0 );
/* clear pending interrupts */
for (i = 0; i < NUM_TX_FIFOS ; i++)
{
USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.DINEPS[i]->DIEPINTx, 0xFF);
USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.DOUTEPS[i]->DOEPINTx, 0xFF);
}
USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.DEV->DAINT, 0xFFFFFFFF );
daintmsk.ep.in = 1;
daintmsk.ep.out = 1;
USB_OTG_WRITE_REG32( &USB_OTG_FS_regs.DEV->DAINTMSK, daintmsk.d32 );
doepmsk.b.setup = 1;
doepmsk.b.b2bsetup = 1;
doepmsk.b.xfercompl = 1;
doepmsk.b.epdis = 1;
USB_OTG_WRITE_REG32( &USB_OTG_FS_regs.DEV->DOEPMSK, doepmsk.d32 );
diepmsk.b.xfercompl = 1;
diepmsk.b.timeout = 1;
diepmsk.b.epdis = 1;
USB_OTG_WRITE_REG32( &USB_OTG_FS_regs.DEV->DIEPMSK, diepmsk.d32 );
/* Reset Device Address */
dcfg.d32 = USB_OTG_READ_REG32( &USB_OTG_FS_regs.DEV->DCFG);
dcfg.b.devaddr = 0;
USB_OTG_WRITE_REG32( &USB_OTG_FS_regs.DEV->DCFG, dcfg.d32);
/* setup EP0 to receive SETUP packets */
PCD_EP0_OutStart();
/* Clear interrupt */
gintsts.d32 = 0;
gintsts.b.usbreset = 1;
USB_OTG_WRITE_REG32 (&USB_OTG_FS_regs.GREGS->GINTSTS, gintsts.d32);
/* Call the user reset function */
OTGD_FS_DEVICE_RESET;
/* Call user function */
INTR_USBRESET_Callback();
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_EnumDone_ISR
* Description : Reads the device status register and set the device speed
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_EnumDone_ISR(void)
{
USB_OTG_GINTSTS_TypeDef gintsts;
USB_OTG_GUSBCFG_TypeDef gusbcfg;
gintsts.d32 = 0;
gusbcfg.d32 = 0;
OTGD_FS_EP0Activate();
/* Set USB turnaround time */
gusbcfg.d32 = USB_OTG_READ_REG32(&USB_OTG_FS_regs.GREGS->GUSBCFG);
gusbcfg.b.usbtrdtim = 9;
USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.GREGS->GUSBCFG, gusbcfg.d32);
/* Call user function */
INTR_ENUMDONE_Callback();
/* Clear interrupt */
gintsts.b.enumdone = 1;
USB_OTG_WRITE_REG32( &USB_OTG_FS_regs.GREGS->GINTSTS, gintsts.d32 );
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_IsoOutDrop_ISR
* Description : Handles the Isochronous Out packet Dropped interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_IsoOutDrop_ISR(void)
{
USB_OTG_GINTSTS_TypeDef gintsts;
gintsts.d32 = 0;
/* Call user function */
INTR_ISOOUTDROP_Callback();
/* Clear interrupt */
gintsts.b.isooutdrop = 1;
USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.GREGS->GINTSTS, gintsts.d32);
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;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_InEP_ISR
* Description : Handles all IN endpoints interrupts.
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_InEP_ISR(void)
{
USB_OTG_DIEPINTx_TypeDef diepint;
uint32_t ep_intr = 0;
uint32_t epnum = 0;
USB_OTG_EP *ep;
uint32_t fifoemptymsk = 0;
diepint.d32 = 0;
ep_intr = OTGD_FS_ReadDevAllInEPItr();
while ( ep_intr )
{
if (ep_intr&0x1) /* In ITR */
{
ep = PCD_GetInEP(epnum);
diepint.d32 = PCD_ReadDevInEP(ep); /* Get In ITR status */
if ( diepint.b.xfercompl )
{
fifoemptymsk = 0x1 << ep->num;
USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DIEPEMPMSK, fifoemptymsk, 0);
/* Clear the Interrupt flag */
CLEAR_IN_EP_INTR(epnum, xfercompl);
if (epnum == 0)
{
/* Call the core IN process for EP0 */
In0_Process();
/* before terminate set Tx & Rx status */
OTG_DEV_SetEPRxStatus(epnum, SaveRState);
OTG_DEV_SetEPTxStatus(epnum, SaveTState);
}
else
{
/* Call the relative IN endpoint callback */
(*pEpInt_IN[epnum -1])();
}
}
if ( diepint.b.timeout )
{
CLEAR_IN_EP_INTR(epnum, timeout);
}
if (diepint.b.intktxfemp)
{
CLEAR_IN_EP_INTR(epnum, intktxfemp);
}
if (diepint.b.inepnakeff)
{
CLEAR_IN_EP_INTR(epnum, inepnakeff);
}
if (diepint.b.txfempty)
{
if ((epnum == 0) || (OTG_DEV_GetEPTxStatus(epnum) == DEV_EP_TX_VALID))
{
PCD_WriteEmptyTxFifo(epnum);
}
CLEAR_IN_EP_INTR(epnum, txfempty);
}
if ( diepint.b.epdis)
{
/* Reset Endpoint Frame ID to 0 */
ep->even_odd_frame = 0;
CLEAR_IN_EP_INTR(epnum, epdis);
}
}
epnum++;
ep_intr >>= 1;
}
/* Call user function */
INTR_INEPINTR_Callback();
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_OutEP_ISR
* Description : Handles all OUT endpoints interrupts.
* Input : None
* Output : None
* Return : Status
*******************************************************************************/
uint32_t OTGD_FS_Handle_OutEP_ISR(void)
{
uint32_t ep_intr = 0;
USB_OTG_DOEPINTx_TypeDef doepint;
uint32_t epnum = 0;
USB_OTG_EP *ep;
doepint.d32 = 0;
/* Read in the device interrupt bits */
ep_intr = OTGD_FS_ReadDevAllOutEp_itr();
while ( ep_intr )
{
if (ep_intr&0x1)
{
/* Get EP pointer */
ep = PCD_GetOutEP(epnum);
doepint.d32 = OTGD_FS_ReadDevOutEP_itr(ep);
/* Transfer complete */
if ( doepint.b.xfercompl )
{
/* Clear the bit in DOEPINTn for this interrupt */
CLEAR_OUT_EP_INTR(epnum, xfercompl);
if (epnum == 0)
{
/* Call the OUT process for the EP0 */
Out0_Process();
}
else
{
(*pEpInt_OUT[epnum-1])();
}
}
/* Endpoint disable */
if ( doepint.b.epdis)
{
/* Clear the bit in DOEPINTn for this interrupt */
CLEAR_OUT_EP_INTR(epnum, epdis);
}
/* Setup Phase Done (control EPs) */
if ( doepint.b.setup )
{
if (epnum == 0)
{
/* Call the SETUP process for the EP0 */
Setup0_Process();
/* Before exit, update the Tx status */
OTG_DEV_SetEPTxStatus(0x80, SaveTState);
}
else
{
/* Other control endpoints */
}
/* Clear the EP Interrupt */
CLEAR_OUT_EP_INTR(epnum, setup);
}
/* Back to back setup received */
if ( doepint.b.b2bsetup )
{
if (epnum == 0)
{
/* Call the SETUP process for the EP0 */
Setup0_Process();
/* Before exit, update the Tx status */
OTG_DEV_SetEPTxStatus(0x80, SaveTState);
}
}
}
epnum++;
ep_intr >>= 1;
}
/* Call user function */
INTR_OUTEPINTR_Callback();
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_IncomplIsoIn_ISR
* Description : Handles the Incomplete Isochronous IN transfer error interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_IncomplIsoIn_ISR(void)
{
USB_OTG_GINTSTS_TypeDef gintsts;
gintsts.d32 = 0;
/* Call user function */
INTR_INCOMPLISOIN_Callback();
/* Clear interrupt */
gintsts.b.incomplisoin = 1;
USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.GREGS->GINTSTS, gintsts.d32);
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_IncomplIsoOut_ISR
* Description : Handles the Incomplete Isochronous OUT transfer error interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_IncomplIsoOut_ISR(void)
{
USB_OTG_GINTSTS_TypeDef gintsts;
gintsts.d32 = 0;
/* Call user function */
INTR_INCOMPLISOOUT_Callback();
/* Clear interrupt */
gintsts.b.outepintr = 1;
USB_OTG_WRITE_REG32(&USB_OTG_FS_regs.GREGS->GINTSTS, gintsts.d32);
return 1;
}
/*******************************************************************************
* Function Name : OTGD_FS_Handle_Wakeup_ISR
* Description : Handles the Wakeup or Remote Wakeup detected interrupt.
* Input : None
* Output : None
* Return : status
*******************************************************************************/
uint32_t OTGD_FS_Handle_Wakeup_ISR(void)
{
USB_OTG_GINTSTS_TypeDef gintsts;
gintsts.d32 = 0;
/* Call user function */
INTR_WKUPINTR_Callback();
/* Clear interrupt */
gintsts.b.wkupintr = 1;
USB_OTG_WRITE_REG32 (&USB_OTG_FS_regs.GREGS->GINTSTS, gintsts.d32);
return 1;
}
/*******************************************************************************
* Function Name : PCD_ReadDevInEP
* Description : Reads all the Endpoints flags.
* Input : None
* Output : None
* Return : Status
*******************************************************************************/
static uint32_t PCD_ReadDevInEP( USB_OTG_EP *ep)
{
uint32_t v = 0, msk = 0, emp=0;
msk = USB_OTG_READ_REG32(&USB_OTG_FS_regs.DEV->DIEPMSK);
emp = USB_OTG_READ_REG32(&USB_OTG_FS_regs.DEV->DIEPEMPMSK);
msk |= ((emp >> ep->num) & 0x1) << 7;
v = USB_OTG_READ_REG32(&USB_OTG_FS_regs.DINEPS[ep->num]->DIEPINTx) & msk;
return v;
}
/*******************************************************************************
* 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;
}
#endif /* STM32F10X_CL */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/