Скажем так. Есть 2 вида вылета.
Первый происходит закономерно в одном и том же месте. Как правило это либо обращение по не выровненному адресу или обращение по несуществующему адресу. То есть неверный расчёт указателя при работе с указателями. Такой вылет найти просто. Вам надо найти место где он происходит (например способом предложенным
Сергей Борщ). Потом поставить точку останова пораньше и пройти по шагам, анализируя работу.
Второй - непредсказуемый вылет в произвольном месте. Как правило, причина - неверный размер стека. Либо при работе с буферами неверно рассчитан его размер. То есть, в месте, где реально происходит ошибка, вылета нет, там просто портятся данные. А вылет происходит там где вы пытаетесь воспользоваться уже испорченными данными.
Тут рекомендуется:
1. Существенно увеличить размеры стека для разных задач. Пробовать останавливать и контролировать реальные размеры стеков.
2. Попытаться локализовать задачу где происходит вылет. Или место. Посмотреть какую-то статистику.
---
Например я во FreeRTOSConfig добавил следующую строку
// для отладки. слежение за задачей
#define traceTASK_SWITCHED_IN() *(uint32_t*)0x40002868 = pxCurrentTCB->uxTCBNumber
(не обращайте внимание на прямой адрес. В программе у меня Вы этого больше нигде не увидите. Просто если добавляешь в исходники FreeRTOS заголовочные файлы, то там конфликты - я пытался этого избегать.)
На самом деле это следующее
// Номер задачи, которая последней выполнялась перед вылетом по ошибке
#define NBRTASKFAULT RTC->BKP6R
Сама traceTASK_SWITCHED_IN вызывается во FreeRTOS в vTaskSwitchContext
Далее
Код
void HardFault_Handler(void)
{
StatusTM3->nbrTskFlt = NBRTASKFAULT & 0x1f; // записать номер вылетевшей программы
StatusTM3->fHardFault = TRUE; // установить признак
DelayMs(TIM_SMALLWAIT,100); // Задержка
NVIC_SystemReset(); // Начать сначала
}