FreeRTOS: использование стека и проверка стека на переполнение Печать
Добавил(а) microsin   

Каждая задача (task) системы FreeRTOS использует свой собственный, индивидуальный стек. Если задача была создана с использованием API-функции xTaskCreate(), то память для стека автоматически выделяется из кучи FreeRTOS, и выделяемый размер стека определяется параметром, переданным в xTaskCreate(). Если задача создается вызовом xTaskCreateStatic(), то память для стека задачи предварительно выделяется разработчиком приложения. Переполнение стека (stack overflow) наиболее частая причина нестабильности приложения. Поэтому FreeRTOS предоставляет 2 механизма, которые можно использовать для помощи в определении и исправлении проблем со стеком. Используемая опция конфигурируется константой configCHECK_FOR_STACK_OVERFLOW.

Имейте в виду, что эти опции доступны только на архитектурах, у которых карта памяти не сегментирована. Также некоторые процессоры могут генерировать ошибку или исключение в ответ на повреждение стека до того, как сможет произойти проверка переполнения стека в ядре FreeRTOS (RTOS kernel overflow check). Приложение должно предоставить функцию перехвата переполнения стека (stack overflow hook function), если опция configCHECK_FOR_STACK_OVERFLOW не установлена в 0. Hook-функция должна называться vApplicationStackOverflowHook(), и иметь следующий прототип:

void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName );

Здесь параметры xTask и pcTaskName передают в hook-функцию дескриптор (handle) и имя проблемной задачи соответственно. Однако следует отметить, что в зависимости от серьезности переполнения эти параметры сами по себе могут оказаться испорченными, в таком случае можно напрямую инспектировать переменную pxCurrentTCB.

Проверка переполнения стека вводит дополнительную нагрузку на переключение контекста, поэтому эту проверку рекомендуется использовать только на фазе тестирования.

[Определение переполнения стека, метод 1]

Вероятно, что стек задачи достигнет своего наибольшего использования (самой большой глубины) посте того, как ядро RTOS выведет эту задачу из состояния Running, потому что в этот момент в стеке должен находиться контекст задачи (task context, т. е. текущее состояние выполнения задачи). В этой точке ядро RTOS может проверить, что указатель стека процессора остался в пределах допустимой области стека. Функция перехвата переполнения стека (hook-функция) будет вызвана в том случае, когда указатель стека содержит значение, которое выходит за допустимое пространство стека.

Этот метод работает быстро, однако он не гарантирует, что может отследить все переполнения стека. Чтобы использовать только этот метод, установите configCHECK_FOR_STACK_OVERFLOW в значение 1.

[Определение переполнения стека, метод 2]

Когда задача создается, её область стека заполняется заранее известным значением (обычно байтом 0xA5). Когда происходит выход задачи из состояния Running (переключение контекста), ядро RTOS может проверить последние 16 в допустимом пространстве стека - были ли они перезаписаны задачей или активным прерыванием. Будет вызвана функция перехвата переполнения стека, если эти 16 не находятся в своем первоначальном значении.

Этот метод менее эффективен, чем метод 1, однако он все же достаточно быстрый. Он с большой вероятностью отлавливает переполнения стека, однако не гарантирует перехват всех переполнений.

Для использования метода 2 в комбинации с методом 1 установите configCHECK_FOR_STACK_OVERFLOW в значение 2. Отдельно метод 2 использовать нельзя.

[Ссылки]

1. Stack Usage and Stack Overflow Checking site:freertos.org.
2. uxTaskGetStackHighWaterMark uxTaskGetStackHighWaterMark2 site:freertos.org.
3FreeRTOS: практическое применение, часть 6 (устранение проблем).
4Проектирование стека и кучи в IAR.
5FreeRTOS, STM32: отладка ошибок и исключений.
6IAR C-SPY: предупреждение о переполнении стека.