У меня проблема, связанная с серьезной неисправностью моего Cortex-M0, поэтому я пытаюсь отладить ее. Я пытаюсь распечатать содержимое регистров ядра ARM, которые были помещены в стек при возникновении аппаратной ошибки.
Вот мой базовый код сборки:
__attribute__((naked)) void HardFaultVector(void) {
asm volatile(
// check LR to see whether the process stack or the main stack was being used at time of exception.
"mov r2, lr\n"
"mov r3, #0x4\n"
"tst r2, r3\n"
"beq _MSP\n"
//process stack was being used.
"_PSP:\n"
"mrs r0, psp\n"
"b _END\n"
//main stack was being used.
"_MSP:\n"
"mrs r0, msp\n"
"b _END\n"
"_END:\n"
"b fault_handler\n"
);
}
Функция fault_handler
распечатает содержимое кадра стека, который был передан либо в стек процесса, либо в основной стек. Но вот мой вопрос:
Когда я печатаю содержимое кадра стека, который предположительно имеет сохраненные регистры, я вижу вот что:
Stack frame at 0x20000120:
pc = 0xfffffffd; saved pc 0x55555554
called by frame at 0x20000120, caller of frame at 0x20000100
Arglist at unknown address.
Locals at unknown address, Previous frame's sp is 0x20000120
Saved registers:
r0 at 0x20000100, r1 at 0x20000104, r2 at 0x20000108, r3 at 0x2000010c, r12 at 0x20000110, lr at 0x20000114, pc at 0x20000118, xPSR at 0x2000011c
Вы можете видеть сохраненные регистры, это регистры, которые передаются ядром ARM при возникновении аппаратной ошибки. Вы также можете увидеть строку pc = 0xfffffffd;
, которая указывает, что это значение EXC_RETURN
LR
. Значение 0xfffffffd
указывает мне, что стек процессов использовался во время аппаратной ошибки.
Если я напечатаю значение $psp
, я получу следующее:
gdb $ p/x $psp
$91 = 0x20000328
Если я напечатаю значение $msp
, я получу следующее:
gdb $ p/x $msp
$92 = 0x20000100
Вы можете ясно видеть, что $msp
указывает на вершину стека, где предположительно находятся сохраненные регистры. Не означает ли это, что в главном стеке есть сохраненные регистры, которые ядро ARM поместило в стек?
Если я распечатаю содержимое памяти, начиная с адреса $msp
, я получу следующее:
gdb $ x/8xw 0x20000100
0x20000100 <__process_stack_base__>: 0x55555555 0x55555555 0x55555555 0x55555555
0x20000110 <__process_stack_base__+16>: 0x55555555 0x55555555 0x55555555 0x55555555
Пусто...
Теперь, если я распечатаю содержимое памяти, начиная с адреса $psp
, я получу следующее:
gdb $ x/8xw 0x20000328
0x20000328 <__process_stack_base__+552>: 0x20000860 0x00000054 0x00000054 0x20000408
0x20000338 <__process_stack_base__+568>: 0x20000828 0x08001615 0x1ad10800 0x20000000
Это выглядит более точным. Но я думал, что сохраненные регистры должны указывать, где они находятся во флэш-памяти? Так какой в этом смысл?