HAL_Delay () застрял в бесконечном цикле - PullRequest
0 голосов
/ 23 декабря 2018

Я застрял с функцией HAL_Delay ().Когда я вызываю эту функцию HAL_Delay (), управление застревает в бесконечном цикле.При поиске проблемы я обнаружил это

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

В этом конкретном комментарии, в котором говорится и я цитирую "Существует проблема с файлом компоновщика, пожалуйста, используйте прилагаемый файл. Вам необходимо отобразитьдва банка памяти по отдельности, поэтому сначала SRAM1 96K, а затем SRAM2 32K. Я думаю, что об этом следует сообщать как об ошибке в 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().

IMP THING

проблема возникает каждый раз, но нет определенного времени, т. Е. Элемент управления может зависнуть через 5 минут и 10 минут или 15 минут.Он не зависает от конкретной функции.Функции могут быть разными.то есть иногда это может зависнуть от имени функции getIMEI() или иногда это может быть get service provider

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

Исправление:

Сводка:
Увеличьте приоритет SysTick_Handler NVIC (уменьшив его числовое значение NVIC, которое имеет диапазон от 0 до 15).

Подробности:
То, что @P__J__ говорит в своем ответе здесь , верно, и я тоже подозреваю, что это ваша проблема.Чтобы исправить это, вам нужно, чтобы ваше прерывание SysTick имело приоритет NVIC (Nested Vectored Interrupt Controller) выше , чем любых других прерываний, которые делают вызовы HAL, которые могут зависеть от увеличения системного тика. Это включает в себя все вызовы HAL, которые имеют тайм-ауты, например, а также задержки HAL.Более высокий приоритет NVIC означает, что вы должны сделать его меньшим числовым значением, так как самый высокий приоритет NVIC равен 0, а самый низкий - 15 для чипов STM32 в конфигурации по умолчанию.

Чтобы установить приоритеты NVIC в STM32CubeMX 5, перейдите в Распиновка и Конфигурация -> Системное ядро ​​-> (нажмите крошечную стрелку вверх / вниз, чтобы перейти на страницу с NVIC), затем нажмите NVIC-> Уменьшите значение «Приоритет выкупа», чтобы оно было ниже, чем (более высокий приоритет, чем) для любых других ISR, использующих вызовы HAL.

Вот снимок экрана.Обратите внимание, что вы также можете попасть на этот экран, нажав кнопку «Вид системы» рядом с «Видом распиновки», а затем нажав «NVIC» в разделе «Системное ядро».

Снимок экрана:

enter image description here

Подробнее о HAL_IncTick();:

Из файла "stm32f4xx_it.c" вы увидите, что SysTick_HandlerISR вызывает 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_InitTick() функция чуть выше HAL_IncTick().Его комментарии очень проницательны:

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

Обратите особое внимание: часть, которая гласит:

Необходимо соблюдать осторожность, если HAL_Delay () вызывается из периферийного процесса ISR,
Прерывание SysTick должно иметь более высокий приоритет (численно ниже)
, чем периферийное прерывание.В противном случае процесс вызывающего абонента будет заблокирован.

Это именно то место, где я это узнал.

Обязательно прыгайте по коду и иногда просматривайте функции и документацию в самом исходном коде ST HAL, чтобы найти скрытое понимание, подобное этому.Сделайте это, конечно, в дополнение к ссылкам на следующие основные документы:

Ключевые документы STM32 для вашего чипа, в порядке приоритета (самый важный первый):

  1. Справочное руководство:RM0351
  2. Лист данных: DS10198
  3. UM1725 - Описание драйверов STM32F4 HAL и LL
  4. Руководство по программированию: PM0214

Эти и другие важные руководства можно легко найти на веб-сайте ST (https://www.st.com/en/microcontrollers/stm32l476vg.html), или, что еще удобнее: в STM32CubeMX через Справка -> Документы и ресурсы (ярлык: Alt + D ).

0 голосов
/ 23 декабря 2018

Все функции реле задержки и таймаута HAL на счетчике увеличены в обработчике SysYick.Если вы используете какую-либо из этих функций в другом прерывании, вы должны убедиться, что приоритет прерывания SysTick выше, чем приоритет прерывания, обработчик которого вызывает эти функции.В противном случае обработчик SysTick никогда не вызывается, и вы попадете в бесконечный цикл, поскольку счетчик никогда не будет увеличен.

...