📄 stm32f_usb.c
字号:
Int32U EpCtrlGet_STAT_RX(volatile pInt32U pReg)
{
Int32U Data = *pReg &( 0x3UL << 12);
return(Data >> 12);
}
/*************************************************************************
* Function Name: EpCtrlSet_DTOG_RX
* Parameters: volatile pInt32U pReg, Int32U Data
*
* Return: none
*
* Description: Set DTOG_RX bit
*
*************************************************************************/
void EpCtrlSet_DTOG_RX(volatile pInt32U pReg, Int32U Data)
{
Data = Data?(*pReg ^ (1UL<<14)):*pReg;
Data &= ~0x3070; // Clear the toggle bits without DTOG_RX (14)
Data |= USB_CTRL_CLEAR_ONLY_MASK;
*pReg = Data;
}
/*************************************************************************
* Function Name: EpCtrlToggle_DTOG_RX
* Parameters: volatile Int16U pReg
*
* Return: none
*
* Description: Toggle DTOG_RX bit
*
*************************************************************************/
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: 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)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// Init variables
UsbEp0Ctrl.EpStatus.Status = UsbSetupPhase;
UsbCoreT9Fun = NULL;
UserCoreConfigure(NULL);
USB_UserFuncRegistered(UserCoreConfigure,UsbUserConfigure);
UsbSetDevState(UsbDevStatusUnknow);
// Reset USB Engine
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USB,ENABLE);
// Init USB Clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB,ENABLE);
// Release reset USB Engine
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USB,DISABLE);
// Enable 48MHz clock
RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
// Force USB Reset & Disable USB interrupts
USB_CNTR = 1;
// GPIO assign to the USB engine
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap1_CAN,ENABLE); // xxx
// Configure PA11, PA12 as USB lines
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Configure PC11 USB connect.
GPIO_WriteBit(GPIOC,GPIO_Pin_11,Bit_RESET);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// USB interrupt connect to NVIC
#if USB_HIGH_PRIORITY_EVENT > 0
NVIC_InitStructure.NVIC_IRQChannel = USB_HP_CAN_TX_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = IntrSlotHi;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif // USB_HIGH_PRIORITY_EVENT > 0
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN_RX0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = IntrSlotLo;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 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;
// Clear USB Reset
USB_CNTR_bit.FRES = 0;
// Exit from suspend
USB_CNTR_bit.ESOFM = 0;
USB_CNTR_bit.RESUME = 0;
USB_CNTR_bit.LPMODE = 0;
USB_CNTR_bit.FSUSP = 0; // Must be 0
// USB_Configure
USB_Configure(FALSE);
// Set Buffer table address
USB_BTABLE = USB_OffsetOfDBT;
// Init Packet memory table
pPacketMemUse = NULL;
// Endpoint Init
USB_UserFuncRegistered((UserFunc_t)UsbCtrlEp,UsbEp0Out);
USB_UserFuncRegistered((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 + -