Search by Tags

DMA Channel Assignment

 

Compare with Revision

Subscribe for this article updates

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.

C source code sample

#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);