PSoC6 aborting DMA and determining how much was done

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

cross mob
DaJa_4418646
Level 1
Level 1
First like received

I've got an SCB UART connected to Rx and Tx DMA engines.

I have Tx set up so that I can give it a buffer and I will get an interrupt when it's done. That works fine.

I have Rx set up so that I can give it a buffer, and I will get an interrupt when the buffer is full. That also works fine.

However, I would like to have some means to stop/abort the DMA on Rx and get the count of how many bytes were received so far. Ideally, I would call some function and the Rx DMA engine would finish the last iteration of what it was doing and then still call the completion ISR, but in that ISR, I can read GetXloopCount or something to determine how much had been done.

I can't for the life of me get that to work. I can't figure out how to disable the DMA in such a way that I get an interrupt anyway.

Alternatively, I'd be happy to skip the last interrupt and just disable the DMA, but in that case, I still want to get a count of how many bytes have transferred so far.

What am I doing wrong?

PS -- I'm new to PSoC so please go easy on me.

0 Likes
1 Solution
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi DaJa_4418646​,

The DMA interrupt will trigger only if the DMA completes as per what is mentioned in the Interrupt descriptor.

You can use the Tr_out signal as the input to the Count trigger signal of the counter to count the no of bytes received by the DMA channel. You can clear the counter as soon as the DMA interrupt is triggered (DMA complete event).

pastedImage_0.png

void StopTransferReadCount()

{

            Cy_DMA_Channel_Disable(RxDMA_HW,RxDMA_DW_CHANNEL);

            GetXloopCount = Cy_TCPWM_Counter_GetCounter(Counter_1_HW, Counter_1_CNT_NUM) + 1;

            printf("\n\r%d",GetXloopCount);

            Cy_DMA_Channel_Enable(RxDMA_HW,RxDMA_DW_CHANNEL);

}

Please note that the first count signal will be taken as start for the counter and therefore the count value is offset by 1.

You can also purposefully set an interrupt using Cy_DMA_Channel_SetInterrupt(). (Not required)

For example:

void StopTransferReadCount()

     {

           Cy_DMA_Channel_Disable(RxDMA_HW,RxDMA_DW_CHANNEL);

           Cy_DMA_Channel_SetInterrupt(RxDMA_HW,RxDMA_DW_CHANNEL);

    }

/*Rx DMA ISR*/

void RxDmaCmplt(void)

{

    /* Clears the interupt source in RxDMA channel */

    Cy_DMA_Channel_ClearInterrupt(RxDMA_HW, RxDMA_DW_CHANNEL);

    GetXloopCount = Cy_TCPWM_Counter_GetCounter(Counter_1_HW, Counter_1_CNT_NUM) + 1;

    printf("\n\r%d",GetXloopCount);

    Cy_DMA_Channel_Enable(RxDMA_HW,RxDMA_DW_CHANNEL);

}

   

Regards,

Bragadeesh

Regards,
Bragadeesh

View solution in original post

0 Likes
2 Replies
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi DaJa_4418646​,

The DMA interrupt will trigger only if the DMA completes as per what is mentioned in the Interrupt descriptor.

You can use the Tr_out signal as the input to the Count trigger signal of the counter to count the no of bytes received by the DMA channel. You can clear the counter as soon as the DMA interrupt is triggered (DMA complete event).

pastedImage_0.png

void StopTransferReadCount()

{

            Cy_DMA_Channel_Disable(RxDMA_HW,RxDMA_DW_CHANNEL);

            GetXloopCount = Cy_TCPWM_Counter_GetCounter(Counter_1_HW, Counter_1_CNT_NUM) + 1;

            printf("\n\r%d",GetXloopCount);

            Cy_DMA_Channel_Enable(RxDMA_HW,RxDMA_DW_CHANNEL);

}

Please note that the first count signal will be taken as start for the counter and therefore the count value is offset by 1.

You can also purposefully set an interrupt using Cy_DMA_Channel_SetInterrupt(). (Not required)

For example:

void StopTransferReadCount()

     {

           Cy_DMA_Channel_Disable(RxDMA_HW,RxDMA_DW_CHANNEL);

           Cy_DMA_Channel_SetInterrupt(RxDMA_HW,RxDMA_DW_CHANNEL);

    }

/*Rx DMA ISR*/

void RxDmaCmplt(void)

{

    /* Clears the interupt source in RxDMA channel */

    Cy_DMA_Channel_ClearInterrupt(RxDMA_HW, RxDMA_DW_CHANNEL);

    GetXloopCount = Cy_TCPWM_Counter_GetCounter(Counter_1_HW, Counter_1_CNT_NUM) + 1;

    printf("\n\r%d",GetXloopCount);

    Cy_DMA_Channel_Enable(RxDMA_HW,RxDMA_DW_CHANNEL);

}

   

Regards,

Bragadeesh

Regards,
Bragadeesh
0 Likes

Thank you, Bragadeesh, this makes perfect sense. I'll try it out and get back to you if I have issues.

Best,

Dave J