📄 str91x_usb.c
字号:
*************************************************************************/
void EpCtrlToggle_DTOG_RX(volatile pInt32U pReg)
{
Int32U Data = *pReg | (1UL << 14);
Data &= ~0x3070; // Clear the toggle bits without DTOG_TX (14)
Data |= USB_CTRL_CLEAR_ONLY_MASK;
*pReg = Data;
}
/*************************************************************************
* Function Name: EpCtrlGet_DTOG_RX
* Parameters: volatile pInt32U pReg
*
* Return: Int32U
*
* Description: Get EP DTOG_RX bit (OUT)
*
*************************************************************************/
inline
Int32U EpCtrlGet_DTOG_RX(volatile pInt32U pReg)
{
return(((*pReg & (1UL<<14))?1:0));
}
/*************************************************************************
* Function Name: EpCtrlClr_CTR_RX
* Parameters: volatile pInt32U pReg
*
* Return: none
*
* Description: Clear EP CTR_RX bit (OUT)
*
*************************************************************************/
void EpCtrlClr_CTR_RX(volatile pInt32U pReg)
{
Int32U Data = *pReg;
Data &= ~(USB_CTRL_TOGGLE_MASK | 1UL << 15);
Data |= 1UL << 7; // Set TX_CTR
*pReg = Data;
}
/*************************************************************************
* Function Name: EpCtrlGet_CTR_RX
* Parameters: volatile pInt32U pReg
*
* Return: Int32U
*
* Description: Get EP CTR_RX bit (OUT)
*
*************************************************************************/
inline
Int32U EpCtrlGet_CTR_RX(volatile pInt32U pReg)
{
return(*pReg & (0x1UL << 15)?1:0);
}
/*************************************************************************
* Function Name: WriteEpDTB
* Parameters: EpSlot_t Slot, Int32U Offset, Int32U Data
*
* Return: none
*
* Description: Write to EP Buffer descriptor table
*
*************************************************************************/
static
void WriteEpDTB (EpSlot_t Slot, Int32U Offset, Int32U Data)
{
pInt32U pUSB_BuffDeskTbltt;
Int32U DescTableHold;
pUSB_BuffDeskTbltt = (pInt32U)((Int32U)__segment_begin("USB_PACKET_MEMORY")+(Int32U)USB_OffsetOfDBT);
pUSB_BuffDeskTbltt += (sizeof(USB_BuffDeskTbl_t)/sizeof(Int32U)) * Slot;
switch (Offset)
{
case 0:
DescTableHold = *pUSB_BuffDeskTbltt & ~0xFFFF;
DescTableHold |= Data & 0xFFFF;
*pUSB_BuffDeskTbltt = DescTableHold;
break;
case 2:
DescTableHold = *pUSB_BuffDeskTbltt & 0xFFFF;
DescTableHold |= (Data & 0xFFFF) << 16;
*pUSB_BuffDeskTbltt = DescTableHold;
break;
case 4:
DescTableHold = *(pUSB_BuffDeskTbltt+1) & ~0xFFFF;
DescTableHold |= Data & 0xFFFF;
*(pUSB_BuffDeskTbltt+1) = DescTableHold;
break;
case 6:
DescTableHold = *(pUSB_BuffDeskTbltt+1) & 0xFFFF;
DescTableHold |= (Data & 0xFFFF) << 16;
*(pUSB_BuffDeskTbltt+1) = DescTableHold;
break;
}
}
/*************************************************************************
* Function Name: USB_Init
* Parameters: Int32U IntrSlotHi, Int32U IntrSlotLo,
* CommUserFpnt_t UserCoreConfigure
*
* Return: none
*
* Description: Init USB
*
*************************************************************************/
void USB_Init(Int32U IntrSlotHi, Int32U IntrSlotLo,
CommUserFpnt_t UserCoreConfigure)
{
// Init variables
UsbEp0Ctrl.EpStatus.Status = UsbSetupPhase;
UsbCoreT9Fun = NULL;
UserCoreConfigure(NULL);
USB_UserFuncRegistering(UserCoreConfigure,UsbUserConfigure);
UsbSetDevState(UsbDevStatusUnknow);
// Reset USB Engine
SCU_AHBPeriphReset(__USB,ENABLE);
// Init USB Clock
SCU_AHBPeriphClockConfig(__USB48M,DISABLE);
SCU_AHBPeriphClockConfig(__USB,ENABLE);
// Release reset USB Engine
SCU_AHBPeriphReset(__USB,DISABLE);
#if USB_CONN_CTRL > 0
GPIO_InitTypeDef GPIO_InitStructureConnRes;
// Enable GPIO clocks
SCU_APBPeriphClockConfig(__GPIO7, ENABLE);
// Release GPIO reset
SCU_APBPeriphReset(__GPIO7, DISABLE);
GPIO_InitStructureConnRes.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructureConnRes.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructureConnRes.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructureConnRes.GPIO_Alternate = GPIO_OutputAlt1;
GPIO_InitStructureConnRes.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIO7, &GPIO_InitStructureConnRes);
#endif // USB_CONN_CTRL > 0
// Enable 48MHz clock
#if USB_EXT_CLK > 0
GPIO_InitTypeDef GPIO_InitStructureExClk;
// Enable GPIO clocks
SCU_APBPeriphClockConfig(__GPIO2, ENABLE);
// Release GPIO reset
SCU_APBPeriphReset(__GPIO2, DISABLE);
GPIO_InitStructureExClk.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructureExClk.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructureExClk.GPIO_Alternate = GPIO_InputAlt1;
GPIO_InitStructureExClk.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIO2, &GPIO_InitStructureExClk);
SCU_USBCLKConfig(SCU_USBCLK_EXT);
#else
if(SCU_GetMCLKFreqValue() > 48000)
{
SCU_USBCLKConfig(SCU_USBCLK_MCLK2);
}
else
{
SCU_USBCLKConfig(SCU_USBCLK_MCLK);
}
#endif // USB_EXT_CLK > 0
// Force USB Reset & Disable USB interrupts
USB_CNTR = 1;
SCU_AHBPeriphClockConfig(__USB48M,ENABLE);
// USB interrupt connect to VIC
#if USB_HIGH_PRIORITY_EVENT > 0
VIC_Config(USBHP_ITLine, VIC_IRQ, IntrSlotHi);
VIC_ITCmd(USBHP_ITLine, ENABLE);
#endif // USB_HIGH_PRIORITY_EVENT > 0
VIC_Config(USBLP_ITLine, VIC_IRQ, IntrSlotLo);
VIC_ITCmd(USBLP_ITLine, ENABLE);
// Disconnect device
USB_ConnectRes(FALSE);
// Init controls endpoints
USB_HwReset();
// Clear spurious pending interrupt
USB_ISTR = 0;
// Enable Device interrupts
USB_CNTR = bmCTRM | bmRESETM | bmSUSPM | bmWKUPM |
(USB_SOF_EVENT ? bmSOFM : 0) |
(USB_ERROR_EVENT ? bmERRM : 0) |
( USB_DOVR_EVENT ? bmDOVRM : 0) ;
}
/*************************************************************************
* Function Name: USB_HwReset
* Parameters: none
*
* Return: none
*
* Description: Reset Usb engine
*
*************************************************************************/
void USB_HwReset (void)
{
Int32U Count;
for(Count = 0; Count < ENP_MAX_NUMB; Count++)
{
EpInfo[Count].pEpCtrl = NULL;
}
// Free entire USB packet memory
for (Count = 0; Count < EP_MAX_SLOTS*2; Count++)
{
PacketMemBuff[Count].Size = 0;
}
// Resume delay counter
DlyCnt = 0;
// Filter disabled
// Clear USB Reset
USB_CNTR_bit.FRES = 0;
// Exit from suspend
USB_CNTR_bit.ESOFM = 0;
USB_CNTR_bit.RESUME = 0;
USB_CNTR_bit.LP_MODE = 0;
USB_CNTR_bit.FSUSP = 0; // Must be 0
// USB_Configure
USB_Configure(FALSE);
// Set Buffer table address
USB_BTABLE = USB_OffsetOfDBT;
pUSB_BuffDeskTbl = (pInt16U)((Int32U)__segment_begin("USB_PACKET_MEMORY") + USB_OffsetOfDBT);
// Init Packet memory table
pPacketMemUse = NULL;
// Endpoint Init
USB_UserFuncRegistering((UserFunc_t)UsbCtrlEp,UsbEp0Out);
USB_UserFuncRegistering((UserFunc_t)UsbCtrlEp,UsbEp0In);
USB_RealizeEp(CTRL_ENP_IN,Ep0MaxSize,EP_CTRL,EP_SLOT0);
// Set address 0
USB_SetDefAdd();
}
/*************************************************************************
* Function Name: UsbMalloc
* Parameters: none
*
* Return: void *
*
* Description: Return address of free element of the PacketMemBuff massive
*
*************************************************************************/
static
void * UsbMalloc(void)
{
Int32U Count;
for (Count = 0; Count < EP_MAX_SLOTS*2; Count++)
{
if (PacketMemBuff[Count].Size == 0)
{
return(&PacketMemBuff[Count]);
}
}
return(NULL);
}
/*************************************************************************
* Function Name: UsbFree
* Parameters: pPacketMemUse_t pPntr
*
* Return: none
*
* Description: Free element of the PacketMemBuff massive
*
*************************************************************************/
inline static
void UsbFree(pPacketMemUse_t pPntr)
{
pPntr->Size = 0;
}
/*************************************************************************
* Function Name: USB_AllocateBuffer
* Parameters: pInt16U pOffset,Int32U PacketSize,
* USB_Endpoint_t EndPoint
*
* Return: Boolean
*
* Description: Allocate a new buffer
*
*************************************************************************/
static
Boolean USB_AllocateBuffer (pInt16U pOffset,pInt32U pPacketSize,
USB_Endpoint_t EndPoint)
{
pPacketMemUse_t pPacketMem = pPacketMemUse, pPacketMemNext, pPacketMemUseNew;
//Int32U MaxPacketSize = *pPacketSize+4; // for CRC
Int32U MaxPacketSize = *pPacketSize;
if(MaxPacketSize > 62)
{
// coarse-granularity size alignment by 32
MaxPacketSize += (32-1);
MaxPacketSize &= ~(32-1);
}
else
{
// fine-granularity size alignment by 2
MaxPacketSize += (2-1);
MaxPacketSize &= ~(2-1);
}
*pOffset = 0;
// Finding free memory block from the USB packet memory
while(pPacketMem != NULL)
{
*pOffset = pPacketMem->Start + pPacketMem->Size;
// Offset alignment by 4
*pOffset += (4-1);
*pOffset &= ~(4-1);
pPacketMemNext = pPacketMem->pNext;
if((pPacketMem->pNext == NULL) ||
(pPacketMemNext->Start >= *pOffset + MaxPacketSize))
{
break;
}
pPacketMem = pPacketMem->pNext;
}
// Is block find?
if((*pOffset + MaxPacketSize) >=
(((Int32U)__segment_size("USB_PACKET_MEMORY") -
sizeof(USB_BuffDeskTbl_t) * (MaxIndOfRealizeEp+1))&~7))
{
// Not enough space in the USB packet memory
return(FALSE);
}
pPacketMemUseNew = UsbMalloc();
if(pPacketMemUseNew == NULL)
{
// too many point are realized
return(FALSE);
}
if(pPacketMemUse == NULL)
{
pPacketMemUse = pPacketMemUseNew;
pPacketMemUse->pNext = NULL;
}
else
{
pPacketMemUseNew->pNext = pPacketMem->pNext;
pPacketMem->pNext = pPacketMemUseNew;
}
pPacketMemUseNew->RpAddr = EndPoint;
pPacketMemUseNew->Start = *pOffset;
pPacketMemUseNew->Size = MaxPacketSize;
*pPacketSize = MaxPacketSize;
return(TRUE);
}
/*************************************************************************
* Function Name: USB_ReleaseBuffer
* Parameters: USB_Endpoint_t EndPoint
*
* Return: none
*
* Description: Release the buffer/s
*
*************************************************************************/
static
void USB_ReleaseBuffer (USB_Endpoint_t EndPoint)
{
pPacketMemUse_t pPacketMem, pPacketMemPrev;
pPacketMem = pPacketMemUse;
while(pPacketMem != NULL)
{
if(pPacketMem->RpAddr == EndPoint)
{
pPacketMemPrev->pNext = pPacketMem->pNext;
UsbFree(pPacketMem);
pPacketMem = pPacketMemPrev->pNext;
}
else
{
pPacketMemPrev = pPacketMem;
pPacketMem = pPacketMem->pNext;
}
if (pPacketMem == NULL)
{
break;
}
}
}
/*************************************************************************
* Function Name: USB_RealizeEp
* Parameters: USB_Endpoint_t EndPoint, Int32U MaxPacketSize,
* EpType_t EpKind, EpSlot_t EpSlot,
*
* Return: USB_ErrorCodes_t
*
* Description: Enable or disable endpoint
*
*************************************************************************/
USB_ErrorCodes_t USB_RealizeEp( USB_Endpoint_t EndPoint, Int32U MaxPacketSize,
EpType_t EpType, EpSlot_t EpSlot)
{
volatile pInt32U pEpCtrlBaseAddr;
Int16U Offset,Offset1;
Int32U MaxPacketSizeTmp;
if (MaxPacketSize)
{
// Allocate packet memory for EP buffer/s
// calculate actual size only for the OUT EPs
MaxPacketSizeTmp = MaxPacketSize;
if(!USB_AllocateBuffer(&Offset,&MaxPacketSizeTmp,EndPoint))
{
return(USB_MEMORY_FULL);
}
if((EpType == EP_ISO) || (EpType == EP_BULK_DOUB_BUF) || (EpType == EP_CTRL))
{
// Allocate packet second buffer
MaxPacketSizeTmp = MaxPacketSize;
if(!USB_AllocateBuffer(&Offset1,&MaxPacketSizeTmp,EndPoint))
{
// release buffer
USB_ReleaseBuffer(EndPoint);
return(USB_MEMORY_FULL);
}
}
pEpCtrlBaseAddr = (pInt32U)&USB_EP0R;
pEpCtrlBaseAddr += EpSlot;
// Set Ep Address
EpCtrlSet_EA(pEpCtrlBaseAddr,EndPoint >> 1);
if(EpType == EP_CTRL)
{
EndPoint |= 1;
}
sec_pass: // only for control EP, because this type realize both directions
EpInfo[EndPoint].EpType = EpType;
EpInfo[EndPoint].pEpCtrl = pEpCtrlBaseAddr;
EpInfo[EndPoint].EpSlot = EpSlot;
EpInfo[EndPoint].MaxSize = MaxPacketSize;
if(EndPoint & 1)
{
// IN EP
// Disable EP
EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_DISABLED);
// Clear Tx toggle
EpCtrlSet_DTOG_TX(pEpCtrlBaseAddr,0);
// Clear Correct Transfer for transmission flag
EpCtrlClr_CTR_TX(pEpCtrlBaseAddr);
// Update EP description table
WriteEpDTB_AddrTx(EpSlot,Offset);
WriteEpDTB_CountTx(EpSlot,0);
// Set EP Kind & enable
switch(EpType)
{
case EP_BULK_SING_BUFF:
EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_BULK_SING_BUFF);
EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,0);
// Enable EP
EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_NAK);
break;
case EP_CTRL:
EpCtrlSet_EP_TYPE(pEpCtrlBaseAddr,EP_CTRL);
EpCtrlSet_EP_KIND(pEpCtrlBaseAddr,0);
// Enable EP
EpCtrlSet_STAT_TX(pEpCtrlBaseAddr,EP_NAK);
// Realize OUT direction
EndPoint &= ~1;
Offset = Offset1;
goto sec_pass;
case EP_ISO:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -