DMA from DelSig to Memory, 4 TD's

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
WaMa_286156
Level 5
Level 5
First comment on blog 100 replies posted 50 replies posted

  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 */

   

#define DMA_1_BYTES_PER_BURST 2

   

#define DMA_1_REQUEST_PER_BURST 1

   

#define DMA_1_SRC_BASE (CYDEV_PERIPH_BASE)

   

#define DMA_1_DST_BASE (CYDEV_SRAM_BASE)

   

 

   

void configDMA_1() {

   

    // init channel

   

    DMA_1_Chan = DMA_1_DmaInitialize(DMA_1_BYTES_PER_BURST, DMA_1_REQUEST_PER_BURST, 

   

        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.

   

*

   

******************************************************************************/

   

CY_ISR(DmaDone)

   

{

   

    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()) */

   

    ADC_DelSig_Start();

   

    configDMA_1();

   

    

   

        /* 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

   

 

   

    

   

    ADC_DelSig_StartConvert();

   

    

   

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

   

    

   

    

   

    for(;;)

   

    {

   

        /* Place your application code here. */

   

    }

   

 

   

}

0 Likes
7 Replies
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

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

   

 

   

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

   

    

   

 

   

 Regards, Dana.

0 Likes
WaMa_286156
Level 5
Level 5
First comment on blog 100 replies posted 50 replies posted

  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:

   

 

   
        
0 Likes
WaMa_286156
Level 5
Level 5
First comment on blog 100 replies posted 50 replies posted

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

   

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You did not specify DMA__TD_TERMOUT_EN in Td initialization.

   

 

   

Bob

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

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: http://www.cypress.com/?app=forum&id=2492&rID=104670 (though it uses the SAR ADC)

0 Likes
WaMa_286156
Level 5
Level 5
First comment on blog 100 replies posted 50 replies posted

  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.

0 Likes
WaMa_286156
Level 5
Level 5
First comment on blog 100 replies posted 50 replies posted

 @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!

0 Likes