This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EDMA access to GPIO IN_DATA register on TMS320C6455

#include <csl_gpio.h>
#include <csl_edma3.h>
#include <csl_edma3Aux.h>
#include <csl_intc.h>
#include <csl_intcAux.h>
#include <stdio.h>
#include <string.h>
#include <cslr_dev.h>
#include <dsk6455.h>
#include <dsk6455_led.h>

volatile Uint8 intrCnt=0;
CSL_Edma3Handle hEdma;

void HandleEDMA_INT(void *arg)
{
    CSL_Edma3CmdIntr regIntr;
    
    intrCnt++;

	regIntr.region = CSL_EDMA3_REGION_GLOBAL;
	regIntr.intr = 0x00000000;
	regIntr.intrh = 0xffffffff;
    CSL_edma3HwControl(hEdma, CSL_EDMA3_CMD_INTRPEND_CLEAR, &regIntr);   
}

void main(void)
{
   Bool gpioEn;

   CSL_Status status;
   
   CSL_GpioObj gpioObj;
   CSL_GpioHandle hGpio;
   CSL_GpioConfig gpioCfg = CSL_GPIO_CONFIG_DEFAULTS;
   CSL_GpioPinConfig pinCfg;
   
   CSL_Edma3Obj edmaObj;
   CSL_Edma3ChannelObj edmaChObj;
   CSL_Edma3ChannelHandle hEdmaCh;
   CSL_Edma3ChannelAttr edmaChAtt;
   CSL_Edma3ParamSetup edmaParamSetup;
   CSL_Edma3ParamHandle hParamSetup;
   CSL_Edma3HwSetup edmaHwSetup;
   CSL_Edma3HwDmaChannelSetup edmaDmaChSetup;
   CSL_Edma3CmdDrae regionAccess;
   CSL_Edma3CmdIntr regionIntr;

   CSL_IntcObj edmaIntcObj;
   CSL_IntcHandle hEdmaIntc;
   CSL_IntcContext intcContext;
   CSL_IntcEventHandlerRecord eventRecord[1];
   CSL_IntcEventHandlerRecord edmaIsr;
   CSL_IntcParam vectId;
   CSL_IntcGlobalEnableState state;

   volatile long int mem;
   long int mem1;

   mem = 0;
   mem1 = 0;
   
   DSK6455_LED_init();

   CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERLOCK, DEV_PERLOCK_LOCKVAL, UNLOCK);

   CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG0, DEV_PERCFG0_GPIOCTL, ENABLE);

   do{
      gpioEn = (Bool) CSL_FEXT(((CSL_DevRegs*)CSL_DEV_REGS)->PERSTAT0, DEV_PERSTAT0_GPIOSTAT);
   }while(gpioEn != TRUE);
   
   status = CSL_edma3Init(NULL);
   if(status != CSL_SOK)
   {
     printf("Errore nell'inizializzazione della libreria API per il modulo EDMA\n");
   }

   intcContext.eventhandlerRecord = eventRecord;
   intcContext.numEvtEntries = 1;
   status = CSL_intcInit(&intcContext);
   if(status != CSL_SOK)
   {
     printf("Errore nell'inizializzazione della libreria API per il controller degli interrupt\n");
   }

   status = CSL_intcGlobalNmiEnable();
   if(status != CSL_SOK)
   {
     printf("Errore nell'abilitazione globale degli interrupt non mascherabili\n");
   }

   status = CSL_intcGlobalEnable(&state);
   if(status != CSL_SOK)
   {
     printf("Errore nell'abilitazione globale degli interrupt\n");
   }

   vectId = CSL_INTC_VECTID_4;
   hEdmaIntc = CSL_intcOpen(&edmaIntcObj, CSL_INTC_EVENTID_EDMA3CC_INT0, &vectId, &status);
   if((hEdmaIntc == NULL) || (status != CSL_SOK))
   {
     printf("Errore nell'associazione dell'evento all'interrupt\n"); 
   }

   hEdma = CSL_edma3Open(&edmaObj, CSL_EDMA3, NULL, &status);
   if((status != CSL_SOK) || (hEdma == NULL))
   {
     printf("Errore nell'istanziazione del modulo Edma\n"); 
   }

   edmaDmaChSetup.paramNum = 0;
   edmaDmaChSetup.que = CSL_EDMA3_QUE_0;
   edmaHwSetup.dmaChaSetup = &edmaDmaChSetup;
   edmaHwSetup.qdmaChaSetup = NULL;
   status = CSL_edma3HwSetup(hEdma, &edmaHwSetup);
   if(status != CSL_SOK)
   {
     printf("Errore nella selezione della coda e del PaRam set per il modulo EDMA\n");
   }

   regionAccess.region = CSL_EDMA3_REGION_0;
   regionAccess.drae = 0xffffffff;
   regionAccess.draeh = 0xffffffff;
   status = CSL_edma3HwControl(hEdma, CSL_EDMA3_CMD_DMAREGION_ENABLE, &regionAccess);
   if(status != CSL_SOK)
   {
     printf("Errore nell'abilitazione della regione 0 per il modulo EDMA\n");
   }

   *((volatile Uint32 *)0x02A01008) = 0xffffffff;    // ECR
   *((volatile Uint32 *)0x02A0100C) = 0xffffffff;    // ECRH
   
   edmaChAtt.chaNum = CSL_EDMA3_CHA_GPINT13;
   edmaChAtt.regionNum = CSL_EDMA3_REGION_0;
   hEdmaCh = CSL_edma3ChannelOpen(&edmaChObj, CSL_EDMA3, &edmaChAtt, &status);
   if((status != CSL_SOK) || (hEdmaCh == NULL))
   {
     printf("Errore nell'istanziazione del canale Edma per l'evento GPINT13\n"); 
   }

   hParamSetup = CSL_edma3GetParamHandle(hEdmaCh, 0, &status); 
   if((status != CSL_SOK) || (hEdmaCh == NULL))
   {
     printf("Errore nell'acquisizione del riferimento al PaRam set per il canale Edma\n"); 
   }

   edmaParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
                                             CSL_EDMA3_TCCH_DIS, \
                                             CSL_EDMA3_ITCINT_DIS, \
                                             CSL_EDMA3_TCINT_EN,\
                                             61,CSL_EDMA3_TCC_NORMAL,\
                                             CSL_EDMA3_FIFOWIDTH_NONE, \
                                             CSL_EDMA3_STATIC_DIS, \
                                             CSL_EDMA3_SYNC_A, \
                                             CSL_EDMA3_ADDRMODE_INCR, \
                                             CSL_EDMA3_ADDRMODE_INCR);
   edmaParamSetup.srcAddr = 0x02b00020;
   edmaParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(4, 1);
   edmaParamSetup.dstAddr = (Uint32)&mem;
   edmaParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(0, 0);
   edmaParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL, 0);
   edmaParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0);
   edmaParamSetup.cCnt = 1;
   status = CSL_edma3ParamSetup(hParamSetup, &edmaParamSetup);
   if(status != CSL_SOK)
   {
     printf("Errore nell'impostazione del PaRam set\n"); 
   }

   status = CSL_edma3HwChannelSetupQue(hEdmaCh, CSL_EDMA3_QUE_0);
   if(status != CSL_SOK)
   {
     printf("Errore nell'associazione della coda al canale\n"); 
   }

   edmaIsr.arg = hEdmaIntc;
   edmaIsr.handler = (CSL_IntcEventHandler)&HandleEDMA_INT;
   status = CSL_intcPlugEventHandler(hEdmaIntc, &edmaIsr);
   if(status != CSL_SOK)
   {
     printf("Errore nell'associazione dell'evento al corrispondente handler\n"); 
   }

   status = CSL_intcHwControl(hEdmaIntc, CSL_INTC_CMD_EVTENABLE, NULL);
   if(status != CSL_SOK)
   {
     printf("Errore nell'abilitazione dell'evento\n");
   }
   
   regionIntr.region = CSL_EDMA3_REGION_0;
   regionIntr.intr = 0x00000000;
   regionIntr.intrh = 0xffffffff;
   status = CSL_edma3HwControl(hEdma, CSL_EDMA3_CMD_INTR_ENABLE, &regionIntr);
   if(status != CSL_SOK)
   {
     printf("Errore nell'abilitazione dell'interrupt interno al DMA\n");
   }

   status = CSL_gpioInit(NULL);
   if(status != CSL_SOK)
   {
     printf("Errore nell'inizializzazione della libreria API per il GPIO\n");
   }

   hGpio = CSL_gpioOpen(&gpioObj, CSL_GPIO, NULL, &status);
   if((status != CSL_SOK) || (hGpio == NULL))
   {
     printf("Errore nell'istanziazione della periferica GPIO\n"); 
   }

   status = CSL_gpioHwSetupRaw(hGpio, &gpioCfg);
   
   status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_BANK_INT_ENABLE, NULL);
   if(status != CSL_SOK)
   {
     printf("Errore nell'abilitazione degli interrupt per il GPIO\n"); 
   }
   
   *((volatile Uint32*) 0x02b00024) = 0x00002000;
   
   pinCfg.pinNum = (CSL_GpioPinNum)13;
   pinCfg.direction = CSL_GPIO_DIR_OUTPUT;
   pinCfg.trigger = CSL_GPIO_TRIG_RISING_EDGE;
   status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_CONFIG_BIT, &pinCfg);
   if(status != CSL_SOK)
   {
     printf("Errore nella configurazione del pin numero 13\n");	 
   }

   status = CSL_edma3HwChannelControl(hEdmaCh, CSL_EDMA3_CMD_CHANNEL_ENABLE, NULL);
   if(status != CSL_SOK)
   {
     printf("Errore nell'abilitazione del canale Edma\n");
   }

   status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_SET_BIT, &(pinCfg.pinNum));
   if(status != CSL_SOK)
   {
     printf("Errore nella transizione 0->1 del pin numero 13\n");	 
   }

   while(1) 
   {
      if(intrCnt == 1)
      {
	   DSK6455_LED_on(0);
	   DSK6455_waitusec(3000000);
	   DSK6455_LED_off(0);
       break;
	  }
       
   }
   
   mem1 = *((long int *)0x02b00020);

   status = CSL_gpioClose(hGpio);

   status = CSL_intcClose(hEdmaIntc);

}

 

Hello everybody,

I was trying to do the following: use a GPIO pin to trigger the EDMA in order to trasfer the content of GPIO IN_DATA register to a variable located somewhere into memory and originally set to 0. I wrote the program code so that when the EDMA transfer is over, the completion interrupt starts the execution of a function that switches on a led for a few seconds; this way I'm sure the EDMA transfer is triggered and ends with success. But the variable that should be set with the content of the GPIO IN_DATA register contains its original value instead. I tried to explicitly assign the IN_DATA content to another variable, and this worked, but I would like to get the same result using the EDMA.

This is part of the code I wrote:

volatile long int mem;  //destination of the EDMA transfer

edmaParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \   //PaRam setting; GPIO pin 13 used to trigger the transfer
                                             CSL_EDMA3_TCCH_DIS, \
                                             CSL_EDMA3_ITCINT_DIS, \
                                             CSL_EDMA3_TCINT_EN,\
                                             61,CSL_EDMA3_TCC_NORMAL,\
                                             CSL_EDMA3_FIFOWIDTH_NONE, \
                                             CSL_EDMA3_STATIC_DIS, \
                                             CSL_EDMA3_SYNC_A, \
                                             CSL_EDMA3_ADDRMODE_INCR, \
                                             CSL_EDMA3_ADDRMODE_INCR);
   edmaParamSetup.srcAddr = 0x02b00020;  //address of the IN_DATA register
   edmaParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(4, 1);
   edmaParamSetup.dstAddr = (Uint32)&mem;
   edmaParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(0, 0);
   edmaParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL, 0);
   edmaParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0);
   edmaParamSetup.cCnt = 1;

  *((volatile Uint32*) 0x02b00024) = 0x00002000;  //set the GPIO pin 13 to trigger at a rising edge
  
   pinCfg.pinNum = (CSL_GpioPinNum)13;
   pinCfg.direction = CSL_GPIO_DIR_OUTPUT;
   pinCfg.trigger = CSL_GPIO_TRIG_RISING_EDGE;
   status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_CONFIG_BIT, &pinCfg);

   status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_SET_BIT, &(pinCfg.pinNum)); //manually trigger the EDMA

 

The full code is available in the file attached to this post.

Anyone could suggest a solution to this problem. Is EDMA failing the access to the register (still performing the transfer)? Are GPIO registers not accessible by EDMA ? Or maybe the destination variable is somehow protected from EDMA write operations?

Regards,

Francesco Annese

  • Francesco Annese,

    It makes me very sad when this problem comes up. When this chip first came out, I ran into your main problem also and it took days for me to figure out what to ask and who to ask to solve it.

    But I will get to the point slowly:

    1. Initializing an empty location to 0 can easily give misleading information. The first thing you change is to set the value at mem to something like 0xBAD0BAD1 then re-run the test. This will tell you if your DMA channel is running and it trying to write to the right place.

    2. [very minor] The comment on the last line of code above is misleading. Usually, "manually trigger the EDMA" means to write 1 to EDMA3.ESRH.b29. In your case, you are manually writing to the GPIO bit which in term causes and event trigger to the EDMA and not a manual trigger to the EDMA.

    3. Even though you are copying from our CSL examples, I recommend that you use two lines for "61,CSL_EDMA3_TCC_NORMAL,". This will make it easier to find the TCC value when you are looking through the list of OPT fields. Also, my preference (for what little that is worth) is to not use the trailing back-slashes \ here; these are needed in #define macro definitions, but they are not needed for cases like this where you are just supplying expressions to the macro in your code - but that is just me.

    4. Take a look in the datasheet SPRS276 (k) starting on page 79. Figure 4-1 shows the four EDMA3 Transfer Controllers (TC) on the upper left connected to the DATA SCR, and the third slave block on the right side is the CONFIG SCR. Now go to page 81 and Figure 4-2 where you will see that the GPIO peripheral module is accessed through the CFG SCR, like most of the other peripherals' registers are. Now go to page 80 and look at Table 4-1, which shows how the several bus masters on the left side are or are not connected to the slaves across the top. In particular, notice which masters cannot access the CONFIG SCR.

    Only TC1 can read or write through the CFG SCR to any of the peripheral registers.

    So, you need to map the DMA channel you are using to TC1. Since the Channel Controller's Queue1 is usually mapped to TC1, this means mapping your DMA channel to Queue1 so it will feed Transfer Requests to TC1. This is the detail that has caused this type of problems many, many times.

    Regards,
    RandyP

     

    If you need more help, please reply back. If this answers the question, please click  Verify Answer  , below.