You are here

DMA from DelSig to Memory, 4 TD's | Cypress Semiconductor

DMA from DelSig to Memory, 4 TD's

Summary: 7 Replies, Latest post by wsm on 03 Mar 2015 02:24 PM PST
Verified Answers: 1
Last post
Log in to post new comments.
wsm's picture
91 posts


  I'm trying to dma from ADC DelSig into memory, chained.  I used the DMA tool to generate the code.

  Bringing the ADC EOC out to a pin shows it is bouncing, but I never get an ISR notification of DMA complete.

  I think I'm doing something wrong. Here is the code and a picture of the schematic.  

  Any suggestions as to what I'm doing wrong and how to fix?

  Pic of the schematic under question is attached

#include <project.h>


/* Variable declarations for DMA_1 */

/* Move these variable declarations to the top of the function */

uint8 DMA_1_Chan;// the handle for this DMA unit

int finishedDMA_1;      // set to 1 when the DMA is irq is triggered

uint8 DMA_1_State;      // current state of the DMA unit

uint8 DMA_1_TD_InUse;   // which TD is in use currently (filled in at DMA Complete interrupt)

uint8 DMA_1_TD[4];

int16 WaveForm1a[3750];

int16 WaveForm1b[3750];

int16 WaveForm2a[3750];

int16 WaveForm2b[3750];


/* DMA Configuration for DMA_1 */






void configDMA_1() {

    // init channel


        HI16(DMA_1_SRC_BASE), HI16(DMA_1_DST_BASE));


    // set up transfer descriptors

    DMA_1_TD[0] = CyDmaTdAllocate();

    DMA_1_TD[1] = CyDmaTdAllocate();

    DMA_1_TD[2] = CyDmaTdAllocate();

    DMA_1_TD[3] = CyDmaTdAllocate();


    // configure td

    CyDmaTdSetConfiguration(DMA_1_TD[0], 3750, DMA_1_TD[1],  TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);

    CyDmaTdSetConfiguration(DMA_1_TD[1], 3750, DMA_1_TD[2],  TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);

    CyDmaTdSetConfiguration(DMA_1_TD[2], 3750, DMA_1_TD[3],  TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);

    CyDmaTdSetConfiguration(DMA_1_TD[3], 3750, DMA_1_TD[0],  TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);

    // set addresses

    CyDmaTdSetAddress(DMA_1_TD[0], LO16((uint32)ADC_DelSig_DEC_SAMP_PTR), LO16((uint32)WaveForm1a));

    CyDmaTdSetAddress(DMA_1_TD[1], LO16((uint32)ADC_DelSig_DEC_SAMP_PTR), LO16((uint32)WaveForm1b));

    CyDmaTdSetAddress(DMA_1_TD[2], LO16((uint32)ADC_DelSig_DEC_SAMP_PTR), LO16((uint32)WaveForm2a));

    CyDmaTdSetAddress(DMA_1_TD[3], LO16((uint32)ADC_DelSig_DEC_SAMP_PTR), LO16((uint32)WaveForm2b));

    // set initial td

    CyDmaChSetInitialTd(DMA_1_Chan, DMA_1_TD[0]);

    // enable

    CyDmaChEnable(DMA_1_Chan, 1);




* Function Name: DmaDone



* Summary:

*  Handle Interrupt Service Routine. Source - DMA.





    finishedDMA_1 = 1u;

    // pick up current operational prameters

    CyDmaChStatus( DMA_1_Chan,&DMA_1_TD_InUse, &DMA_1_State);


int main()


    /* Place your initialization/startup code here (e.g. MyInst_Start()) */




        /* Setup the Interrupt connected to the nrq terminal. */

    isr_DMA_1_StartEx(DmaDone);// this call takes the address of our ISR.  isr_DMA_1_Start() assigns default address





     CyGlobalIntEnable;  /* Uncomment this line to enable global interrupts. */





        /* Place your application code here. */




user_14586677's picture
7646 posts

This should be in main() and part of startup right after main( ) {


     CyGlobalIntEnable;  /* Uncomment this line to enable global interrupts. */



 Regards, Dana.

wsm's picture
91 posts


  Thanks for the reply, but that did not change anything.  I saw that the png file did not get included as I thought it would. Here it is:


wsm's picture
91 posts

 The EOC line is transitioning, (yellow trace), but the NRQ line from the DMA unit is never transitioning (blue trace).  Any suggestions?

user_1377889's picture
9268 posts

You did not specify DMA__TD_TERMOUT_EN in Td initialization.



user_78878863's picture
2551 posts

Your DMA TDs form a loop (the last one sets the first one as next TD). So there is no condition that will end the DMA transfer, the just execute one after each other.

So each TD will transfer 3750 bytes, then the next one, and the the first one starts again. Look at AN52705 - Ping-Pong-DMA, thats exactly what you did.

For a solution to your problem: look in this thread: (though it uses the SAR ADC)

wsm's picture
91 posts


  That was it.  I did not pick up on that meaning that nrq was enabled until I played around with the DMA Tool in PSoC creator again.  I thought, from the text of the #define that it killed the transfer.  DOH!

  thanks!  It is working now, I'm getting my ISR.

  worst case,it appears to take about 6 microseconds to generate the NRQ into the ISR unit.  It varies, sometimes it is less than 1 microsecond.


wsm's picture
91 posts

 @hli,  thanks.

  Yes, I understood that.  However, my problem was that NRQ was not being driven through because I did not have DMA_1__TD_TERMOUT_EN  in my configuration of the DMA unit.  I misunderstood what it was for.  Mea culpa!

  Each time I get the ISR, I grab the current TD being used, and gives my non-isr code the information it needs to determine which data set is complete.  A data set is 7,500 bytes.  The DMA unit can only transfer a maximum of 4096 bytes, so I split it into two parts of 3750 bytes.

   I essentially have a ping-pong buffer setup to allow the code to work on one completed unit while the other unit is being filled.  Hopefully that allows me to gather data without dropping any samples.


thanks again!


Log in to post new comments.