Перейти к содержанию
    

STM32 зависание при добавлении любой функции

Имеется плата на stm32f407 камне. Пытаюсь написать функцию парсинга ответов от модема, но при добавлении любой строки в функцию - получаю полное зависание проца. Как отлаживать не могу понять, так как присутствует FreeRTOS.

Собственно сама функция выглядит так:

uint8_t modemresponse(char * data, uint16_t leng)
{
    if(iblanks(Uart3RXBuf, leng))
    {
        return 0;
    }
    else if(memchr(data, '+', leng) && memchr(data, ':', leng))
    {
        return 1;
    }
    else if(strstr(data,"ERROR") != NULL)
    {
        return 2;
    }
    else
    {
        return 3;
    }
}

Если сделать как ниже, то все работает. Тоесть достаточно закоментировать любой из else if или даже else. Если закоментировать один вариант выбора и вместо него в конец функции подставить хотя бы

HAL_UART_Transmit(&huart6,(uint8_t *)"Zavislo\r",8,100);

или все что угодно - опять висяк.

uint8_t modemresponse(char * data, uint16_t leng)
{
    if(iblanks(Uart3RXBuf, leng))
    {
        return 0;
    }
    else if(memchr(data, '+', leng) && memchr(data, ':', leng))
    {
        return 1;
    }
    //else if(strstr(data,"ERROR") != NULL)
    //{
    //    return 2;
    //}
    else
    {
        return 3;
    }
}

Когда то с таким сталкивался и проблема была в размере СТОК\ХЕАП. В данном случае пробовал менять их размер и в FreeRTOS и в Стартап файле, но как узнать какой размер куда прописывать?

 

Похоже разобрался. Поставил во FreeRTOS вместо heap4 тип heap1.

Изменено пользователем Neo_Matrix

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Странно, что работает:

 

const void * memchr ( const void * ptr, int value, size_t num );
      void * memchr (       void * ptr, int value, size_t num );

const char * strstr ( const char * str1, const char * str2 );
      char * strstr (       char * str1, const char * str2 );

 

Т.к. функиции возвращают указатели.

А сравнение уже нужно производить другими функциями. Типа:

 

int strncmp ( const char * str1, const char * str2, size_t num );

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Странно, что работает:

Т.к. функиции возвращают указатели.

И нулевой указатель в отдельных случаях. Так что код вполне рабочий.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Когда то с таким сталкивался и проблема была в размере СТОК\ХЕАП. В данном случае пробовал менять их размер и в FreeRTOS и в Стартап файле, но как узнать какой размер куда прописывать?

Для этого надо вдумчиво прочитать документацию и провести эксперименты.

 

 

 

Похоже разобрался. Поставил во FreeRTOS вместо heap4 тип heap1.

Маловероятно. Скорее всего, проблема где-то глубже.

Кроме того, heap1 очень ущербный - там в принципе нет free(). С ним можно работать, если у Вас задачи-массивы-проч создаются один раз, статически. Если же пользоваться malloc()/free() при работе, операционка довольно быстро повиснет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

gazpar

Странно, что работает:

 

 

void *memchr(const void *buffer, int ch, size_t count);

Эта функция возвращает указатель на первый из символов ch, входящих в массив buffer, или нулевой указатель, если символ ch не найден.

 

Сама реализация вполне рабочая. И совершенно не важно, что там идет после if (if else), можно хоть сравнение добавить uint8_t a=1; if(a==1); все равно функция виснет.

 

esaulenka

Глубже копать уже просто некуда(ну или я не вижу).

В конечном счете выяснил, что при всех вариантах heap,кроме heap_4 все работает. Даже на heap_5 работает, а он почти тот же heap_4.

Остановился на heap_2. Маалоков нет. Динамические только очереди и пару задач временами убиваются/создаются.

 

Изменено пользователем Neo_Matrix

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ок.

 

Neo_Matrix,

Вы используете прерывания?

Если да, то при настройке оных, какой устанавливаете NVIC_PriorityGroup: 0, 1, 2, 3 или 4?

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Глубже копать уже просто некуда(ну или я не вижу).

Ну, если Вы можете чётко сказать "в задаче А столько-то свободного стека, в задаче Б - столько-то, хипа используется столько-то", в эту сторону копать не стоит.

А пока "я не знаю, переполняется что-то или нет", копать есть куда. И много...

 

 

Остановился на heap_2. Маалоков нет. Динамические только очереди и пару задач временами убиваются/создаются.

Ну так создание/удаление очередей-задач - это чистейший маллок/фрии.

А heap_2 - это плохо. Оно нормально работает только при выделении/удалении элементов одинакового размера.

 

 

 

Ну и было б неплохо вместо "проц виснет" описать "вываливается в hardfault, link-register указывает на функцию ааа(), там у меня происходит ...".

Начинать читать здесь: http://www.freertos.org/Debugging-Hard-Fau...ontrollers.html

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

gazpar

Настройка прерываний следущая

HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);

esaulenka

Я увеличивал стек и кучу в 2 раза, это нечего не меняло.

Ну так создание/удаление очередей-задач - это чистейший маллок/фрии.

Тут полностью согласен, но у меня размер очередей одинаков, так что должно работать.

Ну и было б неплохо вместо "проц виснет" описать "вываливается в hardfault, link-register указывает на функцию ааа()....

Я не могу понять где оно валится в хардфолт, отладка как то странно работает под РТОС, попробую еще с отладкой разобраться(РТОС первый раз использую).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В этой РТОС есть специальные службы для определения, что где ломается

 

Hooks

 

В обработчики hook'ов можно добавить отладочные сообщения(зажечь какой-то led(или выдать какую-либо последовательность мигания), отправить сообщение в usart и т.п.)

 

Используется примерно так:

void vApplicationStackOverflowHook( xTaskHandle pxTask,char *pcTaskName )
{
    ( void ) pcTaskName;
    ( void ) pxTask;
    printf("\r\n\r\nStack overflowed by \"%10s\" task\r\n\r\n",pcTaskName);
     
}

Изменено пользователем gazpar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Немного добавлю по отладке. Есть задача, которая в цикле запускает вышеуказанную функцию. Собственно вот:

void vTemp(void const * argument)
{
  for(;;)
  {
    uint16_t leng; //Длина строки до знака \n
    uint8_t resp; //Собственно сам ответ 0,1,2,3.....
    if(uart3_not_empty) //Обработчик прерывания устанавливает флаг 1\0
    {
        leng = uart3_readline(); //вычисляем длину строки вместе с \r\n
        sprintf(debug_buff, "leng: %d, line: %s", len, Uart3RXBuf); //формировка данных в соседний порт для отладки(длина строки и сама строка)
        USART_STR(USART6, debug_buff);  //просто отправка данных в соседний порт для отладки
        resp = process_response(uart3_fifo_line,len); // тут вызов глючной функции
        sprintf(debug_buff, "resp: %d \r\n", resp); //формовка
        TM_USART_Puts(USART6, debug_buff); //отправка для отладки
        }
}
}

Как видно в начале происходит проверка на новые данные if(uart3_not_empty), и даже если условие if не выполнено, все равно все висло.

uart3_not_empty инициализируется 0-лем, в прерывании флаг ставится в 1. Зависон просходил даже при условии отсутствия данных на ком порте, но только при условии, что в функции process_response вариантов if(if else) более трех.

 

В этой РТОС есть специальные службы для определения, что где ломается

О, теперь понятно!!! Спасибо!

 

Еще добавлю, на сайте РТОС есть такое:

Known Issues with the Current Version

Heap_4.c cannot be used on 8-bit devices (FreeRTOS V8.2.1)

A typo in the calculation of xHeapStructSize means heap_4.c cannot be used to provide the heap when FreeRTOS is being built for an 8-bit microcontroller.

Software timers and FreeRTOS-MPU

The software timer API is not yet included in the official distribution of FreeRTOS/source/include/mpu_wrappers.h.

Может как то связано.....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Немного добавлю по отладке. Есть задача, которая в цикле запускает вышеуказанную функцию. Собственно вот:

1) Хорошим тоном является наличие не обычного флажка, а семафора. Или очереди.

В этом случае задача не будет крутиться впустую.

 

2) Также хорошим тоном (а в случае "где-то у меня память течёт" - необходимым средством) является использование snprintf() вместо sprintf(). sprintf() легко и непринуждённо портит память, лежащую сразу после выходного буфера (сколько раз сам на это наступал...).

 

 

Как видно в начале происходит проверка на новые данные if(uart3_not_empty), и даже если условие if не выполнено, все равно все висло.

Ну отлично просто. Но пока мы не увидим, где и что конкретно повисло, результаты разглядывания кофейной гущи будут точнее, чем разглядывание кода.

 

 

О, теперь понятно!!! Спасибо!

Т.е. ссылка в 4-м сообщении - непонятная, а ссылка в 9-м - понятная? Удивительное дело, ведь ведут они в конечном итоге в одно и то же место.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1) Хорошим тоном является наличие не обычного флажка, а семафора. Или очереди.

В этом случае задача не будет крутиться впустую.

2) Также хорошим тоном (а в случае "где-то у меня память течёт" - необходимым средством) является использование snprintf() вместо sprintf(). sprintf() легко и непринуждённо портит память, лежащую сразу после выходного буфера (сколько раз сам на это наступал...).

Как можно заметить задача именуется vTemp. Это временное решение, созданное для вывода отладки в ЮАРТ. Этой задачи вовсе не должно было быть. Потому с семафорами я не заморачивался.

 

Ну отлично просто. Но пока мы не увидим, где и что конкретно повисло, результаты разглядывания кофейной гущи будут точнее, чем разглядывание кода.

Если бы я видел, где повисло уже и сам бы решал проблему. Вечером буду пробовать по добавлять отладки в код РТОСа.

 

Т.е. ссылка в 4-м сообщении - непонятная, а ссылка в 9-м - понятная? Удивительное дело, ведь ведут они в конечном итоге в одно и то же место.

Дело вовсе не в ссылке, а в примере который там показан.

 

esaulenka не нужно так агрессивно относится к заданным вопросам, не все так хорошо знакомы с РТОСом, как Вы. После всего прочитанного, мне стало ясно как отлаживать РТОСом, возможно скоро я и найду причину беды, если нет - перепишу с нуля обработчик прерывания и ф-кцию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

esaulenka не нужно так агрессивно

Ок. Извините.

 

У Вас проблема в том, что полностью отсутствуют средства диагностики.

Настоятельно рекомендую разобраться, что такое hardfault, в какие регистры надо при этом смотреть (для начала - скопировать обработчик с сайта freertos, погуглить "hardfault cortex site:electronix.ru -redirect").

Также при работе с RTOS необходимо знание, сколько куда памяти уходит. Во фриртос это почти что встроенная штука (почему-то в heap'е нет диагностики, но это легко поправить).

 

Без диагностики можно долго "исправлять" методом тыка, и оно опять развалится в самый неподходящий момент...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

esaulenka,gazpar

Спасибо за помощь. Уже немного разобрался в отладке.....

Зло было найдено, это была соседняя функция которая в этот момент слала данные в тот же USART TX.

Было так:

HAL_UART_Transmit (&huart3,(uint8_t *)"AT\r",3,100);

т.е. прерывания не было.

 

А так все нормально:

HAL_UART_Transmit_IT(&huart3,(uint8_t *)"AT\r",3);

 

В цикле отправка без прерывания, а прием по прерываниям работает, под РТОС почему то нет. Или это HAL виноват...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Слово "HAL" я пропустил. Вас ждёт масса удивительных открытий.

 

Например, отсутствие нормальных семафоров:

#if (USE_RTOS == 1)
  #error " USE_RTOS should be 0 in the current HAL release "
#else
  #define __HAL_LOCK(__HANDLE__)                                           \
                                do{                                        \
                                    if((__HANDLE__)->Lock == HAL_LOCKED)  \
                                    {                                      \
                                       return HAL_BUSY;                    \
                                    }                                      \
                                    else                                   \
                                    {                                      \
                                       (__HANDLE__)->Lock = HAL_LOCKED;    \
                                    }                                      \
                                  }while (0)

  #define __HAL_UNLOCK(__HANDLE__)                                          \
                                  do{                                       \
                                      (__HANDLE__)->Lock = HAL_UNLOCKED;   \
                                    }while (0)
#endif /* USE_RTOS */

В особо неудачном случае оно действительно может повиснуть.

 

Правда, это старая версия, возможно, за год что-то поменялось...

  * @file    stm32f1xx_hal_def.h
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    15-December-2014

 

PS повторюсь. Не зная, как и что ломалось, гарантировать "вот теперь-то точно всё будет хорошо" нельзя.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...