cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F769 PWM using DMA on two channels PA2 and PA3 issue

VMoca.1
Associate II

Hello,

I have an issue with using two channels of DMA to generate the PWM on PA2 and PA3 pins.

I configured using CubeMX TIM2 PWM Generation CH3 and CH4.

I have added the DMA memory to peripheral for PA2 DMA1Stream1 and for PA3 DMA1Stream6.

The issue I have is that only the DMA1_Stream1_IRQHandler is called and only the PA2 PWM generation is done. DMA1_Stream6_IRQHandler is never called.

This is what I use to test PA3 pin.

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)

{

 GPIO_InitTypeDef  GPIO_InitStruct1;

 GPIO_InitTypeDef  GPIO_InitStruct2;

 static DMA_HandleTypeDef hdma_tim1;

 static DMA_HandleTypeDef hdma_tim2;

 /*##-1- Enable peripherals and GPIO Clocks #################################*/

 /* TIMx clock enable */

 TIMx_CLK_ENABLE();

 /* Enable GPIO Channel3/3N Clocks */

 TIMx_CHANNEL3_GPIO_CLK_ENABLE(); /* PA2 and PA3 */

 /* Enable DMA clock */

 DMAx_CLK_ENABLE();

   /* Configure TIM2_Channel3 in output, push-pull & alternate function mode */

   GPIO_InitStruct1.Pin = GPIO_PIN_CHANNEL4; /*  PA3 */

   GPIO_InitStruct1.Mode = GPIO_MODE_AF_PP;

   GPIO_InitStruct1.Pull = GPIO_PULLUP;

   GPIO_InitStruct1.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

   GPIO_InitStruct1.Alternate = GPIO_AF1_TIM2;

   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct1);

   /* Set the parameters to be configured */

   hdma_tim1.Init.Channel = DMA_CHANNEL_4; /* PA3 TIM2_CH4 */

   hdma_tim1.Init.Direction = DMA_MEMORY_TO_PERIPH;

   hdma_tim1.Init.PeriphInc = DMA_PINC_DISABLE;

   hdma_tim1.Init.MemInc = DMA_MINC_ENABLE;

   hdma_tim1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD ;

   hdma_tim1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD ;

   hdma_tim1.Init.Mode = DMA_CIRCULAR;

   hdma_tim1.Init.Priority = DMA_PRIORITY_HIGH;

   hdma_tim1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

   hdma_tim1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

   hdma_tim1.Init.MemBurst = DMA_MBURST_SINGLE;

   hdma_tim1.Init.PeriphBurst = DMA_PBURST_SINGLE;

   /* Set hdma_tim instance */

   hdma_tim1.Instance = DMA1_Stream6;

   /* Link hdma_tim to hdma[TIM_DMA_ID_CC4] (channel4) */

   __HAL_LINKDMA(htim, hdma[TIM_DMA_ID_CC4], hdma_tim1);

   /* Initialize TIMx DMA handle */

   HAL_DMA_Init(htim->hdma[TIM_DMA_ID_CC4]);

   /* ##-2- Configure the NVIC for DMA ######################################### */

   /* NVIC configuration for DMA transfer complete interrupt */

   HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);

   HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);

}

This is the function to set-up the values to send on PWM in the main() with parameter 20000u corresponding to 20KHz.

void DMA_Config2(uint32_t DmaFreq)

{

   uint8_t idx = 0U;

    /* Load buffer for DMA */

    for (idx = 0; idx < DMA_PWM_MAX_BUF; idx++)

    {

       /* Compute CCR1 value to generate a duty cycle [%] */

       aCCValue_Buffer_right[idx] = (uint32_t)(((uint32_t) (100-idx) * (uwTimerPeriod - 1)) / 100);

    }

   /*##-1- Initialise Timer settings ##########################################*/

   TimHandle2.Instance = TIM2;

   TimHandle2.Init.Period           = uwTimerPeriod;

   TimHandle2.Init.RepetitionCounter = 1;

   TimHandle2.Init.Prescaler        = 0;

   TimHandle2.Init.ClockDivision    = 0;

   TimHandle2.Init.CounterMode      = TIM_COUNTERMODE_UP;

   TimHandle2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

   if (HAL_TIM_PWM_Init(&TimHandle2) != HAL_OK)

   {

    /* Initialization Error */

    Error_Handler();

   }

   /*##-2- Configure the PWM channel 3 ########################################*/

   sConfig2.OCMode      = TIM_OCMODE_PWM1;

   sConfig2.OCPolarity  = TIM_OCPOLARITY_HIGH;

   sConfig2.Pulse       = aCCValue_Buffer_right[0];

   sConfig2.OCNPolarity = TIM_OCNPOLARITY_HIGH;

   sConfig2.OCFastMode  = TIM_OCFAST_DISABLE;

   sConfig2.OCIdleState = TIM_OCIDLESTATE_RESET;

   sConfig2.OCNIdleState = TIM_OCNIDLESTATE_RESET;

   if (HAL_TIM_PWM_ConfigChannel(&TimHandle2, &sConfig2, TIM_CHANNEL_4) != HAL_OK) /* PA3 */

   {

    /* Configuration Error */

    Error_Handler();

   }

   /*##-3- Start PWM signal generation in DMA mode ##############################*/

   if (HAL_TIM_PWM_Start_DMA(&TimHandle2, TIM_CHANNEL_4, aCCValue_Buffer_right, DMA_PWM_MAX_BUF) != HAL_OK) /* PA3 */

   {

    /* Starting Error */

    Error_Handler();

   }

}

1 ACCEPTED SOLUTION

Accepted Solutions
Imen GH
ST Employee

​Hello,

You will find attached my file STM32f7xx_hal_msp.c

The contents of this file was automatically generated ( I didn't add or change anything )

Regards

View solution in original post

18 REPLIES 18

I don't speak the Cube/HAL gobbledygook, but

   /* Set the parameters to be configured */

   hdma_tim1.Init.Channel = DMA_CHANNEL_4; /* PA3 TIM2_CH4 */

is IMO incorrect, I believe you want to set the channel in given stream in DMA, corresponding to given trigger from TIM, ie.

0690X00000Bycj8QAB.png

Reading out and checking the DMA registers is always the ultimate way to find out what the mcu is actually doing.

JW

I have changed like suggested and the IRQ is still not called.

Read out and check/post the TIM and DMA registers content.

JW

TIM2

0690X00000D8APTQA3.jpg0690X00000D8AP4QAN.jpg

As I see all SxFCR.FEIE are set to 0, no IRQ enabled...

VMoca.1
Associate II

As I see in HAL_TIM_Base_MspInit() i get a warning

/* Several peripheral DMA handle pointers point to the same DMA handle.

    Be aware that there is only one stream to perform all the requested DMAs. */

I am trying to set-up two DMAs on PA2 and 3 which are both on DMA1 Channel 3 and only the stream is different (Stream1 for PA2 and Stream6 on PA3).

See code below

if(tim_baseHandle->Instance==TIM2)

 {

 /* USER CODE BEGIN TIM2_MspInit 0 */

 /* USER CODE END TIM2_MspInit 0 */

   /* TIM2 clock enable */

   __HAL_RCC_TIM2_CLK_ENABLE();

   /* TIM2 DMA Init */

   /* TIM2_UP_CH3 Init */

   hdma_tim2_up_ch3.Instance = DMA1_Stream1;

   hdma_tim2_up_ch3.Init.Channel = DMA_CHANNEL_3;

   hdma_tim2_up_ch3.Init.Direction = DMA_MEMORY_TO_PERIPH;

   hdma_tim2_up_ch3.Init.PeriphInc = DMA_PINC_DISABLE;

   hdma_tim2_up_ch3.Init.MemInc = DMA_MINC_ENABLE;

   hdma_tim2_up_ch3.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;

   hdma_tim2_up_ch3.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

   hdma_tim2_up_ch3.Init.Mode = DMA_NORMAL;

   hdma_tim2_up_ch3.Init.Priority = DMA_PRIORITY_LOW;

   hdma_tim2_up_ch3.Init.FIFOMode = DMA_FIFOMODE_ENABLE;

   hdma_tim2_up_ch3.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

   hdma_tim2_up_ch3.Init.MemBurst = DMA_MBURST_SINGLE;

   hdma_tim2_up_ch3.Init.PeriphBurst = DMA_PBURST_SINGLE;

   if (HAL_DMA_Init(&hdma_tim2_up_ch3) != HAL_OK)

   {

     Error_Handler();

   }

   /* Several peripheral DMA handle pointers point to the same DMA handle.

    Be aware that there is only one stream to perform all the requested DMAs. */

   __HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_UPDATE],hdma_tim2_up_ch3);

   __HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_CC3],hdma_tim2_up_ch3);

   /* TIM2_CH2_CH4 Init */

   hdma_tim2_ch2_ch4.Instance = DMA1_Stream6;

   hdma_tim2_ch2_ch4.Init.Channel = DMA_CHANNEL_3;

   hdma_tim2_ch2_ch4.Init.Direction = DMA_MEMORY_TO_PERIPH;

   hdma_tim2_ch2_ch4.Init.PeriphInc = DMA_PINC_DISABLE;

   hdma_tim2_ch2_ch4.Init.MemInc = DMA_MINC_ENABLE;

   hdma_tim2_ch2_ch4.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;

   hdma_tim2_ch2_ch4.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

   hdma_tim2_ch2_ch4.Init.Mode = DMA_NORMAL;

   hdma_tim2_ch2_ch4.Init.Priority = DMA_PRIORITY_LOW;

   hdma_tim2_ch2_ch4.Init.FIFOMode = DMA_FIFOMODE_ENABLE;

   hdma_tim2_ch2_ch4.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

   hdma_tim2_ch2_ch4.Init.MemBurst = DMA_MBURST_SINGLE;

   hdma_tim2_ch2_ch4.Init.PeriphBurst = DMA_PBURST_SINGLE;

   if (HAL_DMA_Init(&hdma_tim2_ch2_ch4) != HAL_OK)

   {

     Error_Handler();

   }

   /* Several peripheral DMA handle pointers point to the same DMA handle.

    Be aware that there is only one stream to perform all the requested DMAs. */

   __HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_CC2],hdma_tim2_ch2_ch4);

   __HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_CC3],hdma_tim2_ch2_ch4);

}

}

Your problem is with DMA1 Stream 6, and you post registers only for stream 0 to 5...

So you don't want to get help with this or what?

JW

/* Several peripheral DMA handle pointers point to the same DMA handle.

    Be aware that there is only one stream to perform all the requested DMAs. */

Okay, so this may be a Cube/HAL limitation.

Ditch Cube, go for the registers.

JW