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

时间:2019-05-28 14:13:10

标签: 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]:立即操作数不是常量

我尝试使用具有不同串联设置的预处理器宏,但无济于事。

有人知道如何将运行时相关的状态标志作为立即输入到IAR中的__asm()块吗?根据我读过的here,这是不可能的,但是这样做可能会有聪明的技巧。

P.S .:是的,作为一种解决方法,我可以使用switch语句在其中列出所有可能的状态并对其进行硬编码,但这很丑陋而且很长。

编辑:

基于以下公认的答案,这是我将来的实现方式:

uint32_t status = Flash_EraseAll();
__asm volatile ("str %0, [sp, #0]!" : : "r"(status));
__asm("bkpt 0x0");

执行嵌入式代码后,状态标志被压入堆栈(不减少SP以便于应用程序使用),并且CPU的“返回码” 0暂停。因此,通过读取最终SP值以下的地址,而不是8位,而是可以“向外界报告更多”内容(在这种情况下为32位)。

2 个答案:

答案 0 :(得分:1)

我会将值压入堆栈,然后使用带有定义编号的foreach (var metric in metrics) { var added = context.Set(metric.GetType()).Add(metric); foreach (var dbEntityEntry in context.ChangeTracker.Entries()) { //If these entities exist, don't add them. var metricContext = dbEntityEntry.Entity as MetricContext; if (metricContext != null) { var found = context.MetricContext.FirstOrDefault(c => c.Context == metricContext.Context); if (found != default(MetricContext)) { dbEntityEntry.State = EntityState.Detached; } } } } 指令,以便调试器可以在堆栈中查看此状态。

类似这样的东西(伪代码):

bkpt

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

由于__asm("push %0" : : "i" (status)); __asm("bkpt %0" : : "i" (0x70)); 仅使用立即数进行编码,因此您显然不能在运行时更改它,因为必须修改代码。

答案 1 :(得分:0)

基于@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()

汇编指令告诉编译器将状态变量放入方便的寄存器“ r”,并将该寄存器的内容存储在堆栈指针的递减地址下,然后以立即数0暂停CPU的执行。

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

这样,人们可以动态地向外界“报告”更多的东西(在本例中为32位),而不是从bkpt的立即数生成静态的8位代码。

正如@PeterCordes强调的那样,push和bkpt语句必须在同一行内联汇编指令中,否则编译器可能决定在这些语句之间插入代码。另外,由于编译器仅对SP进行控制,因此必须将SP恢复为__asm()之前的值。