реклама на сайте
подробности

 
 
> Случайное падение шедулера. Как отследить?, FreeRTOS, C++, обработка исключений, шедулер
vv_
сообщение Nov 29 2016, 12:24
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 24-06-14
Пользователь №: 82 043



Доброго времени!
Пишу проект на C++ в Keil, процессор STM32F4**, ось FreeRTOS V8.2.3, менеджер памяти heap_4. Проект сгенерирован в CubeMX.
Столкнулся с ситуацией, когда при обработке исключений на C++ происходит неопределенное поведение.
CODE

class MemTest{
public:
MemTest(){ _p = new char[10000]; }
~MemTest(){ delete _p; }
private:
char * _p;
};
class exc{
public:
exc(){}
~exc(){}
};
/* таска в которой локализую ошибку */
void exception_debug(void const * argument){
while(true){
try{
MemTest mt;
throw exc();
} catch(const exc& e){
osDelay(100);
} catch(...){
osDelay(500);
}
}
vTaskDelete(NULL);
}

Операторы new и delete выглядят так:
CODE

void *operator new(size_t size){
void *p=pvPortMalloc(size);
#ifdef __EXCEPTIONS
if (p==0)
throw std::bad_alloc();
#endif
return p;
}
void operator delete(void *p){
vPortFree( p );
}

Сценарий выполнения выглядит следующим образом:
1. некоторое количество раз (в среднем от 1 до 25) выполняется в цикле try ... catch и мы успешно падаем в блок catch(const exc& e).
2. после последнего удачного раза отработки конструкторов - деструкторов типов MemTest и exc, на следующей итерации, когда я попадаю в деструктор MemTest, выполняю операцию delete и в этот момент у меня выполнение кода передаётся на функцию HAL_TIM_IRQHandler и дальше попадаю в функции HAL для обработки сравнений итп, что касается таймера.

Вопрос такой, как определить в какую сторону копать? У меня есть предположение, что в некоторой ситуации крашится шедулер FreeRTOS. Но отловить в какой именно пока не получилось.

PS1: Я отслеживаю переполнение хипа и стека. Эти хуки не вызываются, из чего можно сделать вывод, что использование памяти не выходит за границы..
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
vv_
сообщение Nov 30 2016, 09:06
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 24-06-14
Пользователь №: 82 043



Спасибо за советы!
Покрыл отладочными состояниями. конструкторы и деструкторы отрабатываются правильно. Предсказуемо)
CODE

volatile int debug;
class MemTest{
public:
MemTest()
: _p(0)
{
debug = 0;
try{
debug = 1;
_p = new char[10000];
debug = 2;
} catch(...){
debug = 3;
}
HAL_GPIO_TogglePin(PAPER_LED_GPIO_Port, PAPER_LED_Pin);

MemTest(){
debug = 4;
if(_p != 0) delete _p;
debug = 5;
}
private:
char * _p;
};
class exc{
public:
exc(){
debug = 6;
}
~exc(){
debug = 7;
}
};
void exception_debug(void const * argument){
while(true){
try{
MemTest mt;
throw exc();
} catch(const exc& e){
osDelay(500);
debug = 8;
} catch(...){
osDelay(500);
}
}
vTaskDelete(NULL);
debug = 10;
Error_Handler();
}

Но в какой то "случайный" момент (около 20 итераций, каждый раз по разному), поток выполнения программы падает в:
CODE

/**
* @brief This function handles TIM interrupts requests.
* @param htim: pointer to a TIM_HandleTypeDef structure that contains
* the configuration information for TIM module.
* @retval None
*/
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
...
/* TIM Update event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
HAL_TIM_PeriodElapsedCallback(htim);
}
...
}

В файле startup_stm32f427xx.s вижу, что у меня вызывается прерывание TIM6_DAC_IRQHandler и это значит "TIM6 and DAC1&2 underrun errors"
CODE

DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors

Стек вызовов выглядти так:
рис 1
Заметил еще, что при вызове в void vPortFree( void *pv ){...} функции vTaskSuspendAll(); я постоянно попадаю в HAL_TIM_IRQHandler.

Если в дебаге пошагать дальше, то можно добраться до следующего виде стека вызовов:
рис 2

Интересно то, что после всего этого мы снова возвращаемся к конструктору MemTest, выделяем память, а в деструкторе MemTest при освобождении "_p" история повторяется.
При всём этом, если я отслеживаю процесс не в дебаге, то диод у меня или загарается и уже не гаснет или наоборот. Но больше никогда после падения не изменяет своего состояния. А если в дебаге хожу, то после краша я дохожу до места где диод меняет своё значение.
Не могу понять как это отловить и как локализовать причину.
Сейчас работает только одна таска отладочная и Idle. Больше ничего.
Если есть идеи, с удовольствием готов принять и проверять!)

Сообщение отредактировал vv_ - Nov 30 2016, 09:08
Эскизы прикрепленных изображений
Прикрепленное изображение
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 1st September 2025 - 08:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.0138 секунд с 7
ELECTRONIX ©2004-2016