Get minimal DMA working

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.
MaJa_1553636
Level 3
Level 3
First like given

I am trying to get a simple memory => DAC example working using DMA for the byte transfer.

I have a VDAC and a DMA component on my design.

PSoC_Dma.png

My code initializes an array that is to be DMA-ed to the DAC. The commented-out code in the for(;;) loop tests the DAC - that works (but is too slow).

I have used the DMA Wizard to make the DMA_Init() code - but have experimented with other parameters since then...

#define R_DMA_BYTES_PER_BURST 1u

#define R_DMA_REQUEST_PER_BURST 1u

#define R_DMA_SRC_BASE (CYDEV_SRAM_BASE)

#define R_DMA_DST_BASE (CYDEV_PERIPH_BASE)

int main(void)

{

    for(int16_t i = 0; i < 256; i++)

    {

        R_DAC_Data_SRC = i;

    }

   

    R_DAC_Start();

    DMA_Init();

    DMA_ISR_StartEx(onDmaIsr);

   

    CyGlobalIntEnable; /* Enable global interrupts. */

   

    CyDmaChSetRequest(R_DMA_TD[0], CY_DMA_CPU_REQ);

   

    for(;;)

    {       

        // loop takes 80us / 12.5kHz (CPU@40MHz)

//        for(int16_t i = 0; i < 256; i++)

//        {

//            R_DAC_SetValue(i);

//        }

    }

}

void onDmaIsr()

{

    CyDmaChSetRequest(R_DMA_TD[0], CY_DMA_CPU_REQ);

}

void DMA_Init()

{

   

    /* DMA Configuration for R_DMA */

    R_DMA_Chan = R_DMA_DmaInitialize(R_DMA_BYTES_PER_BURST, R_DMA_REQUEST_PER_BURST,

        HI16(R_DMA_SRC_BASE), HI16(R_DMA_DST_BASE));

   

    R_DMA_TD[0] = CyDmaTdAllocate();

   

    uint16_t transferCount = 255;

    CyDmaTdSetConfiguration(R_DMA_TD[0], transferCount, R_DMA_TD[0], R_DMA__TD_TERMOUT_EN | CY_DMA_TD_AUTO_EXEC_NEXT | CY_DMA_TD_INC_SRC_ADR);

    CyDmaTdSetAddress(R_DMA_TD[0], LO16((uint32)R_DAC_Data_SRC), LO16((uint32)R_DAC_Data_PTR));

    CyDmaChSetInitialTd(R_DMA_Chan, R_DMA_TD[0]);

    CyDmaChEnable(R_DMA_Chan, 1);

}

With a breakpoint on the interrupt handler (onDmaIsr) - that breakpoint is never hit. I suspect the DMA never starts, but after a few hours trying out different stuff I have no clue why not.

(This project is to test the limits of the PSoC 5 to generate VGA - hence the naming)

Any help is appreciated.

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi

In the code, the CyDmaChSetRequest() API must have channel handle as  the first parameter, which in this case is R_DMA_Chan. Hence, the API should be CyDmaChSetRequest(R_DMA_Chan, CY_DMA_CPU_REQ); in both the main() and isr.

Also, PSoC 5lp limits the bytes per burst to 127. Therefore, R_DMA_BYTES_PER_BURST and the transferCount must be maximum of 127.

I have attached an updated code which includes all the changes mentioned. It can be observed that the ISR does get executed in this case.

Do let us know in case of any other query.

Thanks and regards

Harigovind

View solution in original post

5 Replies
lock attach
Attachments are accessible only for community members.
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi

In the code, the CyDmaChSetRequest() API must have channel handle as  the first parameter, which in this case is R_DMA_Chan. Hence, the API should be CyDmaChSetRequest(R_DMA_Chan, CY_DMA_CPU_REQ); in both the main() and isr.

Also, PSoC 5lp limits the bytes per burst to 127. Therefore, R_DMA_BYTES_PER_BURST and the transferCount must be maximum of 127.

I have attached an updated code which includes all the changes mentioned. It can be observed that the ISR does get executed in this case.

Do let us know in case of any other query.

Thanks and regards

Harigovind

Doh! I knew it was something 'stupid' ...

Thanx, I'll test it out soon.

EDIT: Yes, that totally works. Thanx!

BTW: The bytes per burst are max 127. The transfer bytes (in transaction) can be max 4096 (if I understood correctly). Although I had to set the request for burst to 0 to get it working. It is a bit peculiar, for a burst of 2 bytes had to be done per byte. Not sure what that is all about.

0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi

Yes you are right. The transfer count can be a maximum of 4095. You can either set the burst count to 0 (entire transfer count will be transferred in one burst) or the request per burst to 0 (which will ensure all subsequent bursts after the first burst will be automatically requested and carried out).

However, note that CY_DMA_TD_AUTO_EXEC_NEXT must be removed, otherwise the DMA will keep transferring without a CPU request. The configuration API should be:

CyDmaTdSetConfiguration(R_DMA_TD[0], transferCount, R_DMA_TD[0], R_DMA__TD_TERMOUT_EN |  CY_DMA_TD_INC_SRC_ADR);

Thanks and regards

Harigovind

0 Likes

You mean the start / source address (my array) set in the TD is not used when the TD starts again?

I would not expect that.

0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

No. I mean the dma will be active endlessly. The transfer of data will happen without the need of CyDmaChSetRequest(R_DMA_Chan, CY_DMA_CPU_REQ); statement.

0 Likes