Skip to main content
Visitor II
January 8, 2025
Question

How to configure GPDMA for PWM generation?

  • January 8, 2025
  • 2 replies
  • 1030 views

Hi,

I'm using a Riverdi RVT50HQSFWN00 Screen with the STM32U5A9NJH6Q MCU. COnnected to pin PI0 is a WS2812 LED light strip. I already configured the timer 5 channel 4 for PWM generation and validated it with a scope at the pin. Right now I'm stuck at the GPDMA part. I'm able to start the PWM generation using: HAL_TIM_PWM_Start_DMA(&htim8, TIM_CHANNEL_1, (uint32_t *)pwmData, indx);

For the code I followed this tutorial: https://controllerstech.com/interface-ws2812-with-stm32/

This is my timer configuration (TIM5 global interrupt enabled):

m4rk0401_0-1736341234347.png

This is GPDMA configuration:

m4rk0401_1-1736341318843.png

Using a scope, I see that a PWM signal is generated but the HAL_TIM_PWM_PulseFinishedCallback() function is never called, which in the end, stops the DMA transfer.

Would really appreciate any help.

Best regards
Marko

    This topic has been closed for replies.

    2 replies

    ST Employee
    January 8, 2025

    Hello @m4rk0401

    In your GPDMA configuration, in the destination data setting, try enabling the destination address increment after transfer

    m4rk0401Author
    Visitor II
    January 9, 2025

    Thanks @Sarra.S for your quick response. I tried your suggestion without success.

    I tried some more debugging today and achieved following result:

    Code (reduced to most important parts) - app_freertos.c: 

    int datasentflag = 0;
    extern TIM_HandleTypeDef htim5;
    
    void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
    {
    	HAL_TIM_PWM_Stop_DMA(&htim5, TIM_CHANNEL_4);
    	datasentflag=1;
    }
    
    uint16_t pwmData[24];
    void test()
    {
    	for(int i=0; i<24; i++)
    	{
    		pwmData[i] = 50;
    	}
    
    	HAL_TIM_PWM_Start_DMA(&htim5, TIM_CHANNEL_4, (uint32_t *)pwmData, 24);
    	/*
    	while (!datasentflag){};
    	datasentflag = 0;
    	*/
    }
    
    void StartDefaultTask(void *argument)
    {
     /* USER CODE BEGIN defaultTask */
     /* Infinite loop */
     for(;;)
     {
    	 test();
    	 osDelay(100);
     }
     /* USER CODE END defaultTask */
    }


    GPDMA configuration:

    m4rk0401_0-1736433491609.png

    Timer configuration is the same because basic PWM generations works.

    Unfortunately is set 24 different duty cycles in my code and get following result using a oscilloscope:

    IMG_8265 (2).png


    Any idea why only 14 cycles are outputted?

    Best regards
    Marko



    m4rk0401Author
    Visitor II
    January 16, 2025

    Any idea @Sarra.S ?

    Visitor II
    February 27, 2025

    We had a similiar error with GPDMA. What helped us, was changing Data width to "Byte" in Source data setting and destination data setting in GPDMA configuration. Also then you have to change 

    uint16_t pwmData[24];

    to
    uint8_t pwmData[24]