Как сохранить трассировку стека, когда Cortex-M3 ушел в hardfault?

Используя следующую настройку:

Используя 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?)

4

Решение

Самый быстрый способ заставить отладчик сообщать вам подробности о состоянии до возникновения сбоя — вернуть процессор в состояние до сбоя.

В отладчике напишите сценарий, который берет информацию из различных аппаратных регистров и восстановите состояние ПК, LR, R0-R14 непосредственно перед тем, как вызвать серьезную ошибку, а затем выполните дамп стека.

Конечно, это не всегда полезно, когда вы сталкиваетесь с серьезной ошибкой из-за того, что вытаскиваете вещи из разорванного стека или топаете вещи в памяти. Как правило, вы склонны испортить кучу важных регистров, вернуться в какое-то безумное место в памяти и затем выполнить все, что там есть. Вы можете столкнуться с серьезными нарушениями многих тысяч (миллионов?) Циклов после того, как возникнет ваша настоящая проблема.

1

Другие решения