Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.

Programming EDMA without EDMA3LLD package

From Texas Instruments Wiki
Jump to: navigation, search

There have been many queries in trying to understand how to program EDMA3 hardware - a basic knowledge of the hardware peripheral and some basic instructions below should do the trick, and as you will see the task is pretty simple :)

Some assumptions made while writing these steps:

  • User knows which resources he wants to use and program them accordingly. There could be a resource conflict if resources not handled properly,
  • Only DMA channel programming is shown below (QDMA channel can be programmed similarly),
  • Linking and chaining are not shown in these steps, and error conditions are not handled properly, and,
  • User is operating on the global channel specific registers instead of going by the shadow region ones. The shadow region method is recommended in case of a multi-master system.

Steps:

1. EDMA3 Initialization:

  • Initialization of Global registers: Event Queue Priority (QUEPRI), Queue Watermark Threshold Level (QWMTHRA)
  • Clear error registers: Event miss clear registers (EMCR, EMCRH, QEMCR), CC Error register (CCERRCLR). This step makes sure there is no spurious error bit set.
  • For more details refer to the functions: EDMA3_DRV_create() & EDMA3_DRV_open() in EDMA3 LLD

2. Programming DMA Channel:

  • Map the DMA Channel to the PaRAM Set by writing to the DCHMAP register, if it is available.
  • Associate Channel to Event Queue by writing to the DMAQNUM register.
  • Initialize the PaRAM Set with all the required values (like counts, addresses etc). Make sure that the transfer completion interrupt bit is SET in the PaRAM Set OPT field. Without that, user will not be able to check the transfer status.
  • For more details refer to the functions: EDMA3_DRV_requestChannel() & EDMA3_DRV_setPaRAM()

3. Triggering the Transfer and Waiting for Transfer Completion:

  • Trigger the transfer manually by writing to the Event Set Register (ESR); transfer will start immediately.
  • Poll the IPR register to check the transfer status. If the bit is SET, clear it by writing to the ICR register.
  • For more details refer to the functions: EDMA3_DRV_enableTransfer() and EDMA3_DRV_waitAndClearTcc()

Note: In case of error, the corresponding bit will be SET in the EMR register.

Sample C code for demo (for DM648 platform)

/* EDMA register address and definitions */
 
#define EDMA_CC_BASE  	(0x02A00000) /* DM648. Check address for other devices. */
#define DCHMAP0     *((volatile unsigned int *)(EDMA_CC_BASE + 0x0100))
#define DMAQNUM0    *((volatile unsigned int *)(EDMA_CC_BASE + 0x0240))
#define QUEPRI      *((volatile unsigned int *)(EDMA_CC_BASE + 0x0284))
#define EMCR        *((volatile unsigned int *)(EDMA_CC_BASE + 0x0308))
#define EMCRH       *((volatile unsigned int *)(EDMA_CC_BASE + 0x030C))
#define QEMCR       *((volatile unsigned int *)(EDMA_CC_BASE + 0x0314))
#define CCERRCLR    *((volatile unsigned int *)(EDMA_CC_BASE + 0x031C))
#define QWMTHRA     *((volatile unsigned int *)(EDMA_CC_BASE + 0x0620))
#define ESR         *((volatile unsigned int *)(EDMA_CC_BASE + 0x1010))
#define IPR         *((volatile unsigned int *)(EDMA_CC_BASE + 0x1068))
#define ICR         *((volatile unsigned int *)(EDMA_CC_BASE + 0x1070))
 
#define PARAMENTRY0     (0x02A04000) /* DM648. Check address for other devices. */
#define OPT             *((volatile unsigned int *)(PARAMENTRY0 + 0x00))
#define SRC             *((volatile unsigned int *)(PARAMENTRY0 + 0x04))
#define A_B_CNT         *((volatile unsigned int *)(PARAMENTRY0 + 0x08))
#define DST             *((volatile unsigned int *)(PARAMENTRY0 + 0x0C))
#define SRC_DST_BIDX    *((volatile unsigned int *)(PARAMENTRY0 + 0x10))
#define LINK_BCNTRLD    *((volatile unsigned int *)(PARAMENTRY0 + 0x14))
#define SRC_DST_CIDX    *((volatile unsigned int *)(PARAMENTRY0 + 0x18))
#define CCNT            *((volatile unsigned int *)(PARAMENTRY0 + 0x1C))
 
/* Allocate srcBuff and dstBuff. Do a cache flush and cache invalidate,if required. */
static signed char srcBuff[512];
static signed char dstBuff[512];
 
/* Step 1: EDMA initialization */
QUEPRI=0x10;
QWMTHRA =(16<<8u)|(16 & 0xFF);
EMCR =  0xFFFFFFFF;
CCERRCLR = 0xFFFFFFFF;
 
/* Step 2: Programming DMA Channel (and Param set) */
DCHMAP0=0x0;
DMAQNUM0=0x0;
OPT = 0x00100000;  /* only TCINTEN is set */
SRC = (unsigned int)srcBuff;
A_B_CNT = ((1 << 16u) | (512 & 0xFFFFu));    /* ACNT = 512, BCNT = 1 */
DST = (unsigned int)dstBuff;
SRC_DST_BIDX = (512 << 16u) | (512 & 0xFFFFu);    /* SRC_BIDX = 512, DST_BIDX = 512 */
LINK_BCNTRLD = (1 << 16u) | 0xFFFFu;    /* LINK = 0xFFFF, BCNTRLD = 1 */
SRC_DST_CIDX = 0;
CCNT = 1;
 
/* Step 3: Triggering the Transfer and Waiting for Transfer Completion */
ESR = 0x1;
while(((IPR) & 0x1) == 0);
 
/* Transfer has completed, clear the status register. */
ICR=0x01;
 
/* Transfer is complete. Compare the srcBuff and dstBuff */