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

📄 dmawince.c

📁 编译环境为PB,或AK,实现27x平台上对DMA的控制,由于270平台上DMA都处在同一个一级中断下,要使用单个的DMA通道,通常也可以在OAL重新映射其中断号,但比较费事,本驱动实现对DMA的管理,
💻 C
📖 第 1 页 / 共 3 页
字号:


    P_XLLP_UINT8_T			pDescriptor0;
    P_XLLP_UINT8_T			pDescriptor1;
    P_XLLP_UINT8_T			pSrcMemory;
    P_XLLP_UINT8_T			pDstMemory;
    P_XLLP_UINT8_T			pExtMemory;

volatile DMA_GLOBALS *pDMAGlobalsThread = NULL;
volatile P_XLLP_DMAC_T	pDmacHandleThread = NULL;


//******************************************************************************
//
// Function Name: DmacTestThread
//
// Description: Test thread which waits for the channel specific test object
//			    to be signaled by the DMA IST, DmacIntrThread.
//  			   
//  
// Input Arguments:
//	
//	                 
// Output Arguments:
//  	
//
// Return Value: 
//	None 
//
//
//*******************************************************************************
INT WINAPI DmacTestThread
(
    void *Channel
)
{
    XLLP_VUINT32_T  tmp_dint;
    XLLP_VUINT32_T  tmpDCSR;
	XLLP_UINT32_T	idxChannel;
	//void *			EventHandle;
	HANDLE			EventHandle;
	XLLP_UINT32_T	i;
	XLLP_UINT32_T	EventData;
	//XLLP_UINT32_T	LastError;
	P_XLLP_INT8_T			pByteSrc;
	P_XLLP_INT8_T			pByteDst;
	_TCHAR			EventName[20];
	HANDLE			hSharedMap;


	idxChannel = (unsigned int)(Channel);
	NKDbgPrintfW(TEXT("idxChannel = 0x%X\r\n"), idxChannel);
	
    RETAILMSG(1,(TEXT("DmacTestThread .....Initialized\r\n")));

	// Compose the name of the channel event for use with CreateEvent(...) below.
	_stprintf(EventName, TEXT("DMA_CHANNEL_%d"), idxChannel);
	NKDbgPrintfW(TEXT("EventName = %s\r\n"), EventName);

	// Memory mapped file for sharing DMA Globals information.
	hSharedMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
									0, sizeof(DMA_GLOBALS), GDE_SHARED_FILENAME );
	// Memory mapped file should exist from setup in GDE_Init() .
	if( ERROR_ALREADY_EXISTS != GetLastError() )
	{
		NKDbgPrintfW(TEXT("DmacTestThread. No existing MemMapFile . \r\n"));
		return FALSE;	// Memory mapped file set failed
	}
	// Get a valid process pointer to the buffer mapped above.
	pDMAGlobalsThread = (DMA_GLOBALS *)MapViewOfFile( hSharedMap, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
	if( !pDMAGlobalsThread )
	{
		NKDbgPrintfW(TEXT("DmacTestThread. MapViewOfFile failed . \r\n"));
		return FALSE;	// Memory mapped file set failed.
	}

	// Map the DMAC registers.
	pDmacHandleThread = NULL;
	pDmacHandleThread = ( P_XLLP_DMAC_T)VirtualAllocCopyPhysical(sizeof(XLLP_DMAC_T),"pDmacHandle",(PVOID)(BULVERDE_BASE_REG_PA_DMAC));
	if (pDmacHandleThread == NULL)
	{				
		NKDbgPrintfW(TEXT("pDmacHandleThread mapping FAILED...\r\n"));
		return 0;  // 
	}
	// Get event handle for this channel. Note that using the numerical event
	// value, pDMAGlobalsThread->hDMAEvent[idxChannel],  stored in the DMA_Globls
	// struture will in general only work for threads that belong to the Device 
	// Manager (DM) process which contains the IST ( DmacIntrThread ) for the DMA Engine.  
	//
	// Drivers or applications that belong to a different process must obtain
	// the handle value by using the event name as shown below. A general solution
	// will always use the event name.
	// Note. For this implementation of WinCE is happens that the event handle is the
	//		 same in each process. There is no guarantee this will continue to be the
	//		 in future implementations.

	//EventHandle = pDMAGlobalsThread->hDMAEvent[idxChannel];
	//NKDbgPrintfW(TEXT("EventHandle in Test Thread = 0x%08X...\r\n"), EventHandle);
	//if (EventHandle == NULL)
	//{
	//	NKDbgPrintfW(TEXT("EventHandle Zero, NOT Initialized...\r\n"));
	//	return 0;  // 
	//}

	EventHandle = CreateEvent(NULL,FALSE,FALSE, EventName);
	NKDbgPrintfW(TEXT("EventHandle in Test Thread = 0x%08X...\r\n"), EventHandle);
	if (EventHandle == NULL)
	{
		NKDbgPrintfW(TEXT("EventHandle (Named) is Zero...\r\n"));
		return 0;  // 
	}

    while (TRUE)
    {
		NKDbgPrintfW(TEXT("DmacTestThread BEFORE WaitFor...\r\n"));
		// The DMA Engine will after processing an interrupt.
	    WaitForSingleObject(EventHandle, INFINITE);
		NKDbgPrintfW(TEXT("DmacTestThread AFTER WaitFor...\r\n"));
		// Get the DCSR value for the channel that interrupted.
		EventData = GetEventData(EventHandle);
		NKDbgPrintfW(TEXT("GetEventData in Test Thread = 0x%08X...\r\n"), EventData);

		tmp_dint = pDmacHandleThread->DINT;	// Get the current interrupt bits.
		tmpDCSR  = pDmacHandleThread->DCSR[idxChannel];

        RETAILMSG(1,(TEXT("DmacIntHandler: chan=%d DINT=0x%08x DCSR=0x%08x DCMD=0x%08x\r\n"), idxChannel, tmp_dint, tmpDCSR, pDmacHandleThread->DDG[idxChannel].DCMD ));

		// Display Source/Destination Data
		pByteSrc = pSrcMemory;
		pByteDst = pDstMemory;
		for(i=0; i<32; i++)
		{
			NKDbgPrintfW(TEXT("\r\n..S-%x = 0x%X....\r\n"),pByteSrc, *pByteSrc);
			NKDbgPrintfW(TEXT("..D-%x = 0x%X....\r\n"),pByteDst, *pByteDst);
			pByteSrc++;
			pByteDst++;
		}
    }
    
    return XLLP_STATUS_SUCCESS;
}

//*******************************************************************************
//
//	Function Name: XllpDmacTest
//
//
//	Description: Setup a simple memory-to-memory transfer with the DMA hardware.
//
//
//*******************************************************************************

#define GDE_VIRT_BUFFER_DESCRIPTOR	GDE_BUFFER_VIRTUAL + 0x2000
#define GDE_VIRT_BUFFER_SRC			GDE_BUFFER_VIRTUAL + 0x2000 + 0x100
#define GDE_VIRT_BUFFER_DST			GDE_BUFFER_VIRTUAL + 0x2000 + 0x300

#define GDE_PHYS_BUFFER_DESCRIPTOR	GDE_BUFFER_PHYSICAL + 0x2000
#define GDE_PHYS_BUFFER_SRC			GDE_BUFFER_PHYSICAL + 0x2000 + 0x100
#define GDE_PHYS_BUFFER_DST			GDE_BUFFER_PHYSICAL + 0x2000 + 0x300

#define	TESTBUF_SIZE		0x100
#define TEST_SIZE_TOTAL		(2 * (sizeof(XLLP_DMAC_DESCRIPTOR_T) + TESTBUF_SIZE))

XLLP_BOOL_T  XllpDmacTest( void )
{

	XLLP_DMAC_CHANNEL_T		Channel;
	P_XLLP_UINT8_T			pbDMATemp;
	P_XLLP_UINT8_T			pbPhyDMATemp;
    PHYSICAL_ADDRESS		PA;
	XLLP_UINT32_T			i;
	P_XLLP_INT8_T			pByteSrc;
	P_XLLP_INT8_T			pByteDst;
	HANDLE					gDmacIntrThread;
    DMA_ADAPTER_OBJECT		Adapter;

    P_XLLP_UINT8_T			pPhyDescriptor0;
    P_XLLP_UINT8_T			pPhyDescriptor1;
    P_XLLP_UINT8_T			pPhySrcMemory;
    P_XLLP_UINT8_T			pPhyDstMemory;
    P_XLLP_UINT8_T			pXlatPhyDescriptor;
    P_XLLP_UINT8_T			pXlatPhyDescriptor1;
    P_XLLP_UINT8_T			pXlatPhySrcMemory;
    P_XLLP_UINT8_T			pXlatPhyDstMemory;

	XLLP_DMAC_COMMAND_T		TestCmd;

	NKDbgPrintfW(TEXT("\r\nDMAC Test...\r\n"));
	
	// Initialize for this Process/Thread.
	if( !XllpDmacInit() )
	{
			NKDbgPrintfW(TEXT("DmacTest-XllpDmacInit failed\r\n"));
			return XLLP_FALSE;
	}

	// Obtain a DMA channel
	NKDbgPrintfW(TEXT("\r\nObtain a channel\r\n"));

	if(XLLP_STATUS_SUCCESS != XllpDmacAllocChannel(  &Channel,  XLLP_DMAC_CHANNEL_PRIORITY_MEDIUM))
	{
			NKDbgPrintfW(TEXT("XllpDmacAllocChannel failed\r\n"));
			return XLLP_FALSE;
	}
	NKDbgPrintfW(TEXT("AllocChannel=%d \r\n"),Channel);

	//  Create a thread that waits for the above Channel event to be signaled.
    gDmacIntrThread = 
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) DmacTestThread, (void *)Channel, 0, NULL);
    if ( gDmacIntrThread == NULL ) 
    {		
		NKDbgPrintfW(TEXT("DTest--Create Test Thread Failed."));
        return (FALSE);
    }

    // Map DMA for a Memory-to-Memory Transfer. NOT needed for Mem2Mem transfers.
	XllpDmacMapDeviceToChannel(
							      XLLP_DMAC_MEM2MEM_MOVE,
								  Channel
						       );

    // Allocate blocks of virtual memory for Descriptors, Source & Destination.
	// DMA_GLOBALS. Not used for this test.

//-->
    // Map both DMA pages into the local address space.
    //
    Adapter.ObjectSize    = sizeof(DMA_ADAPTER_OBJECT);
    Adapter.InterfaceType = Internal;
    Adapter.BusNumber     = 0;

    pbDMATemp =  (P_XLLP_UINT8_T)HalAllocateCommonBuffer(&Adapter, TEST_SIZE_TOTAL , &PA, FALSE);
    if (!pbDMATemp)
    {
        //DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: pbDMATemp failed to allocate DMA buffer(s).\r\n")));
        return(FALSE);
    }

    pbPhyDMATemp = (BYTE *)PA.LowPart;
//--<

	pDescriptor0	= pbDMATemp;
	pPhyDescriptor0	= pbPhyDMATemp;

	pDescriptor1	= pDescriptor0		+ sizeof(XLLP_DMAC_DESCRIPTOR_T);
	pPhyDescriptor1	= pPhyDescriptor0	+ sizeof(XLLP_DMAC_DESCRIPTOR_T);

	pSrcMemory		= pDescriptor1		+ sizeof(XLLP_DMAC_DESCRIPTOR_T);
	pPhySrcMemory	= pPhyDescriptor1	+ sizeof(XLLP_DMAC_DESCRIPTOR_T);

	pDstMemory		= pSrcMemory		+ TESTBUF_SIZE;
	pPhyDstMemory	= pPhySrcMemory		+ TESTBUF_SIZE;




	NKDbgPrintfW(TEXT("pbDMATemp = 0x%X\r\n"), pbDMATemp);

	// Display Virtual and Physical Address Values.

	if (pbDMATemp)
    {
        // Save pointers to the virtual & physical addresses so the driver can access them.

		NKDbgPrintfW(TEXT("pDescriptor0    = 0x%X\r\n"), pDescriptor0);
		NKDbgPrintfW(TEXT("pPhyDescriptor0 = 0x%X\r\n"), pPhyDescriptor0);
		NKDbgPrintfW(TEXT("pDescriptor1    = 0x%X\r\n"), pDescriptor1);
		NKDbgPrintfW(TEXT("pPhyDescriptor1 = 0x%X\r\n"), pPhyDescriptor1);
		NKDbgPrintfW(TEXT("pSrcMemory      = 0x%X\r\n"), pSrcMemory);
		NKDbgPrintfW(TEXT("pPhySrcMemory   = 0x%X\r\n"), pPhySrcMemory);
		NKDbgPrintfW(TEXT("pDstMemory      = 0x%X\r\n"), pDstMemory);
		NKDbgPrintfW(TEXT("pPhyDstMemory   = 0x%X\r\n"), pPhyDstMemory);

		pXlatPhyDescriptor  = (P_XLLP_UINT8_T)XllpDmacGetPhysicalAds(pDescriptor0);
		pXlatPhyDescriptor1 = (P_XLLP_UINT8_T)XllpDmacGetPhysicalAds(pDescriptor1);
		pXlatPhySrcMemory   = (P_XLLP_UINT8_T)XllpDmacGetPhysicalAds(pSrcMemory);
		pXlatPhyDstMemory   = (P_XLLP_UINT8_T)XllpDmacGetPhysicalAds(pDstMemory);

		NKDbgPrintfW(TEXT(" Xlat pDescriptor0 Phy Addr = 0x%X\r\n"), pXlatPhyDescriptor);
		NKDbgPrintfW(TEXT(" Xlat pDescriptor1 Phy Addr = 0x%X\r\n"), pXlatPhyDescriptor1);
		NKDbgPrintfW(TEXT(" Xlat pSrcMemory   Phy Addr = 0x%X\r\n"), pXlatPhySrcMemory);
		NKDbgPrintfW(TEXT(" Xlat pDstMemory   Phy Addr = 0x%X\r\n"), pXlatPhyDstMemory);

		NKDbgPrintfW(TEXT("sizeof(XLLP_DMAC_DESCRIPTOR_T) = 0x%X\r\n"), sizeof(XLLP_DMAC_DESCRIPTOR_T));
    }
	else
	{
		NKDbgPrintfW(TEXT("pbDMATemp VirtualCopy failed\r\n"));
		return XLLP_FALSE;
	}
	// Only one Descriptor for this test, so linking is not needed.

	//  Load data into the descriptor.
	NKDbgPrintfW(TEXT("\r\n...Load the descriptor-Format...\r\n"));

	TestCmd.aLen        = TESTBUF_SIZE - 0x10;
	TestCmd.aWidth      = XLLP_DMAC_WIDTH_0;
	TestCmd.aSize	    = XLLP_DMAC_RESERVED_SIZE;
	TestCmd.aEndian		= XLLP_FALSE;   // Little Endian.
	TestCmd.aFlyByT		= XLLP_FALSE;	// Normal Transfer. No Fly by
	TestCmd.aFlyByS		= XLLP_FALSE;	// Normal Transfer. No Fly by
	TestCmd.aEndIrqEn   = XLLP_TRUE;	// Interrupt when len = 0.
	TestCmd.aStartIrqEn = XLLP_FALSE;	// No Interrupt when Desc is loaded.
	TestCmd.aAddrMode   = XLLP_FALSE;	// Src & Dst contains values for addresses.
	TestCmd.aCmpEn      = XLLP_FALSE;
	TestCmd.aFlowTrg    = XLLP_FALSE;
	TestCmd.aFlowSrc    = XLLP_FALSE;
	TestCmd.aIncTrgAddr = XLLP_TRUE;
	TestCmd.aIncSrcAddr = XLLP_TRUE;

	NKDbgPrintfW(TEXT("\r\n...Load the descriptor-Call...\r\n"));
	
	XllpDmacFillLinkedDesc(
						    (P_XLLP_DMAC_DESCRIPTOR_T)pDescriptor0,
						    (P_XLLP_DMAC_DESCRIPTOR_T)pPhyDescriptor1,
						    //(P_XLLP_DMAC_DESCRIPTOR_T)pXlatPhyDescriptor1,
						    XLLP_DMAC_DESC_STOP_CHANNEL,
						    XLLP_DMAC_DISABLE_DESC_BRANCH,
						    (XLLP_UINT32_T)pPhySrcMemory,
						    (XLLP_UINT32_T)pPhyDstMemory,
						    //(XLLP_UINT32_T)pXlatPhySrcMemory,
						    //(XLLP_UINT32_T)pXlatPhyDstMemory,
						    &TestCmd
						  );

	NKDbgPrintfW(TEXT("\r\n...Load the descriptor-Done...\r\n"));
	
    // Configure Channels to use Descriptors.
	NKDbgPrintfW(TEXT("\r\n...Configure a channel for Descriptors...\r\n"));
	NKDbgPrintfW(TEXT("DCSR[%d]  = 0x%X  ...\r\n"), Channel ,pDmacHandle->DCSR[Channel] );

	XllpDmacCfgChannelDescTransfer(
					    		     (P_XLLP_DMAC_DESCRIPTOR_T)pPhyDescriptor0,
								     Channel,
								   //XLLP_DMAC_DRCMR_T         aDeviceDrcmr,
								     XLLP_DMAC_MEM2MEM_MOVE,
								     XLLP_DMAC_ALIGNMENT_OFF
				     	  		   );

	NKDbgPrintfW(TEXT("DDADR[%d] = 0x%X  ...\r\n"), Channel ,pDmacHandle->DDG[Channel].DDADR);
	NKDbgPrintfW(TEXT("DSADR[%d] = 0x%X  ...\r\n"), Channel ,pDmacHandle->DDG[Channel].DSADR);
	NKDbgPrintfW(TEXT("DTADR[%d] = 0x%X  ...\r\n"), Channel ,pDmacHandle->DDG[Channel].DTADR);
	NKDbgPrintfW(TEXT("DCMD [%d] = 0x%X  ...\r\n"), Channel ,pDmacHandle->DDG[Channel].DCMD);

    // Link Descriptors

	// Only one Descriptor, so linking is not needed.

	// Enable interrupts for the requested channel. Not Needed.

	// Put a Pattern in the Src memory. 

	NKDbgPrintfW(TEXT("\r\n...Initialize Src/Dst memory....\r\n"));

	pByteSrc = pSrcMemory;
	pByteDst = pDstMemory;

	for(i=0; i< 0x100; i++)
	{
		*pByteSrc++ = (XLLP_INT8_T)i;
		*pByteDst++ = 0x5A;
	}

	// Display Source/Destination Data

	pByteSrc = pSrcMemory;
	pByteDst = pDstMemory;
	for(i=0; i<16; i++)
	{
		NKDbgPrintfW(TEXT("\r\n..S-%x = 0x%X....\r\n"),pByteSrc, *pByteSrc);
		NKDbgPrintfW(TEXT("..D-%x = 0x%X....\r\n"),pByteDst, *pByteDst);
		pByteSrc++;
		pByteDst++;
	}

    // Start the Transfer.

	NKDbgPrintfW(TEXT("\r\n...The the M-M Xfer...\r\n"));

	XllpDmacStartTransfer( Channel );

	// Completed 

	NKDbgPrintfW(TEXT("\r\n...Completed DMAC Test...\r\n"));
	
	return XLLP_TRUE;

}
#endif

//=============================================================================
//=========================Working DMA Sample Code ============================
//================================ Stop =======================================
//=============================================================================
//=============================================================================

⌨️ 快捷键说明

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