Hal of STM32 HAL Library_ Detailed explanation of delay

1, Implementation principle

The code generated automatically by MX is extracted from the following part

/*stm32f1xx_it.c*/
//sysTick interrupt function
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}



/*stm32f1xx_hal.c*/
//SysTick initialization function (HAL_Init() calls this function)
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    return HAL_ERROR;
  }

  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);//Set interrupt
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }

  /* Return function status */
  return HAL_OK;
}
//The interrupt function will call the change function once and increase uwTick by 1
__weak void HAL_IncTick(void)
{
  uwTick += uwTickFreq;
}
//Get uwTick value
__weak uint32_t HAL_GetTick(void)
{
  return uwTick;
}
//The protagonist of this discussion is the ms delay function
__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();//Record the current uwTick value first
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY) //HAL_MAX_DELAY is 0xffffffff. Generally, there will be no problem with this one
  {
    wait += (uint32_t)(uwTickFreq); //Uwtickerfreq is generally defined as 0x01
  }

//Because the systick interrupt will constantly modify the uwTick value, when the uwTick value is larger than the uwTick value recorded at the beginning, the wait value, that is, the ms value, will jump out of the whlie loop and return
  while ((HAL_GetTick() - tickstart) < wait) 
  {
  }
}

2, Input parameter limit

If there are changes to uwtickerfreq, you need to pay attention. The following default uwtickerfreq is unchanged and the value is 1.

Before introducing the following questions, the value that can be entered under reasonable judgment should be (0xffffffff - current uwTick). Then, when uwTick is about to be counted to the maximum, Hal_ Can delay () still be used? With this question, I simply did an experiment.

3, Validity Issue

The maximum value of unsigned 32-bit integer is 0xffffffff ﹐ and the decimal system is 4294967295. From 0ms to 4294967295ms, it takes 4294967.295 s and 1193 hours, that is, more than 49 days. To verify the validity of the experiment, uwTick will start counting from 0 again after 49 days. If Hal is called before_ Delay(), then tickstart , is a value close to the maximum value. After that, when uwTick is compared with tickstart , is it always less than the wait value? Will it enter an infinite cycle?

Here's an experiment:

uint32_t testn;
uint32_t tickss;//Used to view the value of uwTick when debug ging

testn=0xfffffffe;//The simulated uwTick value has been counted to the end
tickss=0;
while ((tickss - testn) < 100)//Delay 100ms
{
	tickss = HAL_GetTick();
}

After the experiment, it is found that when the ticks value is 98, it will exit the while loop. It means that (ticks - testn), that is, (0x62 - 0xfffffffe) is less than 100 ; does not hold.

Why?

Calculate with calculator (PC ¢ is 64 bits, so subtract 0xFFFF ffff fffe):

In other words, after subtraction, the memory is still stored as an unsigned 32-bit value, and the value is 100.

In fact, it is conceivable that you are familiar with the storage mechanism of unsigned integers.

It can be seen that HAL_Delay() can be used permanently.

Tags: Embedded system stm32

Posted by krispykreme on Thu, 19 May 2022 18:40:39 +0300