我试图在我的代码中检索IRQ处理程序的返回地址。 我的目标是在看门狗定时器到期之前和复位之前使用WDT_IRQHandler()保存PC的值以进行调试。我也在用其他IRQ测试这种方法来检查我是否掌握了这个想法。 但似乎我没有。
我已阅读documentation可用的内容。 我明白当异常发生时,8个寄存器被推送到堆栈: R0,R1,R2,R3,R12,LR,PC和XPSR。
我还读过堆栈自动双字对齐。所以在我看来,检索返回地址就像这样简单:
使用附带的调试器进行检查,情况似乎并非如此,该内存地址的内容并不总是指向闪存区域,甚至指向有效区域,并且无论如何它永远不会是PC的价值在POP指令之后假设。
代码工作正常,所以我认为这是我理解其工作原理的一个问题。
如果我检查反汇编,在某些IRQ中,在POPping(?)之前会向sp添加一个常量
00001924: 0x000009b0 ...TE_IRQHandler+280 add sp, #36 ; 0x24
00001926: 0x0000f0bd ...TE_IRQHandler+282 pop {r4, r5, r6, r7, pc}
在其他IRQ中,这不会发生。
据我所知,可能会发生更多寄存器被推送到堆栈,因此我如何确定检索PC的偏移量?
如果我在代码仍在IRQ处理程序中时检查SP周围的内存转储,我可以发现返回地址,但它始终位于一个奇怪的位置,与SP相比具有负偏移。我无法理解如何获得正确的地址。
答案 0 :(得分:5)
由于两个原因,你不能依赖C处理程序内的堆栈指针:
MSP
)。如果中断抢占了从进程堆栈(PSP
)运行的线程模式代码,则寄存器将被推送到PSP
,并且您永远不会在处理程序中找到它们堆叠; 这就是我通常的做法:
void WDT_IRQHandler_real(uint32_t *sp)
{
/* PC is sp[6] (sp + 0x18) */
/* ... your code ... */
}
/* Cortex M3/4 */
__attribute__((naked)) void WDT_IRQHandler()
{
asm volatile (
"TST LR, #4\n\t"
"ITE EQ\n\t"
"MRSEQ R0, MSP\n\t"
"MRSNE R0, PSP\n\t"
"LDR R1, =WDT_IRQHandler_real\n\t"
"BX R1"
);
}
/* Cortex M0/1 */
__attribute__((naked)) void WDT_IRQHandler()
{
asm volatile (
"MRS R0, MSP\n\t"
"MOV R1, LR\n\t"
"MOV R2, #4\n\t"
"TST R1, R2\n\t"
"BEQ WDT_IRQHandler_call_real\n\t"
"MRS R0, PSP\n"
"WDT_IRQHandler_call_real:\n\t"
"LDR R1, =WDT_IRQHandler_real\n\t"
"BX R1"
);
}
这里的技巧是处理程序是一小段程序集(我使用了一个带有GCC asm的裸函数,你也可以使用一个单独的asm文件),它将堆栈指针传递给真正的处理程序。这是它的工作原理(对于M3 / 4):
LR
的初始值称为EXC_RETURN
(更多信息here)。其位有各种含义,如果活动堆栈为EXC_RETURN[2]
,则0
为MSP
,如果活动堆栈为1
,则我们感兴趣PSP
TST LR, #4
; EXC_RETURN[2]
检查MRSEQ R0, MSP
并设置条件标记; MSP
将R0
移至EXC_RETURN[2] == 0
MRSNE R0, PSP
; PSP
将R0
移至EXC_RETURN[2] == 1
LDR
; BX
/ R0
跳转到真实函数(MSP
是第一个参数)。M0 / 1变体类似,但从核心does not support IT blocks开始使用分支。
这解决了PSP
/ LR
问题,因为它在任何编译器生成的堆栈操作之前运行,它将提供可靠的指针。
我在函数中使用了一个简单的(非链接的)分支,因为我不必在它之后做任何事情,LR
已经很好了。它节省了几个周期和R0-R3
推/弹。此外,所有使用的寄存器都在while (index != -1) {
var select = document.getElementById("recipes");
var opt = document.createElement("li");
opt.className = "list-group-item";
var link = document.createElement("a");
link.id = response.substring(0, index);
link.onclick = function () {
alert(link.id);
};
link.textContent = response.substring(0, index);
select.appendChild(opt);
opt.appendChild(link);
response = response.substring(index + 4);
index = response.indexOf("~,;~");
}
临时范围内,因此无需保留它们。