cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with PWM + DMA on a STM32L431

patmar
Associate

Hello, I have a problem with a STM32L431CC generating a circular PWM burst with the DMA. I am using the Timer1 to generate 4 PWM signals on the Pins PA8, PA9, PA10, PA11. The systemclock of the Timer 1 is 80 MHz. The frequency of the PWM signal should be 20kHz. I have attached the code snipped were i configured the GPIO, Timer and DMA in the software. I get no PWM signal from the GPIO pins. When I manipulate the CCRx registers of the Timer1 with the ST Link debugger, I am able to generate PWM signals with the correct frequency and duty cycle. I suspect that the Timer1 do not make a DMA request and I am not able to find the failure. The DMA do not set any interrupt flags. Also when I manipulate the DMAR register of Timer1, I can see a valid PWM signal.

Would be great when someone can support me

Thanks Patrick

patmar_0-1762442802844.png

 

 

#define TIM1_PSC_INIT        0u        
#define TIM1_ARR_INIT        3999u    /* ~20 kHz at 80MHz systemclock frequency */
#define TIM1_RCR_INIT        0u

uint16_t volatile tim1_dma_buffer[] = {
    555,                /* CCR1 */
    1111,                /* CCR2 */
    2222,                /* CCR3 */
    3333                  /* CCR4 */
};    

LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
    LL_GPIO_InitTypeDef gpio = {0};
    gpio.Pin        = LL_GPIO_PIN_8 | LL_GPIO_PIN_9 | LL_GPIO_PIN_10 | LL_GPIO_PIN_11;
    gpio.Mode       = LL_GPIO_MODE_ALTERNATE;
    gpio.Speed      = LL_GPIO_SPEED_FAST;
    gpio.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    gpio.Pull       = LL_GPIO_PULL_NO;        
    gpio.Alternate  = LL_GPIO_AF_1;
    LL_GPIO_Init(GPIOA, &gpio);
	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
    LL_TIM_SetPrescaler(TIM1, TIM1_PSC_INIT);
    LL_TIM_SetAutoReload(TIM1, TIM1_ARR_INIT);
    LL_TIM_SetRepetitionCounter(TIM1, TIM1_RCR_INIT);
    LL_TIM_SetCounterMode(TIM1, LL_TIM_COUNTERMODE_UP);
    LL_TIM_SetClockDivision(TIM1, LL_TIM_CLOCKDIVISION_DIV1);
    LL_TIM_OC_InitTypeDef oc = {0};
    oc.OCMode       = LL_TIM_OCMODE_PWM1;
    oc.OCState      = LL_TIM_OCSTATE_DISABLE;
    oc.OCPolarity   = LL_TIM_OCPOLARITY_HIGH;
    oc.OCIdleState  = LL_TIM_OCIDLESTATE_LOW;
    oc.CompareValue = 0;
    LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH1, &oc);
    oc.CompareValue = 0;
    LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH2, &oc);
    oc.CompareValue = 0;
    LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH3, &oc);
    oc.CompareValue = 0;
    LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH4, &oc);
    LL_TIM_BDTR_InitTypeDef bdtr = {0};
    bdtr.OSSRState = LL_TIM_OSSR_DISABLE;
    bdtr.OSSIState = LL_TIM_OSSI_DISABLE;
    bdtr.LockLevel = LL_TIM_LOCKLEVEL_OFF;
    bdtr.DeadTime  = 0;
    bdtr.BreakState= LL_TIM_BREAK_DISABLE;
    bdtr.AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE;
    LL_TIM_BDTR_Init(TIM1, &bdtr);
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_6); 
	LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_6, (uint32_t)tim1_dma_buffer, (uint32_t)&TIM1->DMAR, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); 
    LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_6, 4); 
    LL_DMA_SetMemoryIncMode (DMA1, LL_DMA_CHANNEL_6, LL_DMA_MEMORY_INCREMENT); 
    LL_DMA_SetPeriphIncMode (DMA1, LL_DMA_CHANNEL_6, LL_DMA_PERIPH_NOINCREMENT); 
    LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MODE_CIRCULAR);
    LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PRIORITY_HIGH);
    LL_DMA_SetPeriphSize (DMA1, LL_DMA_CHANNEL_6, LL_DMA_PDATAALIGN_HALFWORD);   
    LL_DMA_SetMemorySize (DMA1, LL_DMA_CHANNEL_6, LL_DMA_MDATAALIGN_HALFWORD);   
	LL_TIM_ConfigDMABurst(TIM1, LL_TIM_DMABURST_BASEADDR_CCR1, LL_TIM_DMABURST_LENGTH_4TRANSFERS);
	LL_TIM_EnableDMAReq_UPDATE(TIM1);
	LL_TIM_EnableAllOutputs(TIM1);        
    LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1 | LL_TIM_CHANNEL_CH2 |
                                   LL_TIM_CHANNEL_CH3 | LL_TIM_CHANNEL_CH4);
	LL_TIM_EnableARRPreload(TIM1);
	LL_TIM_OC_DisablePreload(TIM1, LL_TIM_CHANNEL_CH1);
	LL_TIM_OC_DisablePreload(TIM1, LL_TIM_CHANNEL_CH2);
	LL_TIM_OC_DisablePreload(TIM1, LL_TIM_CHANNEL_CH3);
	LL_TIM_OC_DisablePreload(TIM1, LL_TIM_CHANNEL_CH4);
	LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_6);
	LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_6);
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_6); 
	LL_TIM_EnableCounter(TIM1); 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
waclawek.jan
Super User

Debug as usually: read out and check/post TIM and DMA registers content. 

Where do you set the DMA request selector? I don't understand the Cube/LL gobbledygook.

JW

View solution in original post

2 REPLIES 2
waclawek.jan
Super User

Debug as usually: read out and check/post TIM and DMA registers content. 

Where do you set the DMA request selector? I don't understand the Cube/LL gobbledygook.

JW

Thanks a lot for the hint with the DMA request selector. This was missing