简体   繁体   English

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

[英]IAR assembler BKPT immediate as input operand

I am writing a flashloader for a Cortex M4 device and I'd like to "return" a value for the driving PC application using the breakpoint instruction's immediate value. 我正在为Cortex M4设备编写Flashloader,我想使用断点指令的立即值“返回”驱动PC应用程序的值。

While hardcoding an immediate works fine: 虽然对立即数进行硬编码可以很好地工作:

__asm("bkpt 0x70");
__asm("bkpt %0" : : "i" (0x70));

as soon as I want to "return" something run-time dependent like 我想“返回”运行时相关的东西

uint8_t status = Flash_EraseAll();
__asm("bkpt %0" : : "i" (status));

The compilation fails with 编译失败并显示

Error[Ta090]: Immediate operand is not constant 错误[Ta090]:立即操作数不是常数

I tried using preprocessor macros with different concatenate setups, but to no avail. 我尝试将预处理器宏用于不同的串联设置,但无济于事。

Has anybody got an idea of how I could input the run-time dependent status flags to the __asm() block in IAR as an immediate? 有谁知道如何将运行时相关的状态标志作为立即输入到IAR中的__asm()块? Based on what I read here , this is not exactly possible, but there might be a clever hacky way to do it. 根据我在这里阅读的内容,这并非完全可能,但是可能有一种巧妙的方法。

PS: Yes, as a workaround I could use a switch statement where I list and hardcode every possible state, but that's just ugly and long. PS:是的,作为一种解决方法,我可以使用switch语句,在其中列出所有可能的状态并对其进行硬编码,但这很丑陋而且很长。

I would push the value on the stack, and then use the bkpt instruction with a defined number, so the debugger can look at the stack for this state. 我会将值压入堆栈,然后使用具有定义编号的bkpt指令,以便调试器可以在堆栈中查看此状态。

Something like this (pseudocode): 这样的东西(伪代码):

__asm("push %0" : : "i" (status));
__asm("bkpt %0" : : "i" (0x70));

Of course you shouldn't forget to cleanup the stack afterwards. 当然,您不应该忘记随后清理堆栈。

Since bkpt is encoded with an immediate only, you can obviously not change that at runtime, as you would have to modify the code. 由于bkpt仅使用立即bkpt进行编码,因此您显然不能在运行时更改它,因为必须修改代码。

Based on @Devolus 's idea, I ended up with the following: 基于@Devolus的想法,我得出以下结论

    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()

The assembly instructions tells the compiler to put the status variable to a convenient register "r", and store that register's content under the stack pointer's pre-decremented address, then halt the CPU's execution with an immediate 0. 汇编指令告诉编译器将状态变量放入方便的寄存器“ r”,并将该寄存器的内容存储在堆栈指针的递减地址下,然后以立即数0暂停CPU的执行。

The driving application would poll the target if it was halted (bkpt hit). 如果目标被停止(击中目标),则驾驶应用程序将轮询目标。 If halted, by reading the 16-bit data under the current PC (__asm("bkpt 0x00") -> 0xbe00 -> #imm = 0xbe00 & 0x00ff = 0), the application can make sure that the execution had stopped at the right place. 如果暂停,则通过读取当前PC下的16位数据(__asm(“ bkpt 0x00”)-> 0xbe00-> #imm = 0xbe00&0x00ff = 0),应用程序可以确保执行在右侧停止地点。 It then would read the 32-bit data under the final SP address to fetch the status of the embedded code's execution. 然后它将读取最终SP地址下的32位数据,以获取嵌入式代码执行的状态。

This way, instead of a static 8-bit code from the bkpt's immediate, one can "report" more stuff to the outside world dynamically (32-bit in this case). 这样,人们可以动态地将更多的东西“报告”给外界(而不是bkpt的静态8位代码)(在这种情况下为32位)。

As @PeterCordes highlights, the push and bkpt statements must be in the same inline assembly instruction, otherwise the compiler might decide to insert code between the statements. 正如@PeterCordes强调的那样,push和bkpt语句必须在同一行内联汇编指令中,否则编译器可能决定在这些语句之间插入代码。 Also, the SP must be restored to the value before the __asm() as the compiler assumes sole control over SP. 另外,由于编译器仅对SP进行控制,因此必须将SP恢复为__asm()之前的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM