📄 usb_drv.c
字号:
#if ( defined(MT6228) || defined(MT6229) || defined(MT6230))
/**** Configure generic DMA *****/
if(addr&0x3)
{
/* address is not 4 bytes alignment, use B2W to copy data */
dma_menu.TMOD.burst_mode = KAL_TRUE;
dma_menu.TMOD.cycle = 4;
dma_input.size = DMA_BYTE;
/* must pad length to multiple of 4, this is hardware limit */
/* copy multiple of 4 bytes to FIFO, but still fill BDT as real packet size */
if((length & 0x3) != 0)
{
dma_input.count= length + (4-(length & 0x3));
}
else
{
dma_input.count = length;
}
}
else
{
/*address is 4 byts alignment, use word to copy data */
dma_input.size = DMA_LONG;
/* must pad length to multiple of 4, this is hardware limit */
/* copy multiple of 4 bytes to FIFO, but still fill BDT as real packet size */
if((length & 0x3) != 0)
{
dma_input.count = (length + (4-(length & 0x3)))>>2;
}
else
{
dma_input.count = length>>2;
}
}
/* see if it is multiple of max packet length*/
/* length % 64 */
if(length & 0x3f)
{
g_UsbDrvInfo.dma_pktrdy[ep_num - 1] = KAL_TRUE;
/* the last residue packet size */
g_UsbDrvInfo.dma_pktlength[ep_num - 1] = length&0x3f;
}
else
{
/* do not need one more packet for the residue of 64 bytes*/
g_UsbDrvInfo.dma_res_tx_ep = 0;
g_UsbDrvInfo.dma_pktrdy[ep_num - 1] = KAL_FALSE;
/* the last residue packet size */
g_UsbDrvInfo.dma_pktlength[ep_num - 1] = 0;
}
/* Configure DMA */
DMA_Config_B2W(g_UsbDrvInfo.dma_port[ep_num - 1], &dma_input, KAL_TRUE, dma_menu.TMOD.burst_mode);
/**** Configure Fast mode *****/
/* length/64*/
fm_pkt_num = length >> 6 ;
/* for rx less than 64 bytes packet, pad to receive 64 bytes*/
if((g_UsbDrvInfo.dma_pktrdy[ep_num - 1] ==KAL_TRUE) && (type==USB_OUT_EP_TYPE))
fm_pkt_num += 1;
/* Setup BDT */
if(type==USB_IN_EP_TYPE)
{
/* Must not set own bit, fast mode engine set it automatically.
If own bit is set here, it will cause race condition */
WRITE_EPN_BDT_PID(ep_num, USB_BDT_TX,
(USB_EP_BULK_MAXP << VUSB_BDT_BC_SHIFT) |
(g_UsbDrvInfo.ep_in_data01[ep_num-1]<<VUSB_BDT_DATA01_SHIFT) |
VUSB_BDT_DTS_BIT);
/* Update data toggle flag*/
if(fm_pkt_num&0x1)
g_UsbDrvInfo.ep_in_data01[ep_num-1]^=1;
}
else
{
/* Must not set own bit, fast mode engine set it automatically.
If own bit is set here, it will cause race condition */
WRITE_EPN_BDT_PID(ep_num, USB_BDT_RX,
(USB_EP_BULK_MAXP << VUSB_BDT_BC_SHIFT) |
(g_UsbDrvInfo.ep_out_data01[ep_num-1]<<VUSB_BDT_DATA01_SHIFT) |
VUSB_BDT_DTS_BIT);
/* Update data toggle flag*/
if(fm_pkt_num&0x1)
g_UsbDrvInfo.ep_out_data01[ep_num-1]^=1;
}
/* Select DMA channel of fm engine*/
DRV_WriteReg8(USB_DMA_FM_SELECT, fm_dma_index);
/* Set fm endpoint */
fm_ep = ep_num;
if(type==USB_IN_EP_TYPE)
{
/* TX endpint */
fm_ep |= VUSB_FM_EP_TX;
/* The last packet is not 64 byte */
if(g_UsbDrvInfo.dma_pktrdy[ep_num - 1] ==KAL_TRUE)
{
fm_ep |= VUSB_FM_EP_TX_RES;
}
}
DRV_WriteReg8(USB_FM_ENDPT, fm_ep);
/* Set transfer number*/
DRV_WriteReg8(USB_FM_PKT_NUML, fm_pkt_num&0xff);
DRV_WriteReg8(USB_FM_PKT_NUMH, (fm_pkt_num>>8)&0xff);
DRV_WriteReg8(USB_FM_PKT_CNTL, 0);
DRV_WriteReg8(USB_FM_PKT_CNTH, 0);
/* Enable fast mode only if fm_count > 0*/
if(fm_pkt_num > 0)
{
DRV_WriteReg8(USB_FM_CTL, VUSB_FM_CTL_FMENB);
}
else
{
/* Enable DMA only for tx with fm_count==0 */
/* If TX packet length is less than 64 bytes, this conditionis matched */
g_UsbDrvInfo.fast_mode_tx_ep = 0;
DRV_WriteReg8(USB_DMA_ENB, 1<<fm_dma_index);
}
#else /* MT6228 || MT6229 || MT6230 */
// moduler 4
if ((length&0x3) || (addr&0x3))
{
/* byte transfer */
dma_input.size = DMA_BYTE;
dma_input.count = length;
}
else
{
/* word transfer */
dma_input.size = DMA_LONG;
dma_input.count = length>>2;
}
/* judge if it is mutiple of max packet length*/
if (length % USB_EP_BULK_MAXP)
g_UsbDrvInfo.dma_pktrdy[ep_num - 1] = KAL_TRUE;
else
g_UsbDrvInfo.dma_pktrdy[ep_num - 1] = KAL_FALSE;
/* Configure DMA */
DMA_Config(g_UsbDrvInfo.dma_port[ep_num - 1], &dma_input, KAL_TRUE);
#endif
}
/* get dma running status*/
kal_bool USB_DMA_Get_Run_Status(kal_uint8 ep_num)
{
if(ep_num>MAX_DMA_EP_NUM)
EXT_ASSERT(0, ep_num, 0, 0);
return g_UsbDrvInfo.dma_running[ep_num-1];
}
/* set dma running status*/
void USB_DMA_Set_Run_Status(kal_uint8 ep_num, kal_bool status)
{
if(ep_num>MAX_DMA_EP_NUM)
EXT_ASSERT(0, ep_num, 0, 0);
g_UsbDrvInfo.dma_running[ep_num-1] = status;
}
/************************************************************
polling functions (used for exception log)
*************************************************************/
/*
Add for retrive exception log
If there is data under transmitting, polling it and block until transmit done
*/
void USB_Polling_Transmit_Done(kal_uint8 ep_num)
{
#if ( defined(MT6228) || defined(MT6229) || defined(MT6230))
volatile kal_uint32 delay;
kal_uint32 fm_dma_index;
#endif
/* This function can only be called after exception*/
if(INT_Exception_Enter==0)
EXT_ASSERT(0, INT_Exception_Enter, 0, 0);
/* error case*/
if(g_UsbDrvInfo.dma_port[ep_num - 1] == 0)
return;
/* polling until DMA done */
while (DMA_CheckRunStat(g_UsbDrvInfo.dma_port[ep_num - 1]))
{
/* check if other interrupt received*/
g_UsbDrvInfo.is_unMaskUSB = KAL_FALSE;
USB_HISR();
}
if (DMA_CheckITStat(g_UsbDrvInfo.dma_port[ep_num - 1]))
{
DMA_ACKI(g_UsbDrvInfo.dma_port[ep_num - 1]);
}
#if ( defined(MT6228) || defined(MT6229) || defined(MT6230))
for(delay=0; delay<100; delay++)
{}
/* clear tx dma ep flag */
g_UsbDrvInfo.dma_tx_ep = 0;
if(g_UsbDrvInfo.dma_dir[ep_num-1] == USB_IN_EP_TYPE)
fm_dma_index = VUSB_FM_DMA_TX1;
else
fm_dma_index = VUSB_FM_DMA_RX1;
/* disable DMA*/
DRV_WriteReg8(USB_DMA_DIS, 1<<fm_dma_index);
#endif
/* the last one pkt length not multiple of MAX_PKT_LEN, clear corresponding bits*/
if (g_UsbDrvInfo.dma_pktrdy[ep_num - 1])
{
if(g_UsbDrvInfo.dma_dir[ep_num-1] != USB_IN_EP_TYPE)
EXT_ASSERT(0, g_UsbDrvInfo.dma_dir[ep_num-1], 0, 0);
#if ( defined(MT6228) || defined(MT6229) || defined(MT6230))
/* TX, config the last one packet */
WRITE_EPN_BDT_PID(ep_num, USB_BDT_TX,
(g_UsbDrvInfo.dma_pktlength[ep_num-1] << VUSB_BDT_BC_SHIFT) |
(g_UsbDrvInfo.ep_in_data01[ep_num-1]<<VUSB_BDT_DATA01_SHIFT) |
VUSB_BDT_DTS_BIT | VUSB_BDT_OWNS_BIT);
g_UsbDrvInfo.ep_in_data01[ep_num-1]^=1;
#else
USB_EP_Bulk_In_Ready(ep_num);
#endif
g_UsbDrvInfo.dma_pktrdy[ep_num - 1] = KAL_FALSE;
}
else
{
#if ( defined(MT6228) || defined(MT6229) || defined(MT6230))
/* wait fm done for USB module */
while(g_UsbDrvInfo.fast_mode_tx_ep!=0)
{
g_UsbDrvInfo.is_unMaskUSB = KAL_FALSE;
USB_HISR();
}
#endif
}
#if ( defined(MT6228) || defined(MT6229) || defined(MT6230))
while((USB_Is_EP_Bulk_In_Empty(ep_num)==KAL_FALSE)||(g_UsbDrvInfo.dma_res_tx_ep!=0))
#else
/* polling the last packet*/
while(USB_Is_EP_Bulk_In_Empty(ep_num)==KAL_FALSE)
#endif
{
/* check if other interrupt received*/
g_UsbDrvInfo.is_unMaskUSB = KAL_FALSE;
USB_HISR();
}
g_UsbDrvInfo.dma_running[ep_num-1] = KAL_FALSE;
}
/*
Add for retrive exception log
Config DMA to transmit data and polling until it is done
*/
void USB_Polling_Transmit_Data(kal_uint8 ep_num, USB_EP_TYPE type, kal_uint32 addr, kal_uint32 length,
usb_dma_callback callback, kal_bool callback_upd_run)
{
/* This function can only be called after exception*/
if(INT_Exception_Enter==0)
EXT_ASSERT(0, INT_Exception_Enter, 0, 0);
/* config DMA to transmit data*/
USB_DMA_Setup(ep_num, type, addr, length, callback, callback_upd_run);
/* wait for transmit done*/
USB_Polling_Transmit_Done(ep_num);
}
/*
Add for retrive exception log
Polling if there is any data received or other interrupts
*/
void USB_Polling_Recv_Data(kal_uint8 ep_num)
{
/* This function can only be called after exception*/
if(INT_Exception_Enter==0)
EXT_ASSERT(0, INT_Exception_Enter, 0, 0);
g_UsbDrvInfo.is_unMaskUSB = KAL_FALSE;
USB_HISR();
}
/************************************************************
HISR/LISR interuupt handler
*************************************************************/
void USB_HISR(void)
{
#if ( defined(MT6228) || defined(MT6229) || defined(MT6230))
volatile kal_uint8 IntrStatus;
volatile kal_uint8 FMStatus;
volatile kal_uint8 ErrorStatus;
volatile kal_uint8 PhyStatus;
volatile kal_uint8 direction;
volatile kal_uint8 even_odd;
volatile kal_uint8 ep_num;
volatile kal_bool fast_mode_enable;
usb_dma_callback callback;
fast_mode_enable = (DRV_Reg8(USB_FM_CTL)&VUSB_FM_CTL_FMENB) ? KAL_TRUE : KAL_FALSE;
IntrStatus = DRV_Reg8(USB_INT_STAT);
FMStatus = DRV_Reg8(USB_FM_ERR_STAT);
ErrorStatus = DRV_Reg8(USB_ERR_STAT);
PhyStatus = DRV_Reg8(USB_PHY_EXTRA);
// USB_Ms_Dbg_Trace(OTG_DEVICE_INTR, IntrStatus);
if (PhyStatus & VUSB_PHY_RESUME_INT)
{
DRV_WriteReg8(USB_PHY_EXTRA, PhyStatus & (~VUSB_PHY_SUSPEND));
g_UsbDrvInfo.power_state = USB_STATE_NORMAL;
USB_Resume();
} /* End resume */
if (IntrStatus & VUSB_INT_STAT_RESET)
{
USB_Resume();
USB_Initialize_Drv();
if(g_UsbDrvInfo.reset_hdlr == NULL)
EXT_ASSERT(0, 0, 0, 0);
g_UsbDrvInfo.reset_hdlr();
/* Clear interrupt other than token done*/
DRV_WriteReg8(USB_INT_STAT, IntrStatus);
DRV_WriteReg8(USB_ERR_STAT, ErrorStatus);
#ifndef __OTG_ENABLE__
/* clear interrupt and unmask interrupt if application agree on it */
IRQClearInt(IRQ_USB_CODE);
if (g_UsbDrvInfo.is_unMaskUSB==KAL_TRUE)
IRQUnmask(IRQ_USB_CODE);
#endif
return;
} /* End VUSB_INT_STAT_RESET */
#ifdef __OTG_ENABLE__
if((OTG_Get_State()==OTG_STATE_A_PERIPHERAL) || (OTG_Get_State()==OTG_STATE_B_PERIPHERAL))
{
#endif
/* Ignore VUSB_INT_STAT_TOKEN_DONE in fast mode */
if(((IntrStatus&VUSB_INT_STAT_TOKEN_DONE)&&(fast_mode_enable==KAL_FALSE)) || (FMStatus&VUSB_FM_ERR_STAT_TOKEN_DONE))
{
/* Parse FM status first */
if(FMStatus&VUSB_FM_ERR_STAT_TOKEN_DONE)
{
direction = (DRV_Reg8(USB_FM_ADDITNL_STAT) >> 3) & 0x01;
even_odd = (DRV_Reg8(USB_FM_ADDITNL_STAT) >> 2) & 0x01;
ep_num = (DRV_Reg8(USB_FM_ADDITNL_STAT) >> 4) & 0x0f;
}
else
{
direction = (DRV_Reg8(USB_STAT) >> 3) & 0x01;
even_odd = (DRV_Reg8(USB_STAT) >> 2) & 0x01;
ep_num = (DRV_Reg8(USB_STAT) >> 4) & 0x0f;
}
/* Note that token done should be cleared here in case FM is set during ep handler,
so that intr will move to fm_intr*/
/* Ignore token done in fast mode, so no clear its intr status in FM */
/* First handle VUSB_FM_ERR_STAT_TOKEN_DONE, so do not clear token done intr status */
if((fast_mode_enable==KAL_TRUE) || (FMStatus&VUSB_FM_ERR_STAT_TOKEN_DONE))
{
DRV_Reg8(USB_FM_ERR_STAT) = FMStatus;
}
else
{
DRV_WriteReg8(USB_INT_STAT, (IntrStatus&VUSB_INT_STAT_TOKEN_DONE));
}
if(ep_num==0)
{
g_UsbDrvInfo.ep0_current_dir = direction;
/* Receive*/
if(direction==USB_BDT_RX)
{
/* This one is received, software should handle this packet*/
g_UsbDrvInfo.ep0_rx_even_odd = even_odd;
if((g_UsbDrvInfo.ep0_transaction_type==USB_EP0_TRANS_TX_DATA)
||(g_UsbDrvInfo.ep0_transaction_type==USB_EP0_TRANS_TX_DATA_END))
{
/* Host send status stage before Device expects*/
g_UsbDrvInfo.ep0_transaction_type = USB_EP0_TRANS_END;
}
if(g_UsbDrvInfo.ep0_transaction_type==USB_EP0_TRANS_TX_STATUS)
{
/* Host send status stage and match Device's expection */
WRITE_EP0_BDT_PID(USB_BDT_RX, g_UsbDrvInfo.ep0_rx_even_odd,
(USB_EP0_MAXP << VUSB_BDT_BC_SHIFT) |VUSB_BDT_OWNS_BIT);
g_UsbDrvInfo.ep0_transaction_type = USB_EP0_TRANS_NONE;
}
}
else
{
/* This one is transmitted, software will fill next packet*/
g_UsbDrvInfo.ep0_tx_even_odd = even_odd^1;
if(g_UsbDrvInfo.ep0_transaction_type==USB_EP0_TRANS_RX_DATA)
{
g_UsbDrvInfo.ep0_transaction_type = USB_EP0_TRANS_END;
}
if(g_UsbDrvInfo.ep0_transaction_type==USB_EP0_TRANS_TX_DATA_END)
{
g_UsbDrvInfo.ep0_transaction_type = USB_EP0_TRANS_TX_STATUS;
}
if(g_UsbDrvInfo.ep0_transaction_type==USB_EP0_TRANS_RX_STATUS)
{
g_UsbDrvInfo.ep0_transaction_type = USB_EP0_TRANS_NONE;
}
}
if(g_UsbDrvInfo.ep0_hdlr == NULL)
EXT_ASSERT(0, 0, 0, 0);
g_UsbDrvInfo.ep0_hdlr();
}
else if(direction == USB_BDT_RX) /* Receive*/
{
if(g_UsbDrvInfo.ep_out_hdlr[ep_num-1]!=NULL)
g_UsbDrvInfo.ep_out_hdlr[ep_num -1]();
/* Not handle else because the fm token done may happen here */
}
else /* Send */
{
if(g_UsbDrvInfo.ep_in_hdlr[ep_num-1]!=NULL)
g_UsbDrvInfo.ep_in_hdlr[ep_num -1]();
/* Not handle else because the fm token done may happen here */
if(g_UsbDrvInfo.fast_mode_tx_ep == ep_num)
{
/* This is Fast mode token done intr */
g_UsbDrvInfo.fast_mode_tx_ep = 0;
if((g_UsbDrvInfo.dma_res_tx_ep==0)&&(g_UsbDrvInfo.dma_tx_ep ==0))
{
/* No TX data residue, and DMA callback function has been done */
callback = g_UsbDrvInfo.dma_callback[ep_num-1];
g_UsbDrvInfo.dma_callback[ep_num-1] = NULL;
if(callback!=NULL)
callback();
}
}
else if(g_UsbDrvInfo.dma_res_tx_ep == ep_num)
{
/* This is the last residue packet token done intr*/
g_UsbDrvInfo.dma_res_tx_ep = 0;
callback = g_UsbDrvI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -