The Toradex Windows CE drivers use several DMA channels. In order to prevent multiple usage of one channel, there is a Memory Mapped File that describes the already used channels.The following C source code sample shows the usage of this global variable. You must use the DMA_MUTEX when manipulating the global variable and to release it afterwards. For more details about the Windows CE API calls like CreateMutex or CreateFileMapping, please visit Microsoft's MSDN.
The memory mapped file is available in Toradex Windows CE V3.4 and onwards.
Toradex sells a DMALib that takes care of the channel allocation and lets you allow to easily create descriptors and start transfers. For more information about the lib please contact colibri@toradex.com.
#define DMA_MAX_CHAN 32 #define DMA_USAGE_LEN 32 #define DMA_PERIPH_FREE -1 // dma Mutex settings #define DMA_MUTEX TEXT("DMA_MUTEX") #define DMA_MAX_TIMEOUT 5000 // Memory mapped filename used by the DMALib for interproces sharing of DMA data structures. #define DMA_SHARED_FILENAME (TEXT("ColibriDmaGlobals")) // Memory mapped DMA Globals structure typedef struct { CHAR szDMAChanUsage[DMA_MAX_CHAN][DMA_USAGE_LEN]; DWORD dwDMAChanUsageID[DMA_MAX_CHAN]; } DMA_GLOBALS; static HANDLE g_hSharedMap = NULL; static HANDLE g_hDMAMutex = NULL; static DMA_GLOBALS* pDMAGlobals = NULL; DWORD i; // Memory mapped file for sharing DMA Globals information. g_hSharedMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(DMA_GLOBALS), DMA_SHARED_FILENAME ); if(!g_hSharedMap){ return; // error } if(GetLastError() != ERROR_ALREADY_EXISTS) { // DMA Globals don't exist. nobody is using dma channels so far! you can use every DMA channel return; } // Get a valid process pointer to the memory mapper buffer. pDMAGlobals = (DMA_GLOBALS *)MapViewOfFile(g_hSharedMap, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); if(!pDMAGlobals) { return; // error } g_hDMAMutex = CreateMutex(NULL,FALSE,DMA_MUTEX); if(g_hDMAMutex == NULL){ return; // error } if(WaitForSingleObject(g_hDMAMutex,DMA_MAX_TIMEOUT) == WAIT_TIMEOUT) { return; //error } // now you can search for a free channel and define it used for(i=0; i<DMA_MAX_CHAN; i++) { if(pDMAGlobals->dwDMAChanUsageID[i] == DMA_PERIPH_FREE) break; } if(i==DMA_MAX_CHAN) return; // error: no channels free pDMAGlobals->dwDMAChanUsageID[i] = periph; // set this to the peripheral id number of your dma access memcpy(pDMAGlobals->szDMAChanUsage[i],"YourDMADescrStr",32); // add a string that describes your dma channel (max 32 char) ReleaseMutex(g_hDMAMutex); // Don't forget to call the following APIs when work is done or errors occur UnmapViewOfFile(pDMAGlobals); CloseHandle(g_hSharedMap); CloseHandle(g_hDMAMutex);