📄 td1120p.c
字号:
/* Disable OUT EP */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_EN_CLEAR_REG, \
(1 << ep->epNumber));
}
}
/*------------------------------------------------------------------------------
Name : TD1120P_DestroyEp
Purpose : De-initialize the endpoint and de-allocate the EP structure
Arguments : pc - peripheral controller handle
ep - endpoint structure pointer
Returns :
Notes :
-----------------------------------------------------------------------------*/
SctStatus TD1120P_DestroyEp(TdiPeriphController *pc, TdiPeriphEp* ep)
{
if (pc == NULL)
{
PRINTF1(("\nTD1120P_DestroyEp: Invalid handle."));
return SCS_ERROR_INVALID_HANDLE;
}
if (ep == NULL)
{
PRINTF1(("\nTD1120P_DestroyEp: Invalid EP handle."));
return SCS_EP_INVALID;
}
TD1120P_EpDeinitialize(pc, ep);
pc->ep[ep->epNumber] = NULL;
SYS_Free(ep);
return (SCS_SUCCESS);
}
/*------------------------------------------------------------------------------
Name : TD1120P_EpDisable
Purpose : Disable the endpoint
Arguments : pc - peripheral controller handle
ep - endpoint structure pointer
Returns :
Notes :
-----------------------------------------------------------------------------*/
SctStatus TD1120P_EpDisable(TdiPeriphController *pc, TdiPeriphEp* ep)
{
if (pc == NULL)
{
PRINTF1(("\nTD1120P_EpDisable: Invalid handle."));
return SCS_ERROR_INVALID_HANDLE;
}
if (ep == NULL)
{
PRINTF1(("\nTD1120P_EpDisable: Invalid EP handle."));
return SCS_EP_INVALID;
}
if (ep->direction == USB_REQUEST_DIRECTION_IN)
{
/* Disable IN EP */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_EN_CLEAR_REG, \
(1 << ep->epNumber));
}
else
{
/* Disable OUT EP */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_EN_CLEAR_REG, \
(1 << ep->epNumber));
}
return (SCS_SUCCESS);
}
/*------------------------------------------------------------------------------
Name : TD1120P_EpEnable
Purpose : Enable the endpoint
Arguments : pc - peripheral controller handle
ep - endpoint structure pointer
Returns :
Notes :
-----------------------------------------------------------------------------*/
SctStatus TD1120P_EpEnable(TdiPeriphController* pc, TdiPeriphEp* ep)
{
if (pc == NULL)
{
PRINTF1(("\nTD1120P_EpEnable: Invalid handle."));
return SCS_ERROR_INVALID_HANDLE;
}
if (ep == NULL)
{
PRINTF1(("\nTD1120P_EpEnable: Invalid EP handle."));
return SCS_EP_INVALID;
}
if (ep->direction == USB_REQUEST_DIRECTION_IN)
{
/* Enable IN EP */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_EN_SET_REG, \
(1 << ep->epNumber));
}
else
{
/* Enable OUT EP */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_EN_SET_REG, \
(1 << ep->epNumber));
/* Set OUT NAK so that we don't receive anything before the software wants to */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_NAK_SET_REG, \
(1 << ep->epNumber));
}
return (SCS_SUCCESS);
}
/*------------------------------------------------------------------------------
Name : TD1120P_GetEpStatus
Purpose : Get the status of the endpoint specified
Arguments : periphHandle - peripheral controller handle
periphEp - endpoint structure pointer
Returns :
Notes :
-----------------------------------------------------------------------------*/
SctStatus TD1120P_GetEpStatus(TdiPeriphController* pc, TdiPeriphEp* ep)
{
if (pc == NULL)
{
PRINTF1(("\nTD1120P_GetEpStatus: Invalid handle."));
return SCS_ERROR_INVALID_HANDLE;
}
if (ep == NULL)
{
PRINTF1(("\nTD1120P_GetEpStatus: Invalid EP handle."));
return SCS_EP_INVALID;
}
/* Nothing to do for TD1120 */
return (SCS_SUCCESS);
}
/*------------------------------------------------------------------------------
Name : TD1120P_GetFrameNumber
Purpose : Get the status of the endpoint specified
Arguments : pc - peripheral controller handle
frameNumber - frame number
Returns : SctStatus
Notes :
-----------------------------------------------------------------------------*/
SctStatus TD1120P_GetFrameNumber(TdiPeriphController* pc, U32* frameNumber)
{
if (pc == NULL)
{
PRINTF1(("\nTD1120P_GetFrameNumber: Invalid handle."));
return SCS_ERROR_INVALID_HANDLE;
}
*frameNumber = (U32)SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_FRAME_NUM_REG);
return (SCS_SUCCESS);
}
/*------------------------------------------------------------------------------
Name : TD1120_FindBit
Purpose : Get which bit is set
Arguments : regValue - value of the register on which to find non-zero bit
Returns : position of the bit
Notes :
-----------------------------------------------------------------------------*/
U8 TD1120_FindBit(U32 regValue)
{
U8 returnVal;
int ii;
for (ii = 0; ii < 16; ii++)
{
if ((regValue >> ii) & 0x1)
{
returnVal = ii;
break;
}
}
return returnVal;
}
/*------------------------------------------------------------------------------
Name : TD1120P_ClearPrevXfers
Purpose : Cancel the previous transfers on the specified endpoint
Arguments : pc - peripheral controller handle
epNumber - endpoint number
Returns : None
Notes : It's called in the interrupt context so there's no need to disable
interrupt
-----------------------------------------------------------------------------*/
void TD1120P_ClearPrevXfers(TdiPeriphController* pc, U8 epNumber)
{
U32 readRegister;
/* Presuming that the control endpoint will be only endpoint 0 and no other one */
/* Check for any pending incomplete OUT transfers */
readRegister = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_THRSHLD_AVAIL_REG);
if (readRegister)
{
if (epNumber == TD1120_FindBit(readRegister))
{
/* Clear the OUT threshold available interrupt */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_THRSHLD_AVAIL_REG, 1 << epNumber);
}
}
/* Check for any done OUT transfers */
readRegister = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_XFER_RCVD_REG);
if (readRegister)
{
if (epNumber == TD1120_FindBit(readRegister))
{
/* Clear the xfer recved interrupt */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_XFER_RCVD_REG, (1 << epNumber));
}
}
/* Check for any pending IN transfers */
readRegister = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_THRSHLD_AVAIL_REG);
if (readRegister)
{
if (epNumber == TD1120_FindBit(readRegister))
{
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_THRSHLD_AVAIL_REG, (1 << epNumber));
}
}
readRegister = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_XFER_SENT_REG);
if (readRegister)
{
if (epNumber == TD1120_FindBit(readRegister))
{
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_XFER_SENT_REG, (1 << epNumber));
}
}
}
/*------------------------------------------------------------------------------
Name : TD1120P_PeripheralInit
Purpose : TD1120 initialization--physical
Arguments : pc - peripheral controller handle
Returns : None
Notes :
-----------------------------------------------------------------------------*/
void TD1120P_PeripheralInit(TdiPeriphController* pc)
{
pc->controllerResourceAddress = 0;
/* Reset the controller */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_CTRL_SET_REG, TD1120_DEV_CTRL_SOFT_RESET);
/* Enable All Interrupts in FPGA */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_INTR_ENABLES_SET_REG, 0xffff);
/* Enable Read DWord */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_CTRL_SET_REG, TD1120_DEV_CTRL_READ_DWORD_EN);
/* Enable OUT packet count feature */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_CTRL_SET_REG, TD1120_DEV_CTRL_OUT_PKT_EN);
}
/*------------------------------------------------------------------------------
Name : TD1120P_InterruptHandler
Purpose : ISR for the 1120 device.
Arguments : handle - unused parameter
Returns : None.
Notes : None.
------------------------------------------------------------------------------*/
void TD1120P_InterruptHandler(S32 handle)
{
TdiPeriphController* pc = localHandle;
U32 intStatus, i;
U32 readRegister;
U32 readInThreshold = 0, readInSent = 0, readOutThreshold = 0, readOutRx = 0;
U8 epNumber;
SYS_Write1120P_Register(pc->ioBase, TD1120_INTR_ENABLE_CLEAR,
TD1120_INTR_ENABLE_PERIPHERAL);
/* Read the interrupt status register */
intStatus = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_INTR_STATUS_REG);
/* Clear the interrupt status register */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_INTR_CLEAR_REG, intStatus);
/* VBus Interrupt Handler */
if (intStatus & TD1120_DEV_INTR_VBUS_CHANGE)
{
readRegister = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_CTRL_SET_REG);
if (readRegister & TD1120_DEV_CTRL_VBUS)
{
TD1120P_CallEventService(pc, USB_SERVICE_VBUS_CHANGE_EVENT, NULL);
}
else
{
/* Detach the device by disconnecting the resistor on D+ */
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_CTRL_CLEAR_REG, \
TD1120_DEV_CTRL_CONNECT_RESISTOR);
TD1120P_PeripheralInit((TdiPeriphController*)pc);
}
}
/* Some Interrupts Require Additional Work To Process */
if (intStatus & TD1120_DEV_INTR_RESET_STARTED)
{
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_ADDRESS_REG, 0);
}
if (intStatus & TD1120_DEV_INTR_RESET_FINISHED)
{
pc->speed = (SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_CTRL_SET_REG) & \
TD1120_DEV_CTRL_SPEED);
TD1120P_CallEventService(pc, USB_SERVICE_BUS_RESET_EVENT, NULL);
TD1120P_CallEventService(pc, USB_SERVICE_SPEED_DETECTION_EVENT, \
(void*)&pc->speed);
}
if (intStatus & TD1120_DEV_INTR_SUSPEND_DETECTED)
{
TD1120P_GoSuspend((TdiPeriphController*)pc);
}
if (intStatus & TD1120_DEV_INTR_RESUME_DETECTED)
{
TD1120P_GoResume((TdiPeriphController*)pc);
}
if (intStatus & TD1120_DEV_INTR_SOF_DETECTED)
{
pc->isSuspended = SCC_FALSE;
SYS_Write1120P_Register(pc->ioBase, TD1120_DEV_INTR_ENABLES_CLEAR_REG, \
TD1120_DEV_INTR_SOF_DETECTED);
}
/* SETUP Packet Received Handler */
if (intStatus & TD1120_DEV_INTR_SETUP_TKN_RX)
{
/* Determine which Endpoint Received the Setup Packet */
readRegister = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_EP_SETUP_RCVD_REG);
epNumber = TD1120_FindBit(readRegister);
/* Ensure all previous control transfers get cancelled */
TD1120P_ClearPrevXfers((TdiPeriphController *)pc, epNumber);
/* Process new SETUP token */
TD1120P_CallEventService(pc, USB_SERVICE_SETUP_PACKET, (void *)&epNumber);
}
else
{
/* Read all possible IN/OUT interrupt sources */
if (intStatus & TD1120_DEV_INTR_IN_THRSHLD_EMPTIED)
{
readInThreshold = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_THRSHLD_AVAIL_REG);
}
if (intStatus & TD1120_DEV_INTR_IN_XFER_SENT)
{
readInSent = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_EP_IN_XFER_SENT_REG);
}
if (intStatus & TD1120_DEV_INTR_OUT_THRSHLD_FILLED)
{
readOutThreshold = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_THRSHLD_AVAIL_REG);
}
if (intStatus & TD1120_DEV_INTR_OUT_XFER_RX)
{
readOutRx = SYS_Read1120P_Register(pc->ioBase, TD1120_DEV_EP_OUT_XFER_RCVD_REG);
}
/* Check if its control endpoint and if its both IN and OUT interrrupts at the same time */
if (((readInThreshold | readInSent) & 0x1) && ((readOutThreshold | readOutRx) & 0x1))
{
/* Both OUT and IN token interrupts have been notified at the same time.
** Its a control endpoint so we should process the data
** phase before the status phase. So find out of it is a control
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -