Используя следующую настройку:
Используя JLinkGDBServer и eclipse в качестве интерфейса отладки, у меня всегда есть хорошая трассировка стека при переходе по моему коду. При использовании бесплатных инструментов Code Confidence (плагин eclipse) я также вижу трассировки стека всех потоков, которые в данный момент не работают (без этого плагина я вижу только трассировку стека активной нити). Все идет нормально.
Но теперь, когда мое приложение попадает в сбой, трассировка стека теряется.
Ну, я знаю технику, как узнать адрес кода, который вызывает неисправность (как видно Вот).
Но это очень плохая информация по сравнению с полной трассировкой стека.
Хорошо, иногда при попадании в hardfault невозможно сохранить трассировку стека, например, когда стек поврежден неисправным кодом. Но если стек полезен, я думаю, что получение трассировки стека может быть возможным (не так ли?).
Я думаю, что причина потери трассировки стека в случае сбоя заключается в том, что указатель стека будет автоматически перенесен из PSP в MSP архитектурой Cortex-M3. Одна из идей сейчас состоит в том, чтобы (возможно) установить MSP на предыдущее значение PSP (и, возможно, придется выполнить дополнительную подготовку стека?).
Любые предложения о том, как сделать тот или иной подход, чтобы сохранить трассировку стека в hardfault?
Редактировать 2015-07-07, добавлено больше деталей.
Я использую этот код для провокации:
__attribute__((optimize("O0"))) static void checkHardfault() {
volatile uint32_t* varAtOddAddress = (uint32_t*)-1;
(*varAtOddAddress)++;
}
При входе в checkHardfault()
моя трассировка выглядит так:
gdb-> backtrace
#0 checkHardfault () at Main.cxx:179
#1 0x100360f6 in GetOneEvent () at Main.cxx:185
#2 0x1003604e in executeMainLoop () at Main.cxx:121
#3 0x1001783a in vMainTask (pvParameters=0x0) at Main.cxx:408
#4 0x00000000 in ?? ()
Когда врезаться в hardfault (в (*varAtOddAddress)++;
) и оказываюсь внутри HardFault_Handler()
, трассировка стека:
gdb-> backtrace
#0 HardFault_Handler () at Hardfault.c:312
#1 <signal handler called>
#2 0x10015f36 in prvPortStartFirstTask () at freertos/portable/GCC/ARM_CM3/port.c:224
#3 0x10015fd6 in xPortStartScheduler () at freertos/portable/GCC/ARM_CM3/port.c:301
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Самый быстрый способ заставить отладчик сообщать вам подробности о состоянии до возникновения сбоя — вернуть процессор в состояние до сбоя.
В отладчике напишите сценарий, который берет информацию из различных аппаратных регистров и восстановите состояние ПК, LR, R0-R14 непосредственно перед тем, как вызвать серьезную ошибку, а затем выполните дамп стека.
Конечно, это не всегда полезно, когда вы сталкиваетесь с серьезной ошибкой из-за того, что вытаскиваете вещи из разорванного стека или топаете вещи в памяти. Как правило, вы склонны испортить кучу важных регистров, вернуться в какое-то безумное место в памяти и затем выполнить все, что там есть. Вы можете столкнуться с серьезными нарушениями многих тысяч (миллионов?) Циклов после того, как возникнет ваша настоящая проблема.