Cannot set DMA X loop size in software unless configured as greater than 1 in schematic entry

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

cross mob
ChRe_4711096
Level 4
Level 4
50 replies posted 25 replies posted 25 sign-ins

I'm trying to set the number of loop transfers for a DMA channel in software using sizeof(). However, this halts in Cy_DMA_Descriptor_SetXloopDataCount() *if* the x loop transfer count is initially set to one in the schematic entry:

Anmerkung 2020-06-25 232530.png

Setting it to two works, as in the attached project.

Questions:

Is there a reason why this is so?

Did I find the appropriate workaround?

is there a better way of DMA'ing two variables from one memory location to another with just one trigger?

The real application will use a hardware trigger to start the DMA transfer (PWM timer overflow output).

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

Hi ChRe_4711096​,

You are looking for a 1D transfer (array of elements) in one X Loop transfer. If no of data elements to transfer in X loop is set to 1, it becomes a single transfer. When you set this parameter to 1, observe that cy_stc_dma_descriptor_t sets .ctl  to 0 which is CY_DMA_SINGLE_TRANSFER.

pastedImage_0.png

Therefore setting the no of X loop counts to 2 or more (sizeof returns 8 in your case), is invalid. See the implementation of Cy_DMA_Descriptor_SetXloopDataCount()

pastedImage_1.png

GetDescriptorType() will return 0 and causes a processing fault.

How to solve this problem?

1. Set the transfer type to CY_DMA_1D_TRANSFER using Cy_DMA_Descriptor_SetDescriptorType(&DMA_1_descr_struct, CY_DMA_1D_TRANSFER  )

2. Change the X Loop transfer count to value greater than 2 but less than 256 using Cy_DMA_Descriptor_SetXloopDataCount(&DMA_1_descr_struct, sizeof(struct));

3. Change X loop increment : Cy_DMA_Descriptor_SetXloopSrcIncrement(&DMA_1_descr_struct, 1UL);

4. Change Y loop increment : Cy_DMA_Descriptor_SetXloopDstIncrement(&DMA_1_descr_struct, 1UL); 

5. Change Next Descriptor : Cy_DMA_Descriptor_SetNextDescriptor(&DMA_1_descr_struct, &nextDescriptor);

Make sure you don't modify any of the descriptor settings when the current descriptor is getting executed. I'm attaching the project I used to test this for your reference.

Regards,

Bragadeesh

Regards,
Bragadeesh

View solution in original post

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

Hi ChRe_4711096​,

You are looking for a 1D transfer (array of elements) in one X Loop transfer. If no of data elements to transfer in X loop is set to 1, it becomes a single transfer. When you set this parameter to 1, observe that cy_stc_dma_descriptor_t sets .ctl  to 0 which is CY_DMA_SINGLE_TRANSFER.

pastedImage_0.png

Therefore setting the no of X loop counts to 2 or more (sizeof returns 8 in your case), is invalid. See the implementation of Cy_DMA_Descriptor_SetXloopDataCount()

pastedImage_1.png

GetDescriptorType() will return 0 and causes a processing fault.

How to solve this problem?

1. Set the transfer type to CY_DMA_1D_TRANSFER using Cy_DMA_Descriptor_SetDescriptorType(&DMA_1_descr_struct, CY_DMA_1D_TRANSFER  )

2. Change the X Loop transfer count to value greater than 2 but less than 256 using Cy_DMA_Descriptor_SetXloopDataCount(&DMA_1_descr_struct, sizeof(struct));

3. Change X loop increment : Cy_DMA_Descriptor_SetXloopSrcIncrement(&DMA_1_descr_struct, 1UL);

4. Change Y loop increment : Cy_DMA_Descriptor_SetXloopDstIncrement(&DMA_1_descr_struct, 1UL); 

5. Change Next Descriptor : Cy_DMA_Descriptor_SetNextDescriptor(&DMA_1_descr_struct, &nextDescriptor);

Make sure you don't modify any of the descriptor settings when the current descriptor is getting executed. I'm attaching the project I used to test this for your reference.

Regards,

Bragadeesh

Regards,
Bragadeesh
0 Likes

Thank you very much, that clarified some things. However, you added a comment to your main.c file that got me thinking:

            /* This is required since you have mentioned the nextDescriptor of DMA_1_descr_ctrlReg

                to NULL in configurator */

            Cy_DMA_Channel_SetDescriptor(DMA_1_HW, DMA_1_DW_CHANNEL, &DMA_1_descr_ctrlReg);

If I wanted a timer to re-trigger this DMA transfer without further software intervention, how would I configure the descriptors, especially the chaining?

0 Likes

Hi ChRe_4711096​,

That is a mistake in my comment. Corrected below.

This is required since you have mentioned the nextDescriptor of DMA_1_descr_struct to NULL in configurator */

I believe you want to alternate between the two descriptors. In that case, you can set the "next descriptor" of the second descriptor (DMA_1_descr_struct) to the first descriptor (DMA_1_descr_ctrlReg). I saw this parameter to be "Nothing" in your configurator settings. You will trigger an interrupt at the end of the descriptor chain (see my example code) which is essential to know if the transaction completed successfully.

Regards,

Bragadeesh

Regards,
Bragadeesh
0 Likes

The desired behavior is like this:

hw trigger -> descr_ctrlReg -> descr_struct -> (no ISR) and be ready to accept a new hardware trigger without cpu intervention. The whole point of this DMA channel is to get rid of the ISR entirely.

The alternative would be to write an ISR just to write a control register and copy a structure from one memory location to another:

hw trigger -> ISR

0 Likes

Yes, you can do that by setting Channel state on completion to "Enable" (you already have this enabled). Therefore the channel will always be waiting for a trigger (CPU need not re-enable the channel). But it is essential to check the status of the DMA to handle any errors in transfer.

Regards,
Bragadeesh
0 Likes