eDMA driver

cancel
Showing results for 
Search instead for 
Did you mean: 

eDMA driver

Jump to solution
1,141 Views
Pat
Contributor III

Hi All,

Looking for some guidance on porting my TCD-DMA configuration to the KSDK v2.0 using the eDMA driver API. My code transfer data from buffer to SPI over DMA.

 

static uint32_t SPI_data_patterns[] =
{
   DSPI_PUSHR_PCS0 | DSPI_PUSHR_CTAS(0) | DSPI_PUSHR_CONT | DSPI_PUSHR_TXDATA(0x0ec0),
   DSPI_PUSHR_PCS0 | DSPI_PUSHR_CTAS(0) | DSPI_PUSHR_EOQ  | DSPI_PUSHR_TXDATA(0x0000)
};

 

static uint32_t *p_SPI_data_patterns = SPI_data_patterns;
static uint32_t SPI_data_patterns_size = sizeof(SPI_data_patterns);

 

void test(void)
{
   ...
   /* Load address of source data */
   DMA_0.TCD[16].SADDR.R = p_SPI_data_patterns;
   /* Read 4 bytes per transfer */
   DMA_0.TCD[16].ATTR.B.SSIZE = kEDMA_TransferSize4Bytes;
   /* After transfer, add 4 to src addr */
   DMA_0.TCD[16].SOFF.B.SOFF = 4;
   /* After major loop, reset src addr */
   DMA_0.TCD[16].SLAST.B.SLAST = -SPI_data_patterns_size;
   /* Source modulo feature not used */
   DMA_0.TCD[16].ATTR.B.SMOD = 0;
 
   /* Load address of destination */
   DMA_0.TCD[16].DADDR.B.DADDR = &SPI0.PUSHR.R;
   /* Write 4 bytes per transfer */
   DMA_0.TCD[16].ATTR.B.DSIZE = kEDMA_TransferSize4Bytes;
   /* After transfer, add 0 to dest addr */
   DMA_0.TCD[16].DOFF.B.DOFF = 0;
   /* After major loop, reset dest addr */
   DMA_0.TCD[16].DLASTSGA.B.DLASTSGA = 0;
   /* Destination modulo feature not used */
   DMA_0.TCD[16].ATTR.B.DMOD = 0;
 
   /* Transfer 4 bytes per minor loop */
   DMA_0.TCD[16].NBYTES.MLNO.B.NBYTES = 4;
 
   /* Initialize the begining and current major loop iteration counts */
   DMA_0.TCD[16].BITER.ELINKNO.B.BITER = SPI_data_patterns_size / 4;
   DMA_0.TCD[16].CITER.ELINKNO.B.CITER = SPI_data_patterns_size / 4;
   DMA_0.TCD[16].BITER.ELINKNO.B.ELINK = 0;
   DMA_0.TCD[16].CITER.ELINKNO.B.ELINK = 0;
 
   DMA_0.TCD[16].CSR.B.DREQ         = 1;
   DMA_0.TCD[16].CSR.B.INTHALF      = 0;
   DMA_0.TCD[16].CSR.B.INTMAJOR     = 0;
   DMA_0.TCD[16].CSR.B.MAJORELINK   = 0;
   DMA_0.TCD[16].CSR.B.ESG          = 0
   DMA_0.TCD[16].CSR.B.BWC          = 0;
   DMA_0.TCD[16].CSR.B.START        = 0;
   DMA_0.TCD[16].CSR.B.DONE         = 0;
   DMA_0.TCD[16].CSR.B.ACTIVE       = 0;

 

   /*eDMA request signal for channel 16 is enabled, start DMA/SPI transfer*/
   DMA_0.ERQ.B.ERQ16 = 1U;

...
}   
void my10msISR(void)

{

...

      if (SPI_0.SR.B.EOQF){
         /*clear EOQF, so next frames are TXed by DMA*/
         SPI_0.SR.R = DSPI_SR_EOQF;
         DMA_0.ERQ.B.ERQ16 = 1U;
      }

...
 }

 

Best regards,

Pat

Labels (1)
Tags (2)
1 Solution
338 Views
DavidS
NXP Employee
NXP Employee

Hi Pat,

I do not see a specific EDMA API for modifying the LAST.

I tested below code in the edma scatter gather for frdm-k64f using KSDK_v2.

    EDMA_CreateHandle(&g_EDMA_Handle, DMA0, 0);

#if 1         //DES 1=test, 0=default code

    edma_tcd_t *tcdRegs;

    tcdRegs = (edma_tcd_t *)(&g_EDMA_Handle.base->TCD[g_EDMA_Handle.channel]);

    tcdRegs->SLAST = -4;

#endif

Regards,

David

View solution in original post

5 Replies
338 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Pat,

do you want to develop code for  DMA and SPI module based on SDK2.0? The SDK2.0 has the example for spi plus DMA.

For example, this is the directory of example for DMA and SPI based on K64.

C:\Freescale\SDK2.0_FRDM_K64F\boards\frdmk64f\driver_examples\dspi\edma_transfer\kdsp:

you can download SDK2.0 from the link:

http://www.nxp.com/ksdk

Hope it can help you

BR

XiangJun Rong

0 Kudos
338 Views
Pat
Contributor III

Hi XiangJun,

I already downloaded and saw the examples provided in KSDK2.0 which unfortunately don't match with my working "simple" DMA-SPI Tx tranfer. The TCD configuration is done just one time during initialisation. During runtime I only have to enable the corresponding DMA channel in order to send my data and DMA stop automatically, and waiting for a new activation, and so on.

Anyway, I would like porting my TCD configuration to the KSDK v2.0 using the eDMA driver API. For example, I'm facing a problem when I would like set the SLAST field, it seems that it's not covered by the eDMA API ?!

Best regards,

Pat

0 Kudos
339 Views
DavidS
NXP Employee
NXP Employee

Hi Pat,

I do not see a specific EDMA API for modifying the LAST.

I tested below code in the edma scatter gather for frdm-k64f using KSDK_v2.

    EDMA_CreateHandle(&g_EDMA_Handle, DMA0, 0);

#if 1         //DES 1=test, 0=default code

    edma_tcd_t *tcdRegs;

    tcdRegs = (edma_tcd_t *)(&g_EDMA_Handle.base->TCD[g_EDMA_Handle.channel]);

    tcdRegs->SLAST = -4;

#endif

Regards,

David

View solution in original post

338 Views
Pat
Contributor III

Hi David,

Thank you for the workaround. I was wondering if it's the rignt way to set the TCD  because I have to call EDMA_TcdDisableInterrupts() in order to clear the INTMAJOR previously enabled by EDMA_SubmitTransfer() ?

    edma_handle_t g_EDMA_Handle;


    EDMA_GetDefaultConfig(&userConfig);
    EDMA_Init(DMA0, &userConfig);
    EDMA_CreateHandle(&g_EDMA_Handle, DMA0, 0);

    {
        edma_tcd_t *tcdRegs;
        tcdRegs = (edma_tcd_t *)(&g_EDMA_Handle.base->TCD[g_EDMA_Handle.channel]);
        tcdRegs->SLAST = -sizeof(SPI_data_patterns);
    }

    EDMA_PrepareTransfer(&transferConfig, SPI_data_patterns, sizeof(SPI_data_patterns[0]),

                         (void *)&SPI0->PUSHR, sizeof(SPI0->PUSHR),
                         sizeof(SPI_data_patterns[0]), sizeof(SPI_data_patterns),

                         kEDMA_MemoryToPeripheral);
    EDMA_SubmitTransfer(&g_EDMA_Handle, &transferConfig);

    /*Disable TCD[n].CSR.INTMAJOR because it has been previously set by EDMA_SubmitTransfer(),

      and the corresponding NVIC interrupt is still enabled by EDMA_CreateHandle()*/
    EDMA_TcdDisableInterrupts((edma_tcd_t *)(&g_EDMA_Handle.base->TCD[g_EDMA_Handle.channel]),

                              (uint32_t)(kEDMA_MajorInterruptEnable));                      
 
   for(;;){
       wait20ms();  
       EDMA_StartTransfer(&g_EDMA_Handle);
        /* Wait for SPI0 finish */
       while (!(DSPI_GetStatusFlags(SPI0) & kDSPI_EndOfQueueFlag))
       {
       }
       ...
   }

Best regards,

Pat

0 Kudos
338 Views
DavidS
NXP Employee
NXP Employee

Hi Pat,

Since the LAST was initialized to 0 and there is not a standard API function call to change it, this is just one way to do it.

You could go implement this into your own API call as well.

Regards,

David 

0 Kudos