代码之家  ›  专栏  ›  技术社区  ›  Devjeet Mandal

HAL_Delay()卡在无限循环中

  •  1
  • Devjeet Mandal  · 技术社区  · 6 年前

    我一直在使用HAL_Delay()函数。当我调用这个函数HAL_Delay()时,控制卡在无限循环中。

    http://www.openstm32.org/forumthread2145#threadId2146

    在这个特别的评论中,我引用了“链接器文件有问题,请使用附件中的一个。您需要分别映射两个内存库,首先是SRAM1 96K,然后是SRAM2 32K。我认为这应该在CubeMX中报告为错误,因为它生成了错误的链接器文件。”还有两个扩展名为.ld的文件。

    我正在寻找的是如何在我的项目中使用这个文件,或者其他更好的方法来处理这个问题。

    另外,我使用的是stm32l476探索板、Cube Mx 5.0.0和Attolic True Studio。

    我的项目是有一个RS485通信,我从那里获取数据,我有两个任务处理该数据,在MAX7219显示器上显示,并使用sim800 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()

    小鬼的东西

    问题每次都会发生,但没有具体时间,即控件可能会在5分钟、10分钟或15分钟后卡住。它不受特定功能的约束。功能可能不同。i、 有时它可能会被函数名卡住 getIMEI() 或者某个时候它可能会伤害我 get service provider

    2 回复  |  直到 6 年前
        1
  •  13
  •   Gabriel Staples    6 年前

    总结:
    增加 SysTick_Handler NVIC优先级(通过减小其NVIC数值,其范围为0到15)。


    @P_uuuj_uuu在他的回答中说了什么 here 是正确的,我也怀疑这是你的问题。要修复它,您需要使SysTick中断具有NVIC(嵌套向量中断控制器)优先级 较高的 进行HAL调用的任何其他中断,可能依赖于系统滴答递增。 降低 数值,因为默认配置下STM32芯片的最高NVIC优先级为0,最低优先级为15。

    (优先级高于)依赖HAL呼叫的任何其他ISR。

    截图:

    enter image description here

    更多关于 HAL_IncTick();

    您将从“stm32f4xx_it.c”文件中看到 ISR呼叫

    /**
      * @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++;
    }
    

    哈尔·英蒂克() 函数位于文件“…STM32Cube_FW_F4_V1.19.0/Drivers/STM32F4xx_HAL_Driver/Src/STM32F4xx_HAL.c”中,该文件还包含 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
    2. 数据表:DS10198
    3. UM1725 - Description of STM32F4 HAL and LL drivers
    4. 编程手册:PM0214

    https://www.st.com/en/microcontrollers/stm32l476vg.html + ).

        2
  •  3
  •   Adrian Mole Chris    4 年前

    SysTick 处理程序。如果在另一个中断中使用这些函数中的任何一个,则必须确保 系统定时器 中断的优先级高于该中断。否则 处理器永远不会被调用,并且最终会进入无限循环,因为计数器永远不会增加。