📄 usb_hw.c
字号:
else
{
RxCount_t RxCount = {0};
// OUT EP
// Disable EP
EpCtrlSet_STAT_RX(pEpCtrlBaseAddr,EP_DISABLED);
// Clear Rx toggle
EpCtrlSet_DTOG_RX(pEpCtrlBaseAddr,0);
// Clear Correct Transfer for reception flag
EpCtrlClr_CTR_RX(pEpCtrlBaseAddr);
// Update EP description table
MaxPacketSizeTmp = pEP_Desc->wMaxPacketSize;
RxCount.BlSizeField = (MaxPacketSizeTmp > 62);
RxCount.NubBlockField = (MaxPacketSizeTmp > 62) ? (MaxPacketSizeTmp>>5)-1:MaxPacketSizeTmp>>1;
WriteEpDTB_AddrRx(pEP->EpSlot,Offset);
WriteEpDTB_CountRx(pEP->EpSlot,RxCount.Count);
// Set EP Kind & enable
switch(pEP->EpType)
{
case UsbEpTransferControl:
EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_CTRL);
EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,0);
// Enable EP
EpCtrlSet_STAT_RX(pEpCtrlBaseAddr,EP_NAK);
break;
case UsbEpTransferIsochronous:
WriteEpDTB_CountTx(pEP->EpSlot,RxCount.Count);
// Disable transmitting (only singe direction is possible)
EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_DISABLED);
WriteEpDTB_AddrTx(pEP->EpSlot,Offset1);
EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_ISO);
EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,0);
// Enable EP
EpCtrlSet_STAT_RX(pEpCtrlBaseAddr,EP_VALID);
break;
case UsbEpTransferBulk:
EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_BULK);
EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,pEP->bDoubleBuffered);
if (pEP->bDoubleBuffered)
{
// EP_BULK_DOUB_BUF
// Disable transmitting (only singe direction is possible)
EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_DISABLED);
WriteEpDTB_CountTx(pEP->EpSlot,RxCount.Count);
WriteEpDTB_AddrTx(pEP->EpSlot,Offset1);
EpCtrlSet_DTOG_TX(pEpCtrlBaseAddr,0);
}
// Enable EP
EpCtrlSet_STAT_RX(pEpCtrlBaseAddr,EP_VALID);
break;
case UsbEpTransferInterrupt:
EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_INTERRUPT);
EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,0);
// Enable EP
EpCtrlSet_STAT_RX(pEpCtrlBaseAddr,EP_VALID);
break;
default:
assert(0);
}
}
}
else
{
if (EpCnfg[EP].pEpCtrl)
{
pEpCtrlBaseAddr = (pInt32U)&USB_EP0R;
pEpCtrlBaseAddr += EpCnfg[EP].EpSlot;
if(EP & 1)
{
// Disable IN EP
EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_DISABLED);
// Clear Correct Transfer for reception flag
EpCtrlClr_CTR_TX(pEpCtrlBaseAddr);
}
else
{
// Disable OUT EP
EpCtrlSet_STAT_RX(pEpCtrlBaseAddr,EP_DISABLED);
// Clear Correct Transfer for reception flag
EpCtrlClr_CTR_RX(pEpCtrlBaseAddr);
}
// release buffer
USB_ReleaseBuffer(EP);
EpCnfg[EP].pEpCtrl = NULL;
}
}
return(USB_OK);
}
/*************************************************************************
* Function Name: USB_SetAdd
* Parameters: Int32U DevAdd - device address between 0 - 127
*
* Return: none
*
* Description: Set device address
*
*************************************************************************/
void USB_SetAdd(Int32U DevAdd)
{
USB_DADDR = DevAdd | 0x80;
}
/*************************************************************************
* Function Name: USB_ConnectRes
* Parameters: Boolean Conn
*
* Return: none
*
* Description: Enable Pull-Up resistor
*
*************************************************************************/
void USB_ConnectRes (Boolean Conn)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_1,((Conn)?Bit_RESET:Bit_SET));
}
/*************************************************************************
* Function Name: USB_Suspend
* Parameters: void
*
* Return: none
*
* Description: Suspend the USB engine
*
*************************************************************************/
static
void USB_Suspend(void)
{
USB_CNTR_bit.FSUSP = 1;
USB_CNTR_bit.LPMODE = 1;
}
#if USB_REMOTE_WAKEUP != 0
/*************************************************************************
* Function Name: USB_WakeUp
* Parameters: none
*
* Return: none
*
* Description: Wake up Usb
*
*************************************************************************/
void USB_WakeUp (void)
{
USB_Resume(USB_RESUME_SOFT_EVENT);
}
#endif // USB_REMOTE_WAKEUP != 0
/*************************************************************************
* Function Name: USB_Resume
* Parameters: UsbResumeEvent_t UsbResumeEvent
*
* Return: none
*
* Description: USB Resume implement
*
*************************************************************************/
static
void USB_Resume (UsbResumeEvent_t UsbResumeEvent)
{
Int32U LineStates;
switch(UsbResumeEvent)
{
case USB_RESUME_SOF_EVENT:
if(DlyCnt)
{
// Waiting 8ms (not take more than 10ms) before release signal to host
if(--DlyCnt == 0)
{
USB_CNTR_bit.ESOFM = 0;
USB_CNTR_bit.RESUME = 0;
USB_CNTR_bit.FSUSP = 0; // Must be 0
}
}
break;
case USB_RESUME_SOFT_EVENT: // resume by USER
USB_CNTR_bit.LPMODE = 0;
DlyCnt = USB_RESUME_DLY;
USB_CNTR_bit.RESUME = 1;
USB_CNTR_bit.ESOFM = 1;
UsbDevSuspendCallback(FALSE);
break;
case USB_RESUME_WAKE_UP_EVENT: // resume by HOST
LineStates = USB_FNR & 0xC000;
if((LineStates == 0x8000) && (LineStates == 0x3000))
{
// noise return to suspend state again
USB_Suspend();
}
else if(LineStates)
{
// wake-up
USB_CNTR_bit.LPMODE = 0;
USB_CNTR_bit.FSUSP = 0; // Must be 0
UsbDevSuspendCallback(FALSE);
}
break;
}
}
/*************************************************************************
* Function Name: USB_GetDevStatus
* Parameters: USB_DevStatusReqType_t Type
*
* Return: Boolean
*
* Description: Return USB device status
*
*************************************************************************/
Boolean USB_GetDevStatus (USB_DevStatusReqType_t Type)
{
switch (Type)
{
case USB_DevConnectStatus:
return(TRUE);
case USB_SuspendStatus:
return(USB_CNTR_bit.FSUSP);
case USB_ResetStatus:
return(USB_CNTR_bit.FRES);
}
return(FALSE);
}
/*************************************************************************
* Function Name: USB_SetStallEP
* Parameters: USB_Endpoint_t EP, Boolean Stall
*
* Return: USB_ErrorCodes_t
*
* Description: The endpoint stall/unstall
*
*************************************************************************/
USB_ErrorCodes_t USB_SetStallEP (USB_Endpoint_t EP, Boolean Stall)
{
if (EpCnfg[EP].pEpCtrl == NULL)
{
return(USB_EP_NOT_VALID);
}
if(Stall)
{
EpCnfg[EP].Status = STALLED;
if(EP & 1)
{
// IN EP
EpCtrlSet_STAT_TX(EpCnfg[EP].pEpCtrl,EP_STALL);
EpCnfg[EP].AvbBuff = EpCnfg[EP].bDoubleBuffered+1;
}
else
{
// OUT EP
EpCtrlSet_STAT_RX(EpCnfg[EP].pEpCtrl,EP_STALL);
EpCnfg[EP].AvbBuff = 0;
}
}
else
{
EpCnfg[EP].Status = NOT_READY;
if(EP & 1)
{
// IN EP
EpCnfg[EP].AvbBuff = EpCnfg[EP].bDoubleBuffered+1;
// reset Data Toggle bit
if (EpCnfg[EP].bDoubleBuffered)
{
EpCtrlSet_DTOG_RX(EpCnfg[EP].pEpCtrl,0);
}
EpCtrlSet_DTOG_TX(EpCnfg[EP].pEpCtrl,0);
EpCtrlSet_STAT_TX(EpCnfg[EP].pEpCtrl,EP_NAK);
}
else
{
// OUT EP
EpCnfg[EP].AvbBuff = 0;
// reset Data Toggle bit
if (EpCnfg[EP].bDoubleBuffered)
{
EpCtrlSet_DTOG_TX(EpCnfg[EP].pEpCtrl,0);
}
EpCtrlSet_DTOG_RX(EpCnfg[EP].pEpCtrl,0);
EpCtrlSet_STAT_RX(EpCnfg[EP].pEpCtrl,EP_VALID);
}
}
return(USB_OK);
}
/*************************************************************************
* Function Name: USB_StallCtrlEP
* Parameters: none
*
* Return: none
*
* Description: Stall both direction of the CTRL EP
*
*************************************************************************/
void USB_StallCtrlEP (void)
{
EpCnfg[CTRL_ENP_IN].AvbBuff = EpCnfg[CTRL_ENP_IN].bDoubleBuffered + 1;
EpCnfg[CTRL_ENP_IN].Status = STALLED;
EpCnfg[CTRL_ENP_OUT].AvbBuff = 0;
EpCnfg[CTRL_ENP_OUT].Status = STALLED;
USB_SetStallEP(CTRL_ENP_IN,TRUE);
USB_SetStallEP(CTRL_ENP_OUT,TRUE);
}
/*************************************************************************
* Function Name: USB_GetStallEP
* Parameters: USB_Endpoint_t EP, pBoolean pStall
*
* Return: USB_ErrorCodes_t
*
* Description: Get stall state of the endpoint
*
*************************************************************************/
USB_ErrorCodes_t USB_GetStallEP (USB_Endpoint_t EP, pBoolean pStall)
{
if(EpCnfg[EP].pEpCtrl == NULL)
{
return(USB_EP_NOT_VALID);
}
*pStall = (EP & 1)?
(EpCtrlGet_STAT_TX(EpCnfg[EP].pEpCtrl) == EP_STALL): // IN EP
(EpCtrlGet_STAT_RX(EpCnfg[EP].pEpCtrl) == EP_STALL); // OUT EP
return (USB_OK);
}
/*************************************************************************
* Function Name: USB_EP_IO
* Parameters: USB_Endpoint_t EndPoint
*
* Return: none
*
* Description: Endpoints IO
*
*************************************************************************/
void USB_EP_IO(USB_Endpoint_t EP)
{
Int32U Data, Count, CountHold;
pInt32U pDst;
pInt32U pSrc;
Boolean CurrentBuffer;
pEpCnfg_t pEP = &EpCnfg[EP];
assert(pEP->pEpCtrl);
if(pEP->Status != BEGIN_SERVICED &&
pEP->Status != NO_SERVICED)
{
return;
}
if(EP & 1)
{
// IN
Count = pEP->Size - pEP->Offset;
while(pEP->AvbBuff)
{
if(Count == 0 && !pEP->bZeroPacket)
{
break;
}
// Set Status
pEP->Status = BEGIN_SERVICED;
// Get data size
if(pEP->bZeroPacketPossible && Count == pEP->MaxSize)
{
pEP->bZeroPacketPossible = 0;
pEP->bZeroPacket = 1;
}
CountHold = Count = MIN(Count,pEP->MaxSize);
if(Count == 0)
{
pEP->bZeroPacket = 0;
}
Int32U Offset = pEP->Offset;
pEP->Offset += Count;
// Write data to SIE buffer
CurrentBuffer = TRUE;
switch (pEP->EpType)
{
case UsbEpTransferControl:
case UsbEpTransferInterrupt:
pDst = (pInt32U)__Offset2Addr_PackMem(ReadEpDTB_AddrTx(pEP->EpSlot));
break;
case UsbEpTransferBulk:
if (!pEP->bDoubleBuffered)
{
pDst = (pInt32U)__Offset2Addr_PackMem(ReadEpDTB_AddrTx(pEP->EpSlot));
}
else
{
if ((CurrentBuffer = (*pEP->pEpCtrl & (1UL << 14)) == 0)) // DTOGRX
{
// Tx Buffer
pDst = (pInt32U)__Offset2Addr_PackMem(ReadEpDTB_AddrTx(pEP->EpSlot));
}
else
{
// Rx Buffer
pDst = (pInt32U)__Offset2Addr_PackMem(ReadEpDTB_AddrRx(pEP->EpSlot));
}
}
break;
case UsbEpTransferIsochronous:
if((CurrentBuffer = (*pEP->pEpCtrl & (1UL << 6)) != 0)) // DTOGTX
{
// Tx Buffer
pDst = (pInt32U)__Offset2Addr_PackMem(ReadEpDTB_AddrTx(pEP->EpSlot));
}
else
{
// Rx Buffer
pDst = (pInt32U)__Offset2Addr_PackMem(ReadEpDTB_AddrRx(pEP->EpSlot));
}
break;
default:
assert(0);
return;
}
while (Count)
{
Data = *(pEP->pBuffer+Offset++);
if (--Count)
{
Data |= (Int32U)(*(pEP->pBuffer+Offset++))<<8;
--Count;
}
*pDst++ = Data;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -