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.

Compiler/TM4C1290NCZAD: TM4C1290NCZAD

Part Number: TM4C1290NCZAD

Tool/software: TI C/C++ Compiler

The SDRAM via EPI is working Properly using uDMA However I’m note able to get end of DMA interrupt.

I’m using similar code to KrishnanCIT_UDMA_EPI.zip

To enable interrupt I add

EPIIntEnable(EPI0_BASE,(EPI_INT_DMA_TX_DONE|EPI_INT_TXREQ));

EPI Interrupt from FIFO in writing works properly!!!

However, I do not receive interrupts from DMA termination

Only EPI_INT_TXREQ works Properly

  1. EPI_INT_TXREQ interrupt when transmit FIFO is below the trigger level.
  2. EPI_INT_RXREQ interrupt when read FIFO is above the trigger level.
  3. EPI_INT_ERR interrupt when an error condition occurs.
  4. EPI_INT_DMA_TX_DONE interrupt when the transmit DMA completes.
  5. EPI_INT_DMA_RX_DONE interrupt when the read DMA completes.

Please help me to resolve this issues.......

Regards,

 

Haim

  • The EPI is treated as a peripheral, so the following paragraph from the TivaWare Peripheral Driver's Library User's Guide applies.

  • We need an indication to finish reading from slow memory that is outside the CPU through the EPI

    According to the quote from the user guide it is not possible

    It does not make sense to me that it is not possible to get an interrupt to end of DMA

    Do you know how to Implement an Interrupt to at End of reading from  EPI via DMA ?

    Thanks

     

    Haim

  • Let me try to be more clear. In your code you need to enable the EPI interrupts for EPI_DMA_TX_DONE and EPI_DMA_RX_DONE. Line 297 in your code is a good place to add it.

    	 		EPIIntEnable(INT_EPI0, EPI_INT_DMA_TX_DONE | EPI_INT_DMA_RX_DONE | EPI_INT_ERR);
    	 		IntEnable(INT_EPI0);
    

    Then in your EPIIntHandler routine, when you call EPIIntStatus(), check for either EPI_INT_DMA_TX_DONE or EPI_INT_DMA_RX_DONE in the return status. I suggest you use the masked value as now you have enabled these two interrupt sources. 

  • I followed your instructions and still I do not get END DMA interrup

    Attach my files

    Would be happy if you can review the code the

    Thank you

     

    Haim

    EPI_UDMA.c
    //*****************************************************************************
    //
    //*****************************************************************************
    
    
    
    //#include "myDriverLib\pin_macros.h"
    #include "Energia.h"
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_adc.h"
    #include "driverlib/debug.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "driverlib/epi.h"
    #include "driverlib/udma.h"
    #include "driverlib/interrupt.h"
    #include "inc/hw_epi.h"
    #include "myDriverLib/devices/EPI_UDMA.h"
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "pinout.h"
    #include "driverlib/interrupt.h"
    #include "inc/tm4c129xnczad.h"
    
     /*************************************************************************
     Variables
     *************************************************************************/
     uint8_t pui8DMAControlTable[max_array_size];
     uint16_t Array_Reverse_Direction[max_array_size];
     volatile uint32_t DMA_flag ;
     uint32_t DMA_int_Status;
     uint32_t g_ui32SysClock;
     uint32_t channelModeTX;
     uint32_t channelModeRX;
     uint32_t g_ui32EPIErrors;
     uint32_t g_ui32EPIStatus;
     uint32_t g_ui32DMAErrCount;
     uint32_t g_ui32DMAErrCount;
     volatile uint32_t EPIInt_source;;
    // volatile uint32_t INT_FG;
     //volatile uint32_t INT_CNT = 0, PGM_CNT = 0;
     //volatile uint32_t COUNTER = 0;
     //volatile uint32_t INT_Flag = 0;
     //int flag = 0;
    
     //unsigned short *cptr = ((unsigned short *) (0xC0000000));
    
     //#define debugcptr 1
    
    uint32_t loopcnt = 0;
    // unsigned short cval[1024];
    // unsigned int temp = 0;
    //unsigned int int_status;
     volatile uint32_t EPI_int_cnt = 0;
     volatile uint32_t EPI_int_Wcnt = 0;
     volatile uint32_t EPI_int_Rcnt = 0;
     volatile uint32_t EPI_int_Ecnt = 0;
    
     /*************************************************************************
          SDRAM read/write demo program (dma,array,word)
    
       *************************************************************************/
    
      void Write_read_SDRAM_loop (void)
     {
       //setup
       loopcnt = 0;
       unsigned int i;
       uint16_t Sdram_dataw[max_array_size];
       uint16_t Sdram_datar[max_array_size];
       uint8_t error_counter =0;
       uint8_t Status=0  ;
    
         for( i = 0 ; i < 1024   ; i++)
           {
             Sdram_dataw[i]=i;
           }
         error_counter =0;
         Status=0  ;
    
         Status = Sdram_init();
    
    // loop
            while(1)
            {
    
                Status=   sdram_write_array_dma(Sdram_dataw, 0, max_array_size, 0);//write block via DMA
                Status =IntMasterEnable ();
               while( DMA_flag ==DMA_Write_Busy){} //wait to dma end
               Status =  sdram_read_array_dma(Sdram_datar, 0, max_array_size);
               while( DMA_flag ==DMA_Read_Busy){} //wait to dma end
               loopcnt++;
           //     delay(100);
           }
     }
    
     //*****************************************************************************
      //
      // The control table used by the uDMA controller.  This table must be aligned
      // to a 1024 byte boundary.
      //
      //*****************************************************************************
      unsigned char dmaControlTable[1024] __attribute__ ((aligned(1024)));
    
      //******************************************************************************
      void EPIIntHandler(void)
      {
    
    uint32_t intStatus;
    
    // Handle any EPI error IRQ signals.
       //
       intStatus = EPIIntErrorStatus(EPI0_BASE);
       if(intStatus)
       {
           EPI_int_Ecnt++;
       }
       EPIIntErrorClear(EPI0_BASE, intStatus);
          EPIInt_source= EPIIntStatus(EPI0_BASE, false);;//read the masked  EPI interrupt status
          EPI_int_cnt++;
          switch (EPIInt_source)
          {
          case EPI_INT_TXREQ:               EPIIntDisable(EPI0_BASE,EPI_INT_TXREQ); EPI_int_Wcnt++;             break;//interrupt when transmit FIFO is below the trigger level.
          case EPI_INT_RXREQ:               EPIIntDisable(EPI0_BASE,EPI_INT_RXREQ); EPI_int_Rcnt++;             break;//interrupt when read FIFO is above the trigger level.
          case EPI_INT_DMA_TX_DONE:         EPIIntDisable(EPI0_BASE,EPI_INT_DMA_TX_DONE); EPI_int_Wcnt++;       break;//interrupt when the transmit DMA completes.
          case EPI_INT_DMA_RX_DONE:         EPIIntDisable(EPI0_BASE,EPI_INT_DMA_RX_DONE);EPI_int_Rcnt++;        break;//interrupt when the read DMA completes
          case EPI_INT_ERR:                 EPIIntDisable(EPI0_BASE,EPI_INT_ERR); EPI_int_Ecnt++;               break;//interrupt when an error condition occurs.
          default:EPI_int_Ecnt++;
          }
          // Get any DMA related information. Clear the IRQ.
               //
              channelModeTX = uDMAChannelModeGet(UDMA_SEC_CHANNEL_EPI0TX);
              channelModeRX = uDMAChannelModeGet(UDMA_SEC_CHANNEL_EPI0RX);
          intStatus = uDMAIntStatus();
             uDMAIntClear(intStatus);
    
    
    
              if((channelModeTX == UDMA_MODE_STOP))
              {
                EPI_int_Wcnt++;
              }
               if(intStatus && (channelModeRX == UDMA_MODE_STOP))
               {
                  EPI_int_Rcnt++;
               }
    
               DMA_flag=DMA_ready ;
      }
    
    void UDMA_module_on(void)
    
     {
             // The application must allocate the channel control table. This one is a
            // full table for all modes and channels.
            // NOTE: This table must be 1024-byte aligned.
            // Enable the UDMA peripheral
    
            SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    
            // Wait for the UDMA module to be ready.
    
            while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA)){}
            // Enable the uDMA controller.
            uDMAEnable();
            uDMAIntClear(uDMAIntStatus());
    
          //  IntRegister(INT_EPI0, EPIIntHandler);
            EPIIntRegister(EPI0_BASE, EPIIntHandler) ;//enables the handler to be called when the EPI module
            // Set the base for the channel control table.
            uDMAControlBaseSet(&pui8DMAControlTable[0]);
     }
    
    
    
     /*************************************************************************
      SDRAM write by dma
      direction mast be 0
       return  Fail  Success or Busy
      *************************************************************************/
     uint8_t sdram_write_array_dma(uint16_t *sdram_data_ar, uint32_t sdram_address, uint16_t array_size, bool direction)
    
     {
         uint32_t i;
         uint32_t DMA_size=array_size;
         uint32_t DMA_source_address;
         uint32_t DMA_destination_address;
    
             DMA_size=array_size;
             DMA_source_address=sdram_data_ar;
             DMA_destination_address=SDRAM_MAPPING_ADDRESS+(sdram_address<<1);//convert address in byte to word
    
            // No attributes must be set for a software-based transfer. The attributes
            // are cleared by default, but are explicitly cleared here, in case they
            // were set elsewhere.
    
    
            uDMAChannelAttributeDisable(UDMA_SEC_CHANNEL_EPI0TX, (UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK));
            uDMAChannelAttributeEnable(UDMA_SEC_CHANNEL_EPI0TX, UDMA_ATTR_USEBURST);
                  // Now set up the characteristics of the transfer for 16-bit data size, with
            // source and destination increments in bytes, and a byte-wise buffer copy.
            // A bus arbitration size of 16 is used.
             uDMAChannelControlSet((UDMA_SEC_CHANNEL_EPI0TX | UDMA_PRI_SELECT),
                                     (UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_16 |
                                      UDMA_ARB_1024));
    
    
    
            // The transfer buffers and transfer size are now configured. The transfer
            // uses AUTO mode, which means that the transfer automatically runs to
            // completion after the first request.
            //
                  uDMAChannelTransferSet(UDMA_SEC_CHANNEL_EPI0TX|UDMA_PRI_SELECT, UDMA_MODE_BASIC,
                                                      (void*)  DMA_source_address,//source address for the transfer.
                                                      (void*)  DMA_destination_address,//destination address for the transfer.
                                                      DMA_size);//is the number of data items to transfer.
    
            // Finally, the channel must be enabled. Because this is a software-
            // initiated transfer, a request must also be made. The request starts the
            // transfer.
             uDMAChannelEnable(UDMA_SEC_CHANNEL_EPI0TX);
            uDMAChannelRequest(UDMA_SEC_CHANNEL_EPI0TX);
    
         EPIIntEnable(EPI0_BASE,(EPI_INT_DMA_TX_DONE|EPI_INT_DMA_RX_DONE|EPI_INT_ERR));
         IntEnable(INT_EPI0);
         DMA_flag=DMA_Write_Busy ;
         return  Success ;
     }
     /*************************************************************************
      SDRAM read by dma
       direction mast be 0
       return  Fail  Success or Busy
      *************************************************************************/
    
     uint8_t sdram_read_array_dma(uint16_t *sdram_data_ar, uint32_t sdram_address, uint16_t array_size)
     {
         uint32_t i;
            uint32_t RDMA_size=array_size;
            uint32_t RDMA_source_address;
            uint32_t RDMA_destination_address;
    
            bool OutOfMemorySize=0;
    
    
           if (uDMAChannelModeGet(UDMA_SEC_CHANNEL_EPI0RX)==1){return  Busy ;}
           if  (array_size>1024)   { return Fail;}
           if  (((sdram_address+RDMA_size)>SDRAM_END_ADDRESS_16)){ return Fail;}
    
                RDMA_size=array_size;
                RDMA_source_address=SDRAM_MAPPING_ADDRESS+(sdram_address<<1);//convert address in byte to word
                RDMA_destination_address=sdram_data_ar;
                // No attributes must be set for a software-based transfer. The attributes
               // are cleared by default, but are explicitly cleared here, in case they
               // were set elsewhere.
    
    
               uDMAChannelAttributeDisable(UDMA_SEC_CHANNEL_EPI0RX, (UDMA_ATTR_HIGH_PRIORITY ));
               // Now set up the characteristics of the transfer for 16-bit data size, with
               // source and destination increments in bytes, and a byte-wise buffer copy.
               // A bus arbitration size of 16 is used.
                uDMAChannelControlSet((UDMA_SEC_CHANNEL_EPI0RX | UDMA_PRI_SELECT),
                                        (UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_16 |
                                         UDMA_ARB_1024));
    
    
    
               // The transfer buffers and transfer size are now configured. The transfer
               // uses AUTO mode, which means that the transfer automatically runs to
               // completion after the first request.
               //
                     uDMAChannelTransferSet(UDMA_SEC_CHANNEL_EPI0RX|UDMA_PRI_SELECT,
                                                 UDMA_MODE_AUTO,
                                                         (void*)  RDMA_source_address,//source address for the transfer.
                                                         (void*)  RDMA_destination_address,//destination address for the transfer.
                                                         RDMA_size);//is the number of data items to transfer.
    
               // Finally, the channel must be enabled. Because this is a software-
               // initiated transfer, a request must also be made. The request starts the
               // transfer.
                uDMAChannelEnable(UDMA_SEC_CHANNEL_EPI0RX);
               uDMAChannelRequest(UDMA_SEC_CHANNEL_EPI0RX);
    
                   EPIIntEnable(EPI0_BASE,(EPI_INT_DMA_TX_DONE|EPI_INT_DMA_RX_DONE|EPI_INT_ERR));
                   IntEnable(INT_EPI0);
                   DMA_flag=DMA_Write_Busy ;
                   return  Success ;
     }
    
    
    
     /*************************************************************************
       EPI bus init and test pseudo random number to all addresses of the SDRAM
       return  Fail or Success
      *************************************************************************/
    uint8_t Sdram_init (void )
    {
        uint8_t status;
       // Registers an interrupt handler for the uDMA controller.
        SdramConfig_IS42S16400J();
        status= SdramCheck_IS42S16400J();
       UDMA_module_on();
    
        return status;
    }
    /*************************************************************************
       EPI bus init
      *************************************************************************/
    void SdramConfig_IS42S16400J(void)
    {
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPI0);
        // Set the EPI divider.
            EPIDividerSet(EPI0_BASE, 1);
       // Select SDRAM mode.
        EPIModeSet(EPI0_BASE, EPI_MODE_SDRAM);
    
        // ui32Refresh = (tRefresh_us / number_rows) / ext_clock_period
        // tRefresh_us = 16000 (usec. A2 grade, according datasheet)
        // number_rows = 4096 (according datasheet)
        // ext_clock_period = 1 / 60MHz = 0.166 usec
        uint32_t ui32Refresh = 234;
    
        // Configure SDRAM mode.
        EPIConfigSDRAMSet(EPI0_BASE, (EPI_SDRAM_CORE_FREQ_50_100 |
                EPI_SDRAM_FULL_POWER | EPI_SDRAM_SIZE_64MBIT), ui32Refresh);
    
        // Set the address map.
        // It start from a base address of 0x60000000 with a size of 16MB.
        // Although our SDRAM is only 8MB, there is no 8MB aperture option so we pick the next larger size.
        // The addresses are :0x60000000-0x64000000
        EPIAddressMapSet(EPI0_BASE, EPI_ADDR_RAM_SIZE_16MB | EPI_ADDR_RAM_BASE_6);
    
        // Wait for the EPI initialization to complete.
       while(HWREG(EPI0_BASE + EPI_O_STAT) & EPI_STAT_INITSEQ)
        {
        }
        // At this point, the SDRAM is accessible and available for use.
       IntEnable(INT_EPI0);
    }
    /*************************************************************************
       SDRAM test pseudo random number to all addresses of the SDRAM
          return  Fail or Success
      *************************************************************************/
    
    uint8_t SdramCheck_IS42S16400J(void)
    {
        int i;
        uint8_t status;
        uint32_t  max_address =SDRAM_END_ADDRESS_16;//>>1;
        // Write a pseudo random number to all addresses of the SDRAM.
        // Check the validity of the data.
        for( i = 0 ; i < max_address ; i++)
        {
            SDRAM_DOMAIN->h_words[i] =( uint16_t) i;
        }
        for( i = 0 ; i < max_address ; i++)
        {
            if (SDRAM_DOMAIN->h_words[i] !=( uint16_t) i)
            {
                return Fail;
            }
        }
    
        return Success;
    }
    

    EPI_TEST.zip

  • I took the example from your first post and modified it so that it works. Since the EPI was setup with a 16-bit data bus, I changed the array and transfers to be 16-bits wide. Note the use of the function uDMAChannelAssign() in initDma(). When the uDMA has read 256 16-bit half-words, you get an EPI interrupt with the EPI_INT_DMA_RX_DONE bit set in the masked status register. I did not see a TivaWare function to clear that interrupt bit, so I did it with a HWREG write. Then I start another 256 half-word reads. The CCSv8 project is in the attached .zip file.

    /cfs-file/__key/communityserver-discussions-components-files/908/6201.CIT_5F00_UDMA_5F00_EPI.zip