讨论:HAL库的HAL_Delay函数bug问题

2019-07-20 14:29发布

STM32的HAL库提供了一个HAL_Delay函数,使用Systick中断来实现,实现过程如下:

1.首先是一个Systick中断配置函数SysTick_Config,该函数实现的是Systick中断每隔ticks中断一次。。。。。
[mw_shl_code=c,true]__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     /* Function successful */
}[/mw_shl_code]

2.其次依次是:HAL_SYSTICK_Config函数和HAL_InitTick函数。。。。
HAL_InitTick函数调用之后,实际上就是配置每隔1ms中断一次,最终调用的是SysTick_Config函数进行配置。而这个函数是在HAL_Init函数中调用,在系统初始化之后会调用。


[mw_shl_code=c,true]uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
   return SysTick_Config(TicksNumb);
}

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  /*Configure the SysTick to have interrupt in 1ms time basis*/
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  /*Configure the SysTick IRQ priority */
  HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0);

  /* Return function status */
  return HAL_OK;
}[/mw_shl_code]

3.经过前面2步骤,开启了Systick定时器,每隔1ms中断一次。。。
而中断服务函数和相关逻辑函数是这样的:
[mw_shl_code=c,true]void SysTick_Handler(void)
{
  HAL_IncTick();
}

static __IO uint32_t uwTick;

__weak void HAL_IncTick(void)
{
  uwTick++;
}


__weak uint32_t HAL_GetTick(void)
{
  return uwTick;
}[/mw_shl_code]
定义了一个32位的全局变量uwTick,每次中断(1ms),变量uwTick增加1.。。。


4.最后HAL_Delay函数是这样的:
[mw_shl_code=c,true]__weak void HAL_Delay(__IO uint32_t Delay)
{
  uint32_t tickstart = 0;
  tickstart = HAL_GetTick();
  while((HAL_GetTick() - tickstart) < Delay)
  {
  }
}[/mw_shl_code]

通过HAL_GetTick();函数获取此时uwTick的值赋给tickstart,然后使用while循环不断调用HAL_GetTick() 函数获取当前uwTick值减掉tickstart,差值就是定时的ms数。。。


问题来了,如果32位的uwTick越界了怎么办? 32位uwTick的值,每1ms增加1,最大只有几十天就越界了。。。。
例如,如果还有1s就越界,如果此时此刻,我们调用HAL_Delay延时10s,那么肯定就乱套了。。。。
ST不应该会犯如此大的错误吧?不知道是我看少了,还是确实是一个Bug,大家讨论一下。。。。




友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。