Skip to main content
wh_it_11193
Associate III
September 22, 2017
Question

Timer DMA Burst mode (arbitrary waveform)

  • September 22, 2017
  • 3 replies
  • 4996 views
Posted on September 22, 2017 at 14:25

Dear all,

I'm having a problem creating a arbitrary waveform using timer 1, MCU STM32L476RG. I use STM32CubeMX (4.21.0) to generate all initialization code after which I try to start a DMA transfer from memory to the timer 1 peripheral. I'm partly successful doing this. 

I created a array of 6 words for two waveform patterns to be send to TIM1  channel  1  (TIM1_ARR, TIM1_RCR, TIM1_CCR1) This is how the basics look

uint32_t aSRC_Buffer[6] = { 100, 2, 15, 100, 8, 50 };  /// ARR, RCR, CCR1  x 2

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) ;

 HAL_TIM_DMABurst_WriteStart(&htim1, TIM_DMABASE_ARR, TIM_DMA_UPDATE, (uint32_t*) aSRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS);

With this code only the first pattern is generated. changing TIM_DMABURSTLENGTH_3TRANSFERS to TIM_DMABURSTLENGTH_6TRANSFERS does not work either (seems right if my assumption is correct, see below). 

I don't understand the relation between the complete DMA buffer size (mem) and the TIM registers update. Right now I assume that setting TIM_DMABURSTLENGTH_3TRANSFERS means the three TIM registers starting at ARR are updated. But how do I set the total buffer size to use. I have tried to set  DMA1_Channel6->CNDTR = 6;  in the HAL_TIM_Base_MspInit routine but that didn't help either. I'm lost.... Is there anyone that can explain to me what I am missing here. 

some cubemx settings are :

DMA1 -> DMA1 channel 6 -> memory to peripheral -> priority high

                Mode normal      Increment address -> memory only

                Data width word

Partly generated code is

if(htim_base->Instance==TIM1)

  {

    /* Peripheral clock enable */

    __HAL_RCC_TIM1_CLK_ENABLE();

 

    hdma_tim1_up.Instance = DMA1_Channel6;

    hdma_tim1_up.Init.Request = DMA_REQUEST_7;

    hdma_tim1_up.Init.Direction = DMA_MEMORY_TO_PERIPH;

    hdma_tim1_up.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_tim1_up.Init.MemInc = DMA_MINC_ENABLE;

    hdma_tim1_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;

    hdma_tim1_up.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

    hdma_tim1_up.Init.Mode = DMA_NORMAL;

    hdma_tim1_up.Init.Priority = DMA_PRIORITY_HIGH;

    if (HAL_DMA_Init(&hdma_tim1_up) != HAL_OK)

    {

      _Error_Handler(__FILE__, __LINE__);

    }

 

    __HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_UPDATE],hdma_tim1_up);

    /* TIM1 interrupt Init */

    HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);

}

  

Thanks in advance,

Wim

    This topic has been closed for replies.

    3 replies

    John Craven
    Senior
    September 24, 2017
    Posted on September 24, 2017 at 03:25

    I found the same issue.

    I traced it to the

    HAL_TIM_DMABurst_WriteStart method.

    If you used AN4776:General-purpose timer cookbook, Section 5as a reference, the sample code (using LL)

    for a burst of 3 sets of 3 registers;

    The sample sets DMA CNDTR to 9 words

    /* Write to DMA1 Channel5 number of data’s register */
     DMA1_Channel5->CNDTR = 9;�?�?�?�?

    The sample s

    ets

    each burst 3 words

    /* Select the DMA base register and DMA burst length */
     TIM1->DCR = TIM_DMABase_ARR | TIM_DMABurstLength_3Transfers;�?�?�?�?

    InHAL, youstart a burst transfer with;

    HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, 
     uint32_t BurstBaseAddress, 
     uint32_t BurstRequestSrc,
     uint32_t *BurstBuffer,
     uint32_t BurstLength)�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

    In older HAL versions, this method put burstlength into both CNDTR and DCR;

    HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, BurstBuffer);
    htim->Instance->DCR = BurstBaseAddress | BurstLength;�?�?�?�?�?�?

    I wrote a patch when i had this issue.

    But I just looked in new HAL that came with F3 FW1.9.0 and they seem to have fixed this;

    HAL_TIM_DMABurst_WriteStartcalls a new HAL_TIM_DMABurst_MultiWriteStart

    HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim,
     uint32_t BurstBaseAddress, 
     uint32_t BurstRequestSrc,
     uint32_t *BurstBuffer,
     uint32_t BurstLength)
    {
     return HAL_TIM_DMABurst_MultiWriteStart(htim, BurstBaseAddress, BurstRequestSrc, BurstBuffer, BurstLength, ((BurstLength) >> 8U) + 1U);
    }
    
    HAL_TIM_DMABurst_MultiWriteStart(TIM_HandleTypeDef *htim, 
     uint32_t BurstBaseAddress, 
     uint32_t BurstRequestSrc,
     uint32_t* BurstBuffer,
     uint32_t BurstLength,
     uint32_t DataLength)�?�?�?�?�?�?
    {
    .
    .
    .
    HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, DataLength);
    .
    .
    .
    htim->Instance->DCR = BurstBaseAddress | BurstLength; 
    �?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?.
    .
    .
    }�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

    Try updating your HAL FW version. In your case you should call;

    #define buffersize 6
    uint32_t aSRC_Buffer[buffersize ] = { 100, 2, 15, 100, 8, 50 }; /// ARR, RCR, CCR1 x 2
     
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) ;
    HAL_TIM_DMABurst_MultiWriteStart(&htim1, 
     TIM_DMABASE_ARR,
     TIM_DMA_UPDATE,
     (uint32_t*)aSRC_Buffer,
     TIM_DMABURSTLENGTH_3TRANSFERS,
     buffersize );�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

    wh_it_11193
    Associate III
    September 25, 2017
    Posted on September 25, 2017 at 13:13

    Hi John,

    Thank you very much for explaining the ins and outs. You gave me the assurance that I'm not crazy -:) It seems that version 1.0.9  is only supporting the STM32Fxx series for burst multi write and read. Anyway , the Lxx devices are not supported yet. I think I will just have to create a patch to get thing going.

    Thanks. 

    John Craven
    Senior
    September 25, 2017
    Posted on September 25, 2017 at 13:52

    It should be pretty easy to take the MultiWriteStart from the current F3 HAL fw and adapt it to your Lxx model.

    wh_it_11193
    Associate III
    September 25, 2017
    Posted on September 25, 2017 at 14:03

    I Agree,

    Again thanks!

    joe bullard
    Visitor II
    February 12, 2018
    Posted on February 12, 2018 at 23:35

    I'm having the same issue. I'm using an L4 series part and I don't see the multiWriteStart in the HAL.     Where and how in the code did you put in the patch to incorporate the dataLength ?  

    Thanks!

    Aleksey Zhurkin
    Visitor II
    February 28, 2018
    Posted on February 28, 2018 at 09:31

    Hello!

    You can open ~/STM32Cube/Repository/STM32Cube_FW_F3_V1.9.0/Drivers/STM32F3xx_HAL_Driver/Src/stm32f3_hal_tim.c

    And simple copy HAL_TIM_Burst_MultiWriteStart.

    Different between

    HAL_TIM_Burst_MultiWriteStart

    and

    HAL_TIM_Burst_WriteStart 

    is that:

    HAL_DMA_Start_IT(...,...,...., ((BurstLength) >> 8) +1) // 

    HAL_TIM_Burst_WriteStart

    HAL_DMA_Start_IT(

    ...,...,...., DataLength)                   // HAL_TIM_Burst_MultiWriteStart

    Romain Mahieu
    Associate
    March 2, 2018
    Posted on March 02, 2018 at 19:07

    No its wrong, BurstLength is not DataLength, copy HAL_TIM_DMABurst_MultiWriteStart from HAL_F3 into your USER SECTION CODE (to preserve HAL sources), use it and remove it when HAL_L4 will be upgraded.