C语言 HAL_Delay()陷入无限循环

ltqd579y  于 2023-01-04  发布在  其他
关注(0)|答案(3)|浏览(298)

我被HAL_Delay()函数卡住了。当我调用这个函数HAL_Delay()时,控制卡在无限循环中。在查找问题时,我发现了这个
http://www.openstm32.org/forumthread2145#threadId2146
在这个特殊的评论中,我引用"链接器文件有问题,请使用附件。您需要分别Map两个内存库,首先是SRAM1 96K,然后是SRAM2 32K。我认为这应该作为CubeMX中的错误报告,因为它生成了坏的链接器文件。"并且有两个扩展名为. ld的文件。

    • 我正在寻找的是如何在我的项目中使用这些文件或任何其他更好的选项来处理这个问题。**

ps.我正在使用stm32l476发现板,立方体mx 5. 0. 0和阿托利克真正的工作室。

    • 编辑**

我的项目是有一个RS485通信,从那里我采取数据,我有两个任务与该数据,显示在MAX7219显示器和发送到互联网使用sim800 gsm模块。
控制卡滞的代码。请注意,此函数仅在执行GSM任务时调用。

void vMyDelay(uint16_t ms)
{
    HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", strlen("\r\n"), 1000);
    HAL_UART_Transmit(&huart2, (uint8_t*)"In Delay", strlen("In Delay"), 1000);
    HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", strlen("\r\n"), 1000);
    for (int i = 0; i < ms; i++ )       HAL_Delay(1);
    HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", strlen("\r\n"), 1000);
    HAL_UART_Transmit(&huart2, (uint8_t*)"Out Delay", strlen("Out Delay"), 1000);
    HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", strlen("\r\n"), 1000);
}

此函数在终端上写入In Delay,但Out Delay不显示。但我也有一个定时器,每2秒调用一次,以显示MAX72219上的数据。
下面的代码是

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", strlen("\r\n"), 1000);
    HAL_UART_Transmit(&huart2, (uint8_t*)"HAL_TIM_PeriodElapsedCallback()", strlen("vRS485_CollectInverterData()"), 1000);
    HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", strlen("\r\n"), 1000);
    if (htim->Instance == htim3.Instance)
    {
        vMax7219_ClearDisplay();
        switch (uiMax7219Index)
        {
            case 0: vMax7219_SendNumberToString(ucFreq7219,1);      break;
            case 1: vMax7219_SendNumberToString(ucInVolt7219,1);    break;
            case 2: vMax7219_SendNumberToString(ucOutVolt7219,1);   break;
            case 3: vMax7219_SendNumberToString(ucOutCurr7219,1);   break;
            case 4: vMax7219_SendNumberToString(ucLoadSpd7219,1);   break;
            case 5: vMax7219_SendNumberToString(ucOutPwr7219,1);    break;
        }
        uiMax7219Index++;
        if (uiMax7219Index > 5) uiMax7219Index = 0;
    }
}

控制卡滞后,此函数始终在2秒后触发。因此得出结论,控制卡滞在HAL_Delay()中。
"IMP的东西"
问题每次都会发生,但没有特定的时间,即控制可能在5分钟和10分钟或15分钟后卡住。它不是从特定的功能卡住。功能可能不同。即有时它可能从功能名称getIMEI()卡住,有时它可能是get service provider

kokeuurv

kokeuurv1#

修复:

    • 摘要:

提高SysTick_Handler NVIC优先级(通过降低其NVIC数值,数值范围为0到15)。**

    • 详细信息:**

@P__J__在他的答案here中说的是正确的,我也怀疑这是你的问题。要解决这个问题,你需要让你的SysTick中断有一个**NVIC(嵌套向量中断控制器)*优先级 * 高于 * 任何其他中断,这些中断进行可能依赖于系统节拍递增的HAL调用。 这包括所有具有超时的HAL调用,例如,以及HAL延迟。更高的NVIC优先级意味着您必须使它成为一个 * 更低 * 的数值,因为默认配置中STM32芯片的最高NVIC优先级为0,最低为15。
要在STM32CubeMX 5中设置NVIC优先级,请转到引脚和配置--〉系统核心--〉(单击微小的向上/向下箭头进入显示NVIC的页面),然后单击NVIC--〉将"抢占优先级"值降低到 * 低于 *(优先级高于)依赖HAL呼叫的任何其他ISR。
这是一个屏幕截图。注意,你也可以通过点击"系统视图"旁边的"引脚视图"按钮,然后点击"系统核心"部分下的"NVIC"来进入这个屏幕。
截图:

有关HAL_IncTick();的更多信息:

您可以在"stm32f4xx_it. c"文件中看到SysTick_Handler ISR调用HAL_IncTick();

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
  HAL_IncTick();
}

如果您按住Ctrl+单击它(至少在System Workbench/Eclipse中)以跳转到HAL_IncTick()的实现,您将看到以下内容,这些内容在注解中提供了一些额外的见解:

/**
  * @brief This function is called to increment  a global variable "uwTick"
  *        used as application time base.
  * @note In the default implementation, this variable is incremented each 1ms
  *       in Systick ISR.
  * @note This function is declared as __weak to be overwritten in case of other 
  *      implementations in user file.
  * @retval None
  */
__weak void HAL_IncTick(void)
{
  uwTick++;
}

这个HAL_IncTick()函数可以在文件"...STM32Cube_FW_F4_V1.19.0/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c"中找到,该文件还包含了HAL_IncTick()上面的HAL_InitTick()函数,它的注解非常有见地:

/**
  * @brief This function configures the source of the time base.
  *        The time source is configured  to have 1ms time base with a dedicated 
  *        Tick interrupt priority.
  * @note This function is called  automatically at the beginning of program after
  *       reset by HAL_Init() or at any time when clock is reconfigured  by HAL_RCC_ClockConfig().
  * @note In the default implementation, SysTick timer is the source of time base. 
  *       It is used to generate interrupts at regular time intervals. 
  *       Care must be taken if HAL_Delay() is called from a peripheral ISR process, 
  *       The SysTick interrupt must have higher priority (numerically lower)
  *       than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
  *       The function is declared as __weak  to be overwritten  in case of other
  *       implementation  in user file.
  * @param TickPriority Tick interrupt priority.
  * @retval HAL status
  */
__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);
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }

  /* Return function status */
  return HAL_OK;
}

特别注意:那部分说:
如果从外设ISR进程调用HAL_Delay(),则必须小心。
SysTick中断必须具有较高的优先级(数值较低)
而不是外设中断。否则,调用ISR进程将被阻塞。
我就是在那里学到这个的。
确保跳过代码,有时查看ST的HAL源代码本身中的函数和文档,以发现像这样隐藏的洞察力。当然,除了参考以下核心文档之外,还要这样做:

芯片的关键STM32文档,按优先顺序排列(最重要的放在前面):

1.参考手册:RM0351
1.规格书:DS10198

  1. UM1725 - Description of STM32F4 HAL and LL drivers
    1.程控手册:PM0214
    这些手册和其他重要手册可在意法半导体网站(https://www.st.com/en/microcontrollers/stm32l476vg.html)上轻松找到,或者更方便:通过帮助--〉文档和资源(快捷方式:Alt + D)。
dwthyt8l

dwthyt8l2#

所有延迟和超时HAL函数都依赖于SysTick处理程序中递增的计数器。如果您在另一个中断中使用这些函数中的任何一个,您必须确保SysTick中断的优先级高于该中断。否则,SysTick处理程序永远不会被调用,您将在无限循环中结束,因为计数器永远不会递增。

2ul0zpep

2ul0zpep3#

我们需要将***SysTick_IRQn*的优先级提高到比其他IRQ优先级更低的数值。
例如:如果我们考虑其他IRQ编号 * 15 ,我们可以使用
HAL_NVIC_SetPriority(SysTick_IRQn,14.0)***为 * SysTick_IRQn * 分配 * 14 *,以便为SysTick分配可接受的优先级。

    • 注意**:在*SystemClock_Config()之后使用HAL_NVIC_SetPriority函数非常重要,如下图所示。

相关问题