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

📄 usbdevdma.c

📁 SmartARM2400系列开发板全套资料
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************Copyright (c)****************************************************
**                            Guangzhou ZHIYUAN electronics Co.,LTD.
**                                      
**                                 http://www.embedtools.com
**
**--------------File Info---------------------------------------------------------------------------------
** File name:               usbDevDMA.c
** Latest modified Date:    2008-05-10
** Latest Version:          1.1
** Descriptions:            ZLG_USB2400 Device 软件包DMA层源文件
**
**--------------------------------------------------------------------------------------------------------
** Created by:              ZhengMingyuan
** Created date:            2005-01-06
** Version:                 1.0
** Descriptions:            The original version
**
**--------------------------------------------------------------------------------------------------------
** Modified by:             LingGuilin
** Modified date:           2008-05-10
** Version:                 1.1
** Descriptions:            修改部分代码以符合代码规范v1.2
**
*********************************************************************************************************/

#include 	"config.h"

#if DMA_ENGINE_EN 

/*********************************************************************************************************
** Function name:       __usbDevDMAInitUdcaTable
** Descriptions:        初始化DMA引擎的UDCA头寄存器和UDCA表
** input parameters:    无					
** output parameters:	无
** Returned value:      无
*********************************************************************************************************/
void __usbDevDMAInitUdcaTable (void)
{
	INT32U *pulUDCA = NULL;
	
	USBUDCAH = USB_RAM_ADDRESS;											/*  初始化UDCA头寄存器 			*/
	pulUDCA = (INT32U *)USBUDCAH;										/*  取出UDCA寄存器值			*/

	pulUDCA[2] = (INT32S)DD_ADDRESS_EP02;								/*  建立UDCA表					*/
	pulUDCA[3] = (INT32S)DD_ADDRESS_EP03;
	pulUDCA[4] = (INT32S)DD_ADDRESS_EP04;
	pulUDCA[5] = (INT32S)DD_ADDRESS_EP05;
}

/*********************************************************************************************************
** Function name:       __usbDevDMAGetDDPointer
** Descriptions:        获取端点的DD指针
** input parameters:    ucEpIndex	物理端点索引					
** output parameters:	无
** Returned value:      指向端点DD的指针
*********************************************************************************************************/
DD_DESCRIPTOR *__usbDevDMAGetDDPointer (INT8U ucEpIndex)
{
	INT32U ulDdaddr = 0;
	
	ulDdaddr = DD_BASE_ADDRESS + DD_SIZE * (ucEpIndex - 2);				/*  计算地址					*/

	return (DD_DESCRIPTOR *)((INT32U *)ulDdaddr);						/*  转换指针类型				*/
}

/*********************************************************************************************************
** Function name:       __usbDevDMAInitEndpointDD
** Descriptions:        初始化端点的DD
** input parameters:    ucEpIndex	物理端点索引					
** output parameters:	无
** Returned value:      无
*********************************************************************************************************/
void __usbDevDMAInitEndpointDD (INT8U ucEpIndex)
{
	DD_DESCRIPTOR *pstDD = __usbDevDMAGetDDPointer(ucEpIndex);			/*  取得 DD 指针				*/

	pstDD->next_dd_addr = 0;											/*  清零两个成员				*/
	pstDD->status = 0;

	switch(ucEpIndex) {
		
	case 0x02: 	
	    pstDD->control = (EP1_PACKET_SIZE << 5) + 		 				/*  写端点数据包大小			*/
					   (EP02_DMA_BUFFER_LENGTH << 16);	 				/*  写DMA缓冲区大小		        */
		pstDD->start_addr = DMA_BUFFER_ADDR_EP02;			 			/*  写DMA缓冲区起始地址		    */
		break;
					
	case 0x03:  
	    pstDD->control = (EP1_PACKET_SIZE << 5) + 
					   (EP03_DMA_BUFFER_LENGTH << 16);
		pstDD->start_addr = DMA_BUFFER_ADDR_EP03;
		break;

	case 0x04:  
		pstDD->control = (EP2_PACKET_SIZE << 5) + 
					   (EP04_DMA_BUFFER_LENGTH << 16);
		pstDD->start_addr = DMA_BUFFER_ADDR_EP04;
		break;

	case 0x05: 	
	    pstDD->control = (EP2_PACKET_SIZE << 5) + 
					   (EP05_DMA_BUFFER_LENGTH << 16);
		pstDD->start_addr = DMA_BUFFER_ADDR_EP05;
		break;
					
	default:
	    break;
	    
	}
}

/*********************************************************************************************************
** Function name:       __usbDevDMASetTransLength
** Descriptions:        设置DMA传输长度
** input parameters:    ucEpIndex	物理端点索引
**						ulSetLen	设置传输字节长度					
** output parameters:	无
** Returned value:      设置成功的传输字节长度
*********************************************************************************************************/
INT32U __usbDevDMASetTransLength (INT8U ucEpIndex, INT32U ulSetLen)
{ 
	DD_DESCRIPTOR *pstDD = __usbDevDMAGetDDPointer(ucEpIndex);			/*  取得 DD 指针 				*/

	__usbDevDMAInitEndpointDD(ucEpIndex);								/*  初始化DD 					*/
	
	if (ulSetLen > (pstDD->control >> 16)) {							/*  长度超过本端点DMA缓冲区 	*/
		ulSetLen = pstDD->control >> 16;
	}
	
	pstDD->control &= 0x0000FFFF;
	pstDD->control |= (ulSetLen << 16);									/*  将设置长度写入DD	 		*/

	return ulSetLen;													/*  返回设置成功的字节长度		*/											
}

/*********************************************************************************************************
** Function name:       __usbDMAGetRecLength
** Descriptions:        取得当前DMA传输数据长度
** input parameters:    ucEpIndex	物理端点索引					
** output parameters:	无
** Returned value:      DMA当前已传输字节数
*********************************************************************************************************/
INT32U __usbDevDMAGetRecLength (INT8U ucEpIndex)
{
	DD_DESCRIPTOR *pstDD = __usbDevDMAGetDDPointer(ucEpIndex);			/*  取得 DD 指针 				*/	
	
	return (pstDD->status & 0xFFFF0000) >> 16;							/*  返回长度值					*/
}

/*********************************************************************************************************
** Function name:       usbDevDMAStartIN
** Descriptions:        启动 IN 端点的 DMA 传输
** input parameters:    ucEpIndex	物理端点索引					
** output parameters:	无
** Returned value:      无
*********************************************************************************************************/
void __usbDevDMAStartIN (INT8U ucEpIndex)
{
	
	USBEpDMAEn |= (INT32U)(0x01 << ucEpIndex);							/*  使能该端点的DMA功能			*/

	USBEpIntEn &= (INT32U)(~(0x01 << ucEpIndex));						/*  设置IN端点工作在DMA模式		*/
}

/*********************************************************************************************************
** Function name:       usbDevDMAGetBuffer
** Descriptions:        获取DMA缓冲区首地址
** input parameters:    ucEpIndex	物理端点索引					
** output parameters:	无
** Returned value:      物理端点的缓冲区指针
*********************************************************************************************************/
INT8U* __usbDevDMAGetBuffer (INT8U ucEpIndex)
{
	const INT32U DmaTbl[4] = {DMA_BUFFER_ADDR_EP02, DMA_BUFFER_ADDR_EP03,
							  DMA_BUFFER_ADDR_EP04, DMA_BUFFER_ADDR_EP05};

	return (INT8U *)((INT32U *)DmaTbl[ucEpIndex - 2]);					/*  返回指向DMA缓冲区的指针 	*/
}

/*********************************************************************************************************
** Function name:       __usbDevDMAReadISR
** Descriptions:        DMA模式下,USB 端点接收中断服务程序
** input parameters:    pstUsb:  	USB接收与发送控制结构体指针
**						ucEpIndex:  物理端点号					
** output parameters:	无
** Returned value:      无
*********************************************************************************************************/
void __usbDevDMAReadISR (CTRL_USB *pstUsb, INT8U ucEpIndex)
{
	INT8U *pucDstBuf = NULL;
	INT8U *pucSrcBuf = NULL;
	INT32U ulRecLen  = 0;
	INT32U ulLeftLen = 0;
	
	if (pstUsb->bEpUsed != 0) {											/*  有任务在等待接收     		*/
							   	   					  			 		
		ulLeftLen = pstUsb->len - pstUsb->cnt;   			   			/*  计算未接收字节数     		*/
		pucDstBuf = pstUsb->buff;
		
		if (ulLeftLen > 0) {
		
			pucSrcBuf = __usbDevDMAGetBuffer(ucEpIndex);				/*  DMA接收缓冲区地址    		*/
			
			ulRecLen = __usbDevDMAGetRecLength(ucEpIndex);				/*  收到的字节数 		 		*/	
			
			if (ulLeftLen >= ulRecLen) {
			
				memcpy(pucDstBuf + pstUsb->cnt, pucSrcBuf, ulRecLen);
				pstUsb->cnt = pstUsb->cnt + ulRecLen;		    		/*  累加已读取字节数       		*/
			
			} else {
	
				memcpy(pucDstBuf + pstUsb->cnt, pucSrcBuf, ulLeftLen);	/*  从DMA缓冲区取出数据  		*/
				pstUsb->cnt = pstUsb->cnt + ulLeftLen;		    		/*  累加已读取字节数       		*/ 
			}
		}		

		if (pstUsb->cnt >= pstUsb->len) {								/*  如果接收完毕 		 		*/
																 		
 			OSSemPost(Ctrl_Usb[ucEpIndex - 2].Ep_Sem);
	  	
	  	} else {
			
			USBEpDMAEn |= (INT32U)(0x01 << ucEpIndex);				/*  使能该端点的DMA功能			*/
			
	  		ulLeftLen = pstUsb->len - pstUsb->cnt;						/*  计算未读取字节数			*/
	  		__usbDevDMASetTransLength(ucEpIndex, ulLeftLen);	  		/*  设置要接收的字节长度 		*/
	  	}
	}
}					

/*********************************************************************************************************
** Function name:       __usbDevDMAWriteISR
** Descriptions:        DMA模式下,USB 端点发送中断服务程序
** input parameters:    pstUsb:  	USB接收与发送控制结构体指针
**						ucEpIndex:  物理端点号					
** output parameters:	无
** Returned value:      无
*********************************************************************************************************/
void __usbDevDMAWriteISR (CTRL_USB *pstUsb, INT8U ucEpIndex)
{
	INT8U *pucDstBuf = NULL;
	INT8U *pucSrcBuf = NULL;
	
	INT32U ulLeftLen = 0;
	INT32U ulSetLen  = 0;
	
	if (pstUsb->bEpUsed != 0) {
																   		/*  有任务在等待发送    	  	*/
		if (pstUsb->cnt >= pstUsb->len) {
		
			OSSemPost(Ctrl_Usb[ucEpIndex - 2].Ep_Sem);				   	/*  数据全部发送完成 	  	   	*/
			return;
		}
		
		ulLeftLen = pstUsb->len - pstUsb->cnt;   			   			/*  计算未发送字节数  	   		*/
		
		pucSrcBuf = pstUsb->buff;
		
		if (ulLeftLen > 0) {
		
			pucDstBuf = __usbDevDMAGetBuffer(ucEpIndex);
			ulSetLen = __usbDevDMASetTransLength(ucEpIndex,ulLeftLen);
			
			memcpy(pucDstBuf, pucSrcBuf + pstUsb->cnt, ulSetLen);
			pstUsb->cnt = pstUsb->cnt + ulSetLen;
			
			__usbDevDMAStartIN(ucEpIndex);								/*  启动 IN 端点的 DMA 传输  	*/
		}		
	}
}

/*********************************************************************************************************
** Function name:       __usbDevDMATransferEnd
** Descriptions:        DMA方式端点传输数据结束中断服务程序
** input parameters:    无					
** output parameters:	无
** Returned value:      无
*********************************************************************************************************/
void __usbDevDMATransferEnd (void)
{
	INT8U  ucEpIndex = 0;
	unsigned long ulEpIntState = 0;
	DD_DESCRIPTOR *pstDD = NULL;
		
	ulEpIntState = USBEoTIntSt;											/*  读传输结束中断寄存器        */
	
	for (ucEpIndex = 2; ucEpIndex <= 5; ucEpIndex++) {
	
		if (ulEpIntState & ((INT32U)(0x01 << ucEpIndex))) {
																		/*  端点中断传输结束       		*/
			if ((ucEpIndex % 2) != 0) {
				USBEpIntEn |= (INT32U)(0x01 << ucEpIndex);				/*  重新使能该端点从机中断 	   	*/		
			}
															
			pstDD = __usbDevDMAGetDDPointer(ucEpIndex);
			
			if ((pstDD->status & 0x1F) == DDS_OVER_RUN)	{				/*  DMA错误 				   	*/
				USBEpDMAEn = (INT32U)(0x01 << ucEpIndex); 			    /*  重新使能该端点的DMA功能    	*/ 
			}
			
			if ((pstDD->status & 0x1F) == DDS_NORMAL_COMP) {			/*  DMA正常结束 			  	*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -