PSoC 6 WS2812 DMA problem

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

cross mob
BohdanHunko
Level 1
Level 1
First reply posted First question asked Welcome!

Hi,

I am trying to use cy8ckit-064s0s2-4343w to drive WS2812b LED strip.

I have found ws2812 library in iot_expert github repo (1)  and it works fine.

But my application is performance critical so I would like to use DMA to output data to SPI.

I have found DMA version of that library (2)   and also the article about it

The problem is that it does not work.

I remember using same library on PSoC 4 and it worked ok.

To narrow down the problem i have combined non DMA version (link (1)) with dma configuration from link (2).

The result is as follows:

When cyhal_psi_transfer() is used to output the data everything works fine.

When WS_DMATrigger() is used the LEDs does not light up.

The code can be found here .

I have spent several hours and still was not able to find the problem.

I would greatly appreciate some help.

Thanks. 

0 Likes
1 Solution
PandaS
Moderator
Moderator
Moderator
250 replies posted 100 solutions authored 5 likes given

Hi @BohdanHunko ,

I tried replicating your code at my end. I was also facing the same issue. Most probably its related to DMA Trigger not working. So for that, I created a simple DMA transfer and did all configurations in PDL and connected the Trigger Multiplexer group to right Input and Output. Then it works fine.

I have created a code example to demonstrate this. Take a look and modify the Trigger connections to right peripherals and give it a try:

#include "cy_pdl.h"
#include "cyhal.h"
#include "cybsp.h"

/* Scenario: Initialize a 1D descriptor */
#define DATACNT (8UL)
cy_stc_dma_descriptor_t descriptor;



int main(void)
{
    cy_rslt_t result;

    uint32_t src[DATACNT] = {1,2,3,4,5,6,7,8};
    uint32_t dst[DATACNT];

    /* Initialize the device and board peripherals */
    result = cybsp_init() ;
    if (result != CY_RSLT_SUCCESS)
    {
        CY_ASSERT(0);
    }

    __enable_irq();


   cy_stc_dma_descriptor_config_t descriptor_cfg =
   {
	   .retrigger = CY_DMA_RETRIG_IM,
	   .interruptType = CY_DMA_DESCR,
	   .triggerOutType = CY_DMA_DESCR,
	   .channelState = CY_DMA_CHANNEL_ENABLED,
	   .triggerInType = CY_DMA_DESCR,
	   .dataSize = CY_DMA_WORD,
	   .srcTransferSize = CY_DMA_TRANSFER_SIZE_WORD,
	   .dstTransferSize = CY_DMA_TRANSFER_SIZE_WORD,
	   .descriptorType = CY_DMA_1D_TRANSFER,
	   .srcAddress = &src,
	   .dstAddress = &dst,
	   .srcXincrement = 1U,
	   .dstXincrement = 1U,
	   .xCount = DATACNT,
	   .srcYincrement = 0U,
	   .dstYincrement = 0U,
	   .yCount = 1UL,
	   .nextDescriptor = NULL,
   };

   if (CY_DMA_SUCCESS != Cy_DMA_Descriptor_Init(&descriptor, &descriptor_cfg))
   {
	   // Insert error handling
   }

   // Scenario: Setup and enable the DMA channel 0 of block DW0
   cy_stc_dma_channel_config_t channelConfig;
   channelConfig.preemptable = false;
   channelConfig.enable = false;
   channelConfig.bufferable = false;

   if (CY_DMA_SUCCESS != Cy_DMA_Channel_Init(DW0, 0UL, &channelConfig))
   {
	   // Insert error handling
   }

   Cy_TrigMux_Connect(TRIG_IN_MUX_0_PDMA0_TR_OUT0 , TRIG_OUT_MUX_0_PDMA0_TR_IN0 , false, TRIGGER_TYPE_EDGE);

   Cy_DMA_Channel_SetDescriptor(DW0, 0UL, &descriptor);
   Cy_DMA_Channel_SetPriority(DW0, 0UL, 3UL);
   Cy_DMA_Channel_Enable(DW0, 0UL);

   Cy_DMA_Enable(DW0);

   if (CY_TRIGMUX_SUCCESS != Cy_TrigMux_SwTrigger(TRIG_OUT_MUX_0_PDMA0_TR_IN0, CY_TRIGGER_TWO_CYCLES))
   {

   }

    for (;;)
    {

    }
}

Thanks and regards

Sobhit

View solution in original post

0 Likes
3 Replies
PandaS
Moderator
Moderator
Moderator
250 replies posted 100 solutions authored 5 likes given

Hi @BohdanHunko ,

I would suggest you to go through Infineon's GitHub repository explaining SPI DMA for PSoC6.

Link - https://github.com/Infineon/mtb-example-psoc6-spi-master-dma

Give it a try and let me know if that helps.

 

Thanks

Sobhit

0 Likes

Hi,

Thanks for quick reply

I have cloned the example and changed SPI_MODE to SPI_MODE_BOTH.

I have also changed target to be cy8ckit-064s0s2-4343w

Everything builds fine, but LED does not blink.

The program is stuck on while(false == tx_dma_complete){}

I have put a breakpoint inside of tx_dma_complete() interrupt handler and this interrupt never happens. This is exactly the results I am seeing in my other projects: dma done event never happens.

0 Likes
PandaS
Moderator
Moderator
Moderator
250 replies posted 100 solutions authored 5 likes given

Hi @BohdanHunko ,

I tried replicating your code at my end. I was also facing the same issue. Most probably its related to DMA Trigger not working. So for that, I created a simple DMA transfer and did all configurations in PDL and connected the Trigger Multiplexer group to right Input and Output. Then it works fine.

I have created a code example to demonstrate this. Take a look and modify the Trigger connections to right peripherals and give it a try:

#include "cy_pdl.h"
#include "cyhal.h"
#include "cybsp.h"

/* Scenario: Initialize a 1D descriptor */
#define DATACNT (8UL)
cy_stc_dma_descriptor_t descriptor;



int main(void)
{
    cy_rslt_t result;

    uint32_t src[DATACNT] = {1,2,3,4,5,6,7,8};
    uint32_t dst[DATACNT];

    /* Initialize the device and board peripherals */
    result = cybsp_init() ;
    if (result != CY_RSLT_SUCCESS)
    {
        CY_ASSERT(0);
    }

    __enable_irq();


   cy_stc_dma_descriptor_config_t descriptor_cfg =
   {
	   .retrigger = CY_DMA_RETRIG_IM,
	   .interruptType = CY_DMA_DESCR,
	   .triggerOutType = CY_DMA_DESCR,
	   .channelState = CY_DMA_CHANNEL_ENABLED,
	   .triggerInType = CY_DMA_DESCR,
	   .dataSize = CY_DMA_WORD,
	   .srcTransferSize = CY_DMA_TRANSFER_SIZE_WORD,
	   .dstTransferSize = CY_DMA_TRANSFER_SIZE_WORD,
	   .descriptorType = CY_DMA_1D_TRANSFER,
	   .srcAddress = &src,
	   .dstAddress = &dst,
	   .srcXincrement = 1U,
	   .dstXincrement = 1U,
	   .xCount = DATACNT,
	   .srcYincrement = 0U,
	   .dstYincrement = 0U,
	   .yCount = 1UL,
	   .nextDescriptor = NULL,
   };

   if (CY_DMA_SUCCESS != Cy_DMA_Descriptor_Init(&descriptor, &descriptor_cfg))
   {
	   // Insert error handling
   }

   // Scenario: Setup and enable the DMA channel 0 of block DW0
   cy_stc_dma_channel_config_t channelConfig;
   channelConfig.preemptable = false;
   channelConfig.enable = false;
   channelConfig.bufferable = false;

   if (CY_DMA_SUCCESS != Cy_DMA_Channel_Init(DW0, 0UL, &channelConfig))
   {
	   // Insert error handling
   }

   Cy_TrigMux_Connect(TRIG_IN_MUX_0_PDMA0_TR_OUT0 , TRIG_OUT_MUX_0_PDMA0_TR_IN0 , false, TRIGGER_TYPE_EDGE);

   Cy_DMA_Channel_SetDescriptor(DW0, 0UL, &descriptor);
   Cy_DMA_Channel_SetPriority(DW0, 0UL, 3UL);
   Cy_DMA_Channel_Enable(DW0, 0UL);

   Cy_DMA_Enable(DW0);

   if (CY_TRIGMUX_SUCCESS != Cy_TrigMux_SwTrigger(TRIG_OUT_MUX_0_PDMA0_TR_IN0, CY_TRIGGER_TWO_CYCLES))
   {

   }

    for (;;)
    {

    }
}

Thanks and regards

Sobhit

0 Likes