⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_drv.c

📁 8032底层驱动部分。因为可以移植 所以单独来拿出来
💻 C
📖 第 1 页 / 共 5 页
字号:

#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 + -