cancel
Showing results for 
Search instead for 
Did you mean: 

DMA only working once

BRapo.1
Associate

Good day,

I'm trying to control this RGB leds N-PI55TAT
Datasheet 

I'm using an STM32H753VIT6


To do that I have to create a fairly fast burst of data with pulses of 0.6, 0.3  and 0.9 us.

To achieve this I set timer 7 to have an update even every 100nS then I set DMA2 stream 0 in memory to peripheral configuration.
The idea is to create a buffer, with the signal timing, and then set the DMA2 to transfer that buffer to the BSRR register of the port I have connected to the leds.

And it works, It generates the pulses every 100nS and then writting to the buffer where the sets and resets are I got my signal with pretty ok timing.

 

The problem is that it only works once.
Since I won't be updating the leds often, I don't want to create a circular buffer and load the DMA all the time. That's why I wanted to do a normal buffer, execute it once and execute it again when I need to change the colors.

 

BRapo1_0-1701943154582.png

BRapo1_1-1701943289052.png

 

While loop:

 

 

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

	  iled_rst(); //Just a 200us low to reset the led
	  HAL_DMA_Start(&hdma_tim7_up, (uint32_t)bf, (uint32_t)&(GPIOE->BSRR), 289); //transfer buffer to BSRR
	  TIM7->DIER |= (1<<8); //I don't know what this is, but I read it's necesary
	  HAL_Delay(10); //10 ms is more than enough for the DMA to finish, the whole transfer takes about 20us
  }

 

 

Buffer:

 

 

  uint32_t bf[289] = {0};

//the buffer is then loaded with the corresponding data to time the signal

 

 

Init:

 

 

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();
  MX_USART3_UART_Init();
  MX_USART2_UART_Init();
  MX_I2C3_Init();
  MX_USART1_UART_Init();
  MX_TIM7_Init();
  MX_TIM6_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start(&htim6);


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  HAL_TIM_Base_Start(&htim7);

 

 

 

If I put an interrupt before the while loop and set the logic analyzer to trigger, I get the signal sent once, perfectly done. But if I set the analyzer to trigger again the DMA just won't send the data anymore.

I tried clearing the interrupt flags of the DMA:

 

 

DMA2->HIFCR = 0x0FFFFFFF;
DMA2->LIFCR = 0x0FFFFFFF;

 

 

 

I read the status of DMA2 after the 10ms time

 

 

HAL_DMA_GetState(&hdma_tim7_up);

 

 

 

And its 2 HAL_DMA_STATE_BUSY = 0x02U, /*!< DMA process is ongoing */

I tried aborting after the 10ms

 

 

HAL_DMA_Abort(&hdma_tim7_up);

 

 

 

With no success.


Can you please explain to me why the DMA only transmits once?

Thank you very much

2 REPLIES 2
Pierre_Paris
ST Employee

Hello @BRapo.1,

Here some support :

  • Why are you transferring an array of size 289 into a single register of 32 bits ? Have you enabled the source increment ? "If the increment mode is enabled, the address of the next transfer is the address of the
    previous one incremented by 1 (for bytes), 2 (for half-words) or 4 (for words) depending on
    the data width programmed in the PSIZE or MSIZE bits in the DMA_SxCR register." (extract of chapter 15 of RM0433, I advise you to read more by clicking here).
  • Also, how are you filling bf ?
  • Can you please share your DMA handler?
  • Once the timer has been enabled, any time the counter is cleared, either due to a reset event or due to a counter roll-over, the repetition counter is decreased. When it reaches zero, a REP interrupt or a DMA request is issued if enabled (REPIE and REPDE bits in the HRTIM_DIER register). -> Your line 9 of while loop enable CPT2IE (Capture Interrupt Enable). Are you enabling REPIE (Bit 4) and REPDE (Bit 20) ?
  • I tried clearing the interrupt flags of the DMA: -> Which flags are enabled ? 

Best Regards,

Pierre

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.