STMicroelectronics / STM32CubeF3

STM32Cube MCU Full Package for the STM32F3 series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on all boards provided by ST (Nucleo, Evaluation and Discovery Kits))
Other
141 stars 54 forks source link

HAL_TIM_DMABurst_WriteStart does work after V1.11.2 #6

Closed tiantian1645 closed 3 years ago

tiantian1645 commented 3 years ago

Caution The Issues are strictly limited for the reporting of problem encountered with the software provided in this project. For any other problem related to the STM32 product, the performance, the hardware characteristics and boards, the tools the environment in general, please post a topic in the ST Community/STM32 MCUs forum.

Describe the set-up

Describe the bug After update this lib from V1.11.1 to V1.11.2, the HAL_TIM_DMABurst_WriteStart function does not work as noraml.

How To Reproduce

  1. use V1.11.1 and conf Timer and DMA as this:

    
    static void MX_TIM16_Init(void)
    {
    
    /* USER CODE BEGIN TIM16_Init 0 */
    
    /* USER CODE END TIM16_Init 0 */
    
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
    
    /* USER CODE BEGIN TIM16_Init 1 */
    
    /* USER CODE END TIM16_Init 1 */
    htim16.Instance = TIM16;
    htim16.Init.Prescaler = MOTOR_PSC;
    htim16.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim16.Init.Period = MOTOR_ARR;
    htim16.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim16.Init.RepetitionCounter = MOTOR_PCR;
    htim16.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    if (HAL_TIM_Base_Init(&htim16) != HAL_OK) {
        Error_Handler();
    }
    if (HAL_TIM_PWM_Init(&htim16) != HAL_OK) {
        Error_Handler();
    }
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = MOTOR_PUL;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
    if (HAL_TIM_PWM_ConfigChannel(&htim16, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
        Error_Handler();
    }
    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
    sBreakDeadTimeConfig.DeadTime = 0;
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
    sBreakDeadTimeConfig.BreakFilter = 0;
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
    if (HAL_TIMEx_ConfigBreakDeadTime(&htim16, &sBreakDeadTimeConfig) != HAL_OK) {
        Error_Handler();
    }
    /* USER CODE BEGIN TIM16_Init 2 */
    
    /* USER CODE END TIM16_Init 2 */
    HAL_TIM_MspPostInit(&htim16);
    }

/**

  1. start Timer PWM and call HAL_TIM_DMABurst_WriteStart

    HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);
    HAL_TIM_DMABurst_WriteStart(&htim16, TIM_DMABASE_ARR, TIM_DMA_UPDATE, (uint32_t *)gMotor_SRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS);
  2. in HAL_TIM_PeriodElapsedCallback call HAL_TIM_DMABurst_WriteStart again

    callback_cnt++;
    if (callback_cnt > 10000) {
    HAL_TIM_DMABurst_WriteStop(&htim16, TIM_DMA_UPDATE);
    HAL_TIM_PWM_Stop(&htim16, TIM_CHANNEL_1);
    } else {
    HAL_TIM_DMABurst_WriteStart(&htim16, TIM_DMABASE_ARR, TIM_DMA_UPDATE, (uint32_t *)gMotor_SRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS);
    }
  3. switch to V1.11.2 and HAL_TIM_PeriodElapsedCallback will only Enetr 3 times

tiantian1645 commented 3 years ago

htim->DMABurstState = HAL_DMA_BURST_STATE_READY; only call in function like Init and Stop When enter HAL_TIM_PeriodElapsedCallback the htim->DMABurstState is HAL_DMA_BURST_STATE_BUSY

P.S. In Drivers\STM32F3xx_HAL_Driver\Inc\stm32f3xx_hal_tim.h I found an unknown word trom

  1090,130: #define TIM_DMABURSTLENGTH_1TRANSFER       0x00000000U                          /*!< The transfer is done to 1 register starting trom TIMx_CR1 + TIMx_DCR.DBA   */
  1091,131: #define TIM_DMABURSTLENGTH_2TRANSFERS      0x00000100U                          /*!< The transfer is done to 2 registers starting trom TIMx_CR1 + TIMx_DCR.DBA  */
  1092,131: #define TIM_DMABURSTLENGTH_3TRANSFERS      0x00000200U                          /*!< The transfer is done to 3 registers starting trom TIMx_CR1 + TIMx_DCR.DBA  */
  1093,131: #define TIM_DMABURSTLENGTH_4TRANSFERS      0x00000300U                          /*!< The transfer is done to 4 registers starting trom TIMx_CR1 + TIMx_DCR.DBA  */
  1094,131: #define TIM_DMABURSTLENGTH_5TRANSFERS      0x00000400U                          /*!< The transfer is done to 5 registers starting trom TIMx_CR1 + TIMx_DCR.DBA  */
  1095,131: #define TIM_DMABURSTLENGTH_6TRANSFERS      0x00000500U                          /*!< The transfer is done to 6 registers starting trom TIMx_CR1 + TIMx_DCR.DBA  */
  1096,131: #define TIM_DMABURSTLENGTH_7TRANSFERS      0x00000600U                          /*!< The transfer is done to 7 registers starting trom TIMx_CR1 + TIMx_DCR.DBA  */
  1097,131: #define TIM_DMABURSTLENGTH_8TRANSFERS      0x00000700U                          /*!< The transfer is done to 8 registers starting trom TIMx_CR1 + TIMx_DCR.DBA  */
  1098,131: #define TIM_DMABURSTLENGTH_9TRANSFERS      0x00000800U                          /*!< The transfer is done to 9 registers starting trom TIMx_CR1 + TIMx_DCR.DBA  */
  1099,132: #define TIM_DMABURSTLENGTH_10TRANSFERS     0x00000900U                          /*!< The transfer is done to 10 registers starting trom TIMx_CR1 + TIMx_DCR.DBA */
  1100,132: #define TIM_DMABURSTLENGTH_11TRANSFERS     0x00000A00U                          /*!< The transfer is done to 11 registers starting trom TIMx_CR1 + TIMx_DCR.DBA */
  1101,132: #define TIM_DMABURSTLENGTH_12TRANSFERS     0x00000B00U                          /*!< The transfer is done to 12 registers starting trom TIMx_CR1 + TIMx_DCR.DBA */
  1102,132: #define TIM_DMABURSTLENGTH_13TRANSFERS     0x00000C00U                          /*!< The transfer is done to 13 registers starting trom TIMx_CR1 + TIMx_DCR.DBA */
  1103,132: #define TIM_DMABURSTLENGTH_14TRANSFERS     0x00000D00U                          /*!< The transfer is done to 14 registers starting trom TIMx_CR1 + TIMx_DCR.DBA */
  1104,132: #define TIM_DMABURSTLENGTH_15TRANSFERS     0x00000E00U                          /*!< The transfer is done to 15 registers starting trom TIMx_CR1 + TIMx_DCR.DBA */
  1105,132: #define TIM_DMABURSTLENGTH_16TRANSFERS     0x00000F00U                          /*!< The transfer is done to 16 registers starting trom TIMx_CR1 + TIMx_DCR.DBA */
  1106,132: #define TIM_DMABURSTLENGTH_17TRANSFERS     0x00001000U                          /*!< The transfer is done to 17 registers starting trom TIMx_CR1 + TIMx_DCR.DBA */
  1107,132: #define TIM_DMABURSTLENGTH_18TRANSFERS     0x00001100U                          /*!< The transfer is done to 18 registers starting trom TIMx_CR1 + TIMx_DCR.DBA */
ASELSTM commented 3 years ago

Hi @tiantian1645,

Thank you for this report. For a better understanding of the issue and in order to reproduce the same behavior, would you please share the whole IOC file if it is possible, so that we can use it to reproduce the issue.

Regarding the unknown word "trom" you have found within the stm32f3xx_hal_tim.h driver, this is a typo and it should be replaced by "from". An internal bug tracker will be raised to fix this. Thank you again for bringing this issue to our attention.

With regards,

tiantian1645 commented 3 years ago

Hello: Here is my ioc file https://pastebin.ubuntu.com/p/ZpDsp8ZZpz/ I use TIM16 CH1 as PWM output. You can see another example in your STM TIM_DMABurst.
Or you can refer AN4776 General-purpose timer cookbook for STM32 microcontrollers - Section 5 Arbitrary waveform generation using timer DMA-burst feature. Please test before release. Thank you

ASELSTM commented 3 years ago

Hi @tiantian1645,

A new DMABurstState field has been added in the global structure definition of TIM_HandleTypeDef in order to manage DMA Burst operation state. Checks within HAL_TIM_DMABurst_MultiWriteStart and HAL_TIM_DMABurst_MultiWriteStop functions are now done on DMABurstState and no longer on the TIM operation state, htim->state. TIM operation state and DMA Burst operation state are now managed separately.

Actually, a HAL_TIM_DMABurst_WriteStopis required to enable once again a DMA Burst start write operation. Then, to fix the issue HAL_TIM_PeriodElapsedCallback should be updated as following :

callback_cnt++;
if (callback_cnt > 10000) {
    HAL_TIM_DMABurst_WriteStop(&htim16, TIM_DMA_UPDATE);
    HAL_TIM_PWM_Stop(&htim16, TIM_CHANNEL_1);
} else {
+   HAL_TIM_DMABurst_WriteStop(&htim16, TIM_DMA_UPDATE);
    HAL_TIM_DMABurst_WriteStart(&htim16, TIM_DMABASE_ARR, TIM_DMA_UPDATE, (uint32_t *)gMotor_SRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS);
}

Hope this will help you.

With regards,

tiantian1645 commented 3 years ago

Hello: What the hell??? Use stop timer code in call back hit myself? Why do not I direct call htim->DMABurstState = HAL_DMA_BURST_STATE_READY;?

Than you.

ASELSTM commented 3 years ago

Hi @tiantian1645,

Indeed, it is also possible to make a direct call htim->DMABurstState = HAL_DMA_BURST_STATE_READY; but it is not recommended.

With regards,

ASELSTM commented 3 years ago

Hi @tiantian1645,

The typos you reported has been fixed in the frame of latest version of the STM32CubeF3 published on GitHub.

Please allow me then to close this thread and thank you again for having reported.

With regards,