C IAR汇编程序BKPT立即数作为输入操作数

C IAR汇编程序BKPT立即数作为输入操作数,c,breakpoints,inline-assembly,iar,C,Breakpoints,Inline Assembly,Iar,我正在为Cortex M4设备编写一个flashloader,我想使用断点指令的立即值为驱动PC应用程序“返回”一个值 虽然硬编码即时代码可以很好地工作: __asm("bkpt 0x70"); __asm("bkpt %0" : : "i" (0x70)); 只要我想“返回”运行时相关的东西,比如 uint8_t status = Flash_EraseAll(); __asm("bkpt %0" : : "i" (status)); 编译失败 错误[Ta090]:立即数操作数不是常量 我

我正在为Cortex M4设备编写一个flashloader,我想使用断点指令的立即值为驱动PC应用程序“返回”一个值

虽然硬编码即时代码可以很好地工作:

__asm("bkpt 0x70");
__asm("bkpt %0" : : "i" (0x70));
只要我想“返回”运行时相关的东西,比如

uint8_t status = Flash_EraseAll();
__asm("bkpt %0" : : "i" (status));
编译失败

错误[Ta090]:立即数操作数不是常量

我试着用不同的连接设置使用预处理器宏,但没有用

有人知道我如何将依赖于运行时的状态标志作为立即数输入IAR中的
\u asm()
块吗?根据我所读到的,这是不可能的,但可能有一个聪明的黑客方法来做到这一点


注意:是的,作为一种解决方法,我可以使用switch语句列出并硬编码每个可能的状态,但这既难看又长。

我会在堆栈上推送值,然后使用带有定义数字的
bkpt
指令,这样调试器就可以查看该状态的堆栈

类似这样的内容(伪代码):

当然,您不应该忘记在之后清理堆栈

由于
bkpt
仅使用立即数编码,因此在运行时显然无法更改它,因为您必须修改代码。

基于的想法,我得出以下结论:

    uint32_t status = Flash_EraseAll();
    __asm volatile ("str %0, [sp, #-4]!\n\t"   // Push to stack
                    "bkpt 0x0\n\t"             // Halt CPU
                    "add sp, sp, #4\n\t"       // Restore SP
                    : : "r"(status));          // status as input to __asm()
汇编指令告诉编译器将状态变量放入一个方便的寄存器“r”,并将该寄存器的内容存储在堆栈指针的预减量地址下,然后立即以0停止CPU的执行

如果目标停止(bkpt命中),驱动应用程序将轮询目标。如果暂停,通过读取当前PC下的16位数据(u asm(“bkpt 0x00”)->0xbe00->#imm=0xbe00&0x00ff=0),应用程序可以确保执行已在正确的位置停止。然后,它将读取最终SP地址下的32位数据,以获取嵌入式代码的执行状态

这样,您就可以动态地向外部世界“报告”更多内容(本例中为32位),而不是从bkpt的immediate中获取静态8位代码


如图所示,push和bkpt语句必须位于同一内联汇编指令中,否则编译器可能会决定在语句之间插入代码。此外,SP必须恢复到_asm()之前的值,因为编译器假定对SP具有唯一控制权。

Hm。。。这不是一个坏主意,而且似乎很简单。没想到。我会等一会儿,看看是否有人对此有其他想法。谢谢这两条指令都必须是一条asm语句的一部分,否则编译器可能会决定将一些编译器生成的指令放在这些语句之间。另外,大概您需要在恢复后清理堆栈。(ping@davidanderle)。另外,对于
状态
,显然需要一个约束而不是
“i”
,因为
“i”
需要一个编译时常量来替换为立即数。可能您想要
“r”(状态)
,并且您可以再次硬编码
bkpt 0x70
,除非您想使用C宏定义设置数字。当您在第一个ASM语句中修改
sp
时,您的解决方案是不安全的。
sp
的推送、断点和恢复必须在同一个asm语句中。@TimothyBaldwin这可能解释了我遇到的一些奇怪行为。在我修改我的编辑之前,你能详细说明一下这到底是如何不安全的吗?设备/堆栈在工作情况下会发生什么情况?我必须补充一点,即;这是我的代码的最后一句话,你的答案作为一个答案,在那里人们可以投票。不要把它编辑成问题来赋予它特殊的状态。如果它比现有的(半途而废的)答案好,您可以接受您自己的答案。@PeterCordes谢谢您的提示,我修改了线程。您没有提到在任何地方还原
SP
。使用此asm,断点处理程序需要在恢复之前将
4
添加到SP,否则内联asm在未通知编译器的情况下修改了SP。@PeterCordes这是我程序的结尾,因此我不需要还原任何内容。我想如果有人想在从bkpt恢复执行后做其他事情,他们可以添加一个“add sp,sp,#4”来撤销str所做的事情?是的。这是一个非常关键的细节,留给未来可能会觉得有用的读者。@PeterCordes感谢您的帮助,非常感谢!
    uint32_t status = Flash_EraseAll();
    __asm volatile ("str %0, [sp, #-4]!\n\t"   // Push to stack
                    "bkpt 0x0\n\t"             // Halt CPU
                    "add sp, sp, #4\n\t"       // Restore SP
                    : : "r"(status));          // status as input to __asm()