我对HAL_Delay()函数感到困惑。当我调用此函数HAL_Delay()时,控件陷入无限循环。 在寻找问题时,我发现了
http://www.openstm32.org/forumthread2145#threadId2146
在此特别声明中,我引用“链接器文件存在问题,请使用所附的链接。您需要分别映射两排内存,因此首先是SRAM1 96K,然后是32K SRAM2。我认为应该报告作为CubeMX中的错误,因为它会生成错误的链接器文件。”还有两个扩展名为.ld的文件。
我正在寻找的是如何在项目中使用此文件,或者如何使用其他更好的选项来解决此问题。
PS。我正在使用stm32l476发现板,Cube Mx 5.0.0和Attolic True Studio。
编辑
我的项目正在进行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()
中。
重要的事情
问题每次都会发生,但没有特定的时间,即控件可能在5分钟,10分钟或15分钟后卡住。它不会因特定功能而卡住。功能可能有所不同。也就是说,有时它可能会因函数名getIMEI()
而卡住,或者有时可能是我get service provider
答案 0 :(得分:1)
SysYick处理程序中增加的所有延迟和超时HAL功能在计数器上进行中继。如果在另一个中断中使用这些功能中的任何一个,则必须确保SysTick中断优先级高于处理程序调用这些功能的中断的优先级。否则,永远不会调用SysTick处理程序,并且由于计数器永远不会增加,您将陷入无限循环。
答案 1 :(得分:1)
摘要:
增加SysTick_Handler
NVIC优先级(通过减小其NVIC数值(范围为0到15)。
详细信息:
@P__J__在他的回答here中说的是正确的,我也怀疑这是您的问题。要解决此问题,您需要使SysTick中断的NVIC(嵌套矢量中断控制器)优先级比要使HAL调用的其他中断(可能依赖于系统滴答增量)的更高。 / em>包括所有具有超时的HAL调用,例如HAL延迟。较高的NVIC优先级意味着您必须将其设为较低的数值,因为对于默认配置的STM32芯片,最高NVIC优先级为0,最低为15。
要在STM32CubeMX 5中设置NVIC优先级,请转到Pinout&Configuration-> System Core->(单击微小的向上/向下箭头进入显示NVIC的页面),然后单击NVIC->将“抢占优先级”值降低为低于(高于所有其他依赖HAL呼叫的ISR)。
这是屏幕截图。请注意,您还可以通过单击“ Pinout视图”旁边的“系统视图”按钮,然后单击“系统核心”部分下的“ 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”中,该文件还包含位于{{1}上方的HAL_InitTick()
函数}。它的评论很有见地:
HAL_IncTick()
尤其要注意:表示以下内容的部分:
如果从外围ISR进程调用HAL_Delay(),则必须小心,
SysTick中断必须具有更高的优先级(数字上更低)
比外设中断。否则,呼叫者ISR进程将被阻止。
这正是我学到的地方。
请确保有时会跳过代码,并查看ST的HAL源代码本身中的函数和文档,以查找类似的隐藏见解。当然,除了引用以下核心文档之外,还请执行此操作:
这些和其他重要手册可在ST网站(https://www.st.com/en/microcontrollers/stm32l476vg.html)上轻松找到,或者甚至更方便:通过“帮助”->“文档与资源”在STM32CubeMX内部(快捷方式: Alt + D )。