STMicroelectronics / STM32CubeL4

STM32Cube MCU Full Package for the STM32L4 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
259 stars 151 forks source link

Assert failed when using hardware timer as HAL Timebase Source #49

Closed fronders closed 2 years ago

fronders commented 2 years ago

If hardware timer is selected as HAL timebase source HAL_NVIC_SetPriority() results in assert failed on PreemptPriority argument invalid value: assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));

Describe the set-up

Describe the bug The following code gets generated for HAL_InitTick() in stm32l4xx_hal_timebase_tim.c when TIM7 (or any other hw timer) is selected as HAL timebase source:

HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  RCC_ClkInitTypeDef    clkconfig;
  uint32_t              uwTimclock = 0;
  uint32_t              uwPrescalerValue = 0;
  uint32_t              pFLatency;
  /*Configure the TIM7 IRQ priority */
  HAL_NVIC_SetPriority(TIM7_IRQn, TickPriority ,0);

  /* Enable the TIM7 global Interrupt */
  HAL_NVIC_EnableIRQ(TIM7_IRQn);

  /* Enable TIM7 clock */
  __HAL_RCC_TIM7_CLK_ENABLE();

  /* Get clock configuration */
  HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);

  /* Compute TIM7 clock */
  uwTimclock = HAL_RCC_GetPCLK1Freq();
  /* Compute the prescaler value to have TIM7 counter clock equal to 1MHz */
  uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);

  /* Initialize TIM7 */
  htim7.Instance = TIM7;

  /* Initialize TIMx peripheral as follow:
  + Period = [(TIM7CLK/1000) - 1]. to have a (1/1000) s time base.
  + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
  + ClockDivision = 0
  + Counter direction = Up
  */
  htim7.Init.Period = (1000000U / 1000U) - 1U;
  htim7.Init.Prescaler = uwPrescalerValue;
  htim7.Init.ClockDivision = 0;
  htim7.Init.CounterMode = TIM_COUNTERMODE_UP;

  if(HAL_TIM_Base_Init(&htim7) == HAL_OK)
  {
    /* Start the TIM time Base generation in interrupt mode */
    return HAL_TIM_Base_Start_IT(&htim7);
  }

  /* Return function status */
  return HAL_ERROR;
}

It does not set the selected TickPriority value to uwTickPrio variable which then fails the check inside HAL_NVIC_SetPriority() . It can be fixed by adding uwTickPrio = TickPriority; after calling HAL_NVIC_SetPriority() as seen in HAL_InitTick() inside stm32l4xx_hal.c

  /*Configure the TIM7 IRQ priority */
  HAL_NVIC_SetPriority(TIM7_IRQn, TickPriority ,0);
  uwTickPrio = TickPriority;

  /* Enable the TIM7 global Interrupt */
  HAL_NVIC_EnableIRQ(TIM7_IRQn);

  /* Enable TIM7 clock */
  __HAL_RCC_TIM7_CLK_ENABLE();

P. S. I have seen this issue come up across different MCU families (WB and F4 confirmed too), can you guys check all of the families at once?

fronders commented 2 years ago

It actually makes more sense to reverse the order of these two lines:

uwTickPrio = TickPriority;
HAL_NVIC_SetPriority(TIM7_IRQn, TickPriority ,0);

for BOTH stm32l4xx_hal.c and stm32l4xx_hal_timebase_tim.c as otherwise the very first call to HAL_InitTick() always fails, as it is ALWAYS called with uwTickPrio as an argument: HAL_InitTick(uwTickPrio); can be seen in HAL_RCC_OscConfig() and HAL_RCC_ClockConfig()

P. S. This is relevant for ALL STM32 families

fronders commented 2 years ago

Just updated CubeMX to 6.4.0 and with newest CubeWB 1.13.0 the issue still exists P. S. I know this is not CubeWB repo

mikucukyilmaz commented 2 years ago

I also have the same issue with tim6 as timebase source ( tim1 or tim6 doesn't matter.)

uint32_t uwTickPrio = (1UL << __NVIC_PRIO_BITS); /* Invalid priority */

HAL_NVIC_SetPriority(TIM6_DAC_IRQn, uwTickPrio,0U);

Which causes the assert below.

[2021-12-16T10:58:36.090Z, +006389ms] Assert! File Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c:191 [2021-12-16T10:58:36.133Z, +006432ms] Kernel Information: FreeRTOS V10.3.1 [2021-12-16T10:58:36.133Z, +006432ms] HAL Driver Version: V1.13.2

So, inside the Drivers/STM32L4xx_HAL_Driver/Src/Src there is a file called stm32l4xx_hal_timebase_tim_template.c . Copy that source file to Core/Src Folder and rename it as stm32l4xx_hal_timebase_tim.c which overrides the Cube generated timebase init function. (You can also remove HAL_TIM_PeriodElapsedCallback() & TIM6_DAC_IRQHandler() from template because they already generated from cubemx. )This function doesn't try to call HAL_NVIC_SetPriority with an invalid priority level.

/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
  /*Configure the TIM6_DAC IRQ priority */
  HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0U);
  uwTickPrio = TickPriority;
}
else
{
  status = HAL_ERROR;
}

FreeRTOS overrides Systick, PendSV, and SVC calls so that issue doesn't cause any problem except annoying assert.

RKOUSTM commented 2 years ago

Hi @fronders,

Thank you for your contribution. You are absolutely right about this point. Indeed, the file stm32l4xx_hal_timebase_tim.c is not aligned with the stm32l4xx_hal_timebase_tim_template.c template which generates a crash.

Actually, the point you raised has already been dealt internally. The fix will be made available in the frame of a future release of CubeMX 6.5.0.

Now, as this issue is not directly related to some software component published within this repository (CMSIS, HAL, BSP, etc.) but rather to our ecosystem (namely the Cube MX tool), please allow me to close it.

Thank you for your contribution. We are looking forward to reading from you again.

With regards,

RKOUSTM commented 2 years ago

ST Internal Reference: 110035