0

我想用内联汇编替换 32 位值的最高字节,以下代码使用 spi 接口将缓冲区写入 FRAM 内存:

#define _load_op_code(op_code, addr)\
  __asm__ __volatile__ (\
  " ldi %D0, %1"     "\n\t"\
  : "=d"  ((uint32_t)addr)\
  : "M" (op_code)\
  )

#define SMEM_WREN   0x06
#define SMEM_WRITE  0x02

void fram_write(uint32_t addr, uint8_t *buf, uint16_t len) {
  FRAM_SELECT();
  spi_send_char(SMEM_WREN);
  FRAM_DESELECT();
  _load_op_code(SMEM_WRITE, addr);
  FRAM_SELECT();
  spi_send_32b(addr);
  spi_send(buf, len);
  FRAM_DESELECT();
}

在 _load_op_code() 内联汇编 addr 变量变得混乱之后 - 编译器使用为 addr 分配的寄存器作为其他操作的临时寄存器,我失去了原始的 addr 值。addr 实际上是 24 位变量。知道这段代码有什么问题吗?

4

1 回答 1

1

addr 的原始值丢失,因为它被带有 SMEM_WRITE 和 3 个未定义字节的 asm 语句覆盖。从 GCC 手册:

普通输出操作数必须是只写的;GCC 假定指令之前这些操作数中的值是死的,不需要生成。扩展 asm 支持输入输出或读写操作数。使用约束字符“+”来表示这样的操作数并将其与输出操作数一起列出。

于 2013-08-22T20:08:41.907 回答