LoginSignup
1
0

More than 5 years have passed since last update.

ESP-WROOM-02プログラムでalignを指定する方法

Last updated at Posted at 2017-03-19

ESP-WROOM-02でrtcメモリやflashメモリにデータを読み書きする場合、読み書きに使うメモリのアドレスを32bit境界に合わせなければなりません。その方法を調べたのでメモします。

要約

変数宣言に __attribute__((aligned(4))) を付ければよい。

uint8 data __attribute__((aligned(4)));

alignが必要な場面

例えば、rtcメモリを読む関数 system_rtc_mem_read の定義は次のようになっています。

bool system_rtc_mem_read(uint32 src_addr, void *des_addr, uint32 load_size);

第2引数のdes_addrは32ビット境界のアドレスでなければなりません。つまり、16進数で表した場合下1桁が 0, 4, 8, C のいずれかでなければなりません。

alignを指定しないでプログラムを書いた例(その1)

グローバル変装としてuint8 dataBuffer[8];を宣言しているプログラム書いた場合、アドレスがどうなっているか試してみましょう。

program1-no-align.ino
uint8 dataBuffer[8];

void setup() {
  Serial.begin(115200);
  delay(10); // macのserial consoleが文字化けしないためのおまじない
  Serial.println("");
  Serial.println("--- setup() ---");

}

void loop() {
  Serial.println("--- loop() ---");
  printAddress("dataBuffer=", (uint32)dataBuffer);

  Serial.println("Wait for 10 seconds");
  delay(10*1000);
}

void printAddress(char *name, uint32 address) {
  Serial.print(name);
  Serial.println(address, HEX);
}

このプログラムをmac上のArduino IDEでコンパイルしてESP-WROOM-02で実行してみると次のような結果が得られます。

--- setup() ---
--- loop() ---
dataBuffer=3FFEE298
Wait for 10 seconds

アドレスの下1桁が 8 なのでこれでOKです。

alignを指定しないでプログラムを書いた例(その2)

では、先ほどのプログラムにグローバル変数 uint8 aaa; を追加してみましょう。

program2-no-align.ino
uint8 dataBuffer[8];
uint8 aaa;


void setup() {
  Serial.begin(115200);
  delay(10); // macのserial consoleが文字化けしないためのおまじない
  Serial.println("");
  Serial.println("--- setup() ---");

}

void loop() {
  Serial.println("--- loop() ---");
  printAddress("dataBuffer=", (uint32)dataBuffer);
  printAddress("aaa =", (uint32)&aaa);

  Serial.println("Wait for 10 seconds");
  delay(10*1000);
}

void printAddress(char *name, uint32 address) {
  Serial.print(name);
  Serial.println(address, HEX);
}

このプログラムを実行してみるとこういう結果が得られます。

--- setup() ---
--- loop() ---
dataBuffer=3FFEE299
aaa =3FFEE298
Wait for 10 seconds

dataBufferのアドレスの下1桁が 9 になっています。これではいけません。
変数を色々宣言していると、そのアドレスが何になるかはコンパイラ任せなので、32bit境界になるかどうかは運任せになります。

alignを指定したプログラム

「この変数は32bit境界に配置してね!」とコンパイラにお願いすることができます。お願いの方法はコンパイラによってまちまちです。ESP-WROOM-02用のプログラムをArduino IDEで記述する場合は、変数宣言に __attribute__((aligned(4))) を付ければ良いことがわかりました。

先ほどのプログラムにこれを付けてみるとこうなります。

program3-with-align.ino
uint8 dataBuffer[8] __attribute__((aligned(4)));
uint8 aaa;


void setup() {
  Serial.begin(115200);
  delay(10); // macのserial consoleが文字化けしないためのおまじない
  Serial.println("");
  Serial.println("--- setup() ---");

}

void loop() {
  Serial.println("--- loop() ---");
  printAddress("dataBuffer=", (uint32)dataBuffer);
  printAddress("aaa =", (uint32)&aaa);

  Serial.println("Wait for 10 seconds");
  delay(10*1000);
}

void printAddress(char *name, uint32 address) {
  Serial.print(name);
  Serial.println(address, HEX);
}

このプログラムを実行するとこういう結果が得られます。

--- setup() ---
--- loop() ---
dataBuffer=3FFEE29C
aaa =3FFEE298
Wait for 10 seconds

dataBufferのアドレスの下1桁が C になっているので、32bit境界なのでOKです。

TODO

Macでしか動作を確かめていないので、Windowsでもやってみる必要があります。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0