2020-02-05 05:03 AM
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();
}
}
Solved! Go to Solution.
2020-02-06 10:20 PM
Hello,
I have managed to set-up the desired PA3 to use DMA but only with Steam7.
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_InitStruct;
static DMA_HandleTypeDef hdma_tim;
/* Configure TIM2_Channel3 in output, push-pull & alternate function mode */
GPIO_InitStruct.Pin = GPIO_PIN_3; /* PA3 */
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Set the parameters to be configured on DMA */
hdma_tim.Init.Channel = DMA_CHANNEL_3; /*PA2 and PA3 have the same channel*/
hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD ;
hdma_tim.Init.Mode = DMA_CIRCULAR;
hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
hdma_tim.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
/* Set hdma_tim instance */
hdma_tim.Instance = DMA1_Stream7;
/* Link hdma_tim to hdma[TIM_DMA_ID_CC4] (channel3) */
__HAL_LINKDMA(htim, hdma[TIM_DMA_ID_CC4], hdma_tim);
/* 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_Stream7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn);
}
and
void DMA_Config(uint32_t DmaFreq)
{
uint8_t idx = 0U;
/* Compute the value of ARR regiter to generate signal frequency at 20.00 Khz */
uwTimerPeriod = (uint32_t)(((SystemCoreClock/2) / DmaFreq) - 1);
/* Load buffer for DMA */
for (idx=0; idx < DMA_PWM_MAX_BUF; idx++)
{
/* Compute CCR1 value to generate a duty cycle [%] */
aCCValue_Buffer_left[idx] = (uint32_t)(((uint32_t) idx * (uwTimerPeriod - 1)) / 100);
}
/*##-1- Initialise Timer settings ##########################################*/
TimHandle.Instance = TIM2;
TimHandle.Init.Period = uwTimerPeriod;
TimHandle.Init.RepetitionCounter = 1;
TimHandle.Init.Prescaler = 0;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-2- Configure the PWM channel 3 ########################################*/
sConfig.OCMode = TIM_OCMODE_PWM1;
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfig.Pulse = aCCValue_Buffer_left[0];
sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfig.OCFastMode = TIM_OCFAST_DISABLE;
sConfig.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_4) != HAL_OK) /* PA3 */
{
/* Configuration Error */
Error_Handler();
}
/*##-3- Start PWM signal generation in DMA mode ##############################*/
if (HAL_TIM_PWM_Start_DMA(&TimHandle, TIM_CHANNEL_4, aCCValue_Buffer_left, DMA_PWM_MAX_BUF) != HAL_OK) /* PA2 */
{
/* Starting Error */
Error_Handler();
}
}
2020-02-06 10:21 PM
I will try to merge the PA2 and PA3 implementation next.
Thank you for your support
2020-02-06 10:23 PM
The CubeMX is blocking selecting both CH3 TIM2_CH3 (Stream1) and CH4 TIM2_CH3(Stream7)...
2020-02-07 01:12 AM
> I have managed to set-up the desired PA3 to use DMA but only with Steam7.
Oh, that's an unexpected twist.
Do you use also CH2 on that timer for DMA?
JW
2020-02-14 07:00 AM
2020-02-16 11:59 PM
Hello,
I cannot find the HAL_TIM_PWM_Init() and HAL_TIM_MspPostInit() functions content from your configuration.
Is it possible to send me this file two?
Thank you.
2020-02-17 02:16 AM
Hello,
Could you please send me the HAL_TIM_MspPostInit() and the HAL_TIM_PWM_MspInit() functions as well.
Thank you.
2020-02-21 12:41 AM
2020-02-21 01:50 AM
Ok, thank you. It works now. I have used different variables in the code (initiated in tim.c with a name and used it in DMA_Config, another variable) and it was not the same addresses :D
Now it is working.