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 に答える