cancel
Showing results for 
Search instead for 
Did you mean: 

LL DMA Burst to a Timer not working on STM32H7

MDega.2
Associate II

Hello,

I am trying to use the DMA in burst mode to send data to a timer, to configure two PWM channels at every update event, but the DMA doesn't seem to write any data, however it doesn't trigger an error and triggers the transfer complete flag .

I am trying it on a Nucleo-H723ZG, Tim8 CH3 on PC8 and CH4 on PC9. I have also a debug Pin on PC10

I don't believe I have the usual memory problem with DCM: my data is at the address 0x24000020.

I believe I configured everything correctly:

#define K_LenBurst   16
uint16_t DataBurst[K_LenBurst];
 
void BurstInit(void) {
 
	  LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_0,(uint32_t)DataBurst);
	  LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_0,(uint32_t)&TIM8->DMAR);
	  LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0,K_LenBurst);
 
	  LL_TIM_ConfigDMABurst(TIM8, LL_TIM_DMABURST_BASEADDR_CCR3, LL_TIM_DMABURST_LENGTH_2TRANSFERS);
 
	  LL_TIM_EnableDMAReq_UPDATE(TIM8);
	  LL_TIM_SetAutoReload(TIM8, 150);
	  LL_TIM_EnableCounter(TIM8);
	  LL_TIM_EnableAllOutputs(TIM8);
	  LL_TIM_CC_EnableChannel(TIM8, LL_TIM_CHANNEL_CH3 | LL_TIM_CHANNEL_CH4);
 
	  LL_DMA_EnableIT_TC(DMA1,LL_DMA_STREAM_0);
}

Then I am runing this at 10Hz:

void Burst(void) {
	int i,dataPtr;
 
	dataPtr = 0;
 
	LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_0);
	LL_DMA_ClearFlag_TC0(DMA1);  //Just in case...
	LL_GPIO_ResetOutputPin(Dbg_GPIO_Port, Dbg_Pin);
 
	for (i=1; i<=16;i++) {  //Filling random data
		DataBurst[dataPtr++] = i<<2;
	}
 
    LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0,K_LenBurst);
 
	LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_0);
}

which trigers the interrupt at 10Hz:

void DMA1_Stream0_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream0_IRQn 0 */
 
  /* USER CODE END DMA1_Stream0_IRQn 0 */
 
  /* USER CODE BEGIN DMA1_Stream0_IRQn 1 */
  LL_GPIO_SetOutputPin(Dbg_GPIO_Port, Dbg_Pin);
  LL_DMA_ClearFlag_TC0(DMA1);
  /* USER CODE END DMA1_Stream0_IRQn 1 */
}

I can see the "Dbg" pin changing state at 10Hz, however the Timer8 CCR3 and CCR4 are always at 0.

In the debug window, if I change the CCR3 and CCR4 registers, then yes I can see a PWM output

The reference manual only shows these steps in the example "43.3.28 DMA burst mode".

I have attached my .ioc file, where I set-up the DMA in normal mode, no buffer and half word for both memory and peripheral.

Did anyone encounter this problem?

Thanks,

Marco

1 ACCEPTED SOLUTION

Accepted Solutions

Hi Jan,

Those registers were initialized from CubeMx, but I was still palying with the values, The correct settings, as described with half word and no buffers are

S0CR = 0x22C50

Anyway I've solved it, it's related to the order of which the init is done from CubeIDE

Tim8 Init contains some DMA settings that are performed before the clock is activated for the DMA init:

  /* TIM1_UP Init */
  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_STREAM_0, LL_DMAMUX1_REQ_TIM1_UP);
 
  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_0, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
 
  LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_0, LL_DMA_PRIORITY_HIGH);
...

However these are executed before enabling the clock for the DMA:

static void MX_DMA_Init(void)
{
 
  /* Init with LL driver */
  /* DMA controller clock enable */
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
...

Calling the MX_DMA_Init before anything else will do the trick:

  /* USER CODE BEGIN SysInit */
  MX_DMA_Init();   //Added
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM8_Init();
  MX_DMA_Init();

I believe that all the values were correct, but without clock during the set-up, something inside the MCU was not getting initialized properly.

Thank you for the support,

Marco

View solution in original post

4 REPLIES 4

Is DataBurst[] cached?\

If you set CCR3 and CCR4 in the setup code to some "random" values, do they remain or do they change to 0?

Read out and check/post content of TIM, DMA, DMAMUX registers.

Note, that reading TIM registers in debugger influences the "burst" mechanism (it messes up the internal "current register pointer", but it still should work somehow, though).

JW

MDega.2
Associate II

Hi Jan,

thank you for your answer.

The cache is disabled (I figure it would save some troubles):

0693W00000GYfqtQAD.pngYes, if I set the CCRx register to some value, it stays there (hence my suspicion that the DMA is not writing into the register)

My DMA settings:

0693W00000GYg2aQAD.pngThere is no transfer error, just the DMEIF0 which is described to be set "when a DMA request occurs when the previous data has not yet been fully transferred", which is odd because there is nothing else running or using the memory bus.

Here are the timer and DMAMUX settings

0693W00000GYg92QAD.png0693W00000GYg6XQAT.png

Both S0CR=0x10 and S0NDTR=0 are wrong.

Where do you set the DMA control registers fields?

JW

Hi Jan,

Those registers were initialized from CubeMx, but I was still palying with the values, The correct settings, as described with half word and no buffers are

S0CR = 0x22C50

Anyway I've solved it, it's related to the order of which the init is done from CubeIDE

Tim8 Init contains some DMA settings that are performed before the clock is activated for the DMA init:

  /* TIM1_UP Init */
  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_STREAM_0, LL_DMAMUX1_REQ_TIM1_UP);
 
  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_0, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
 
  LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_0, LL_DMA_PRIORITY_HIGH);
...

However these are executed before enabling the clock for the DMA:

static void MX_DMA_Init(void)
{
 
  /* Init with LL driver */
  /* DMA controller clock enable */
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
...

Calling the MX_DMA_Init before anything else will do the trick:

  /* USER CODE BEGIN SysInit */
  MX_DMA_Init();   //Added
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM8_Init();
  MX_DMA_Init();

I believe that all the values were correct, but without clock during the set-up, something inside the MCU was not getting initialized properly.

Thank you for the support,

Marco