« グラフに「パーミル」って! | トップページ | メモ:早明浦ダム空撮 »

2019年4月 1日 (月)

ArduinoのEEPROMアクセス、「EEMEM」について

ArduinoのEEPROMを使う上での注意点。
EEPROMに置いたデータを16進ダンプした時、「むむ?」な事態に遭遇しました。

Arduino、EEPROMに不揮発性データを置くことができます。
その時に使うのが「EEMEM」。
たとえば
word EEMEM data0;
word EEMEM data1;
    :
word EEMEM data9;
こんな具合に、順に記していけばdata0~9までEEPROM内のアドレスが得られます。

↓のように、EEPROMアドレスの増加を自分に勘定しなくてもよいわけです。
#define data0 0
#define data1 2   ←wordだから2進む
  :
#define data9 18
1バイトデータだけでなく多バイトデータでも、うまく配置してくれますので数えミスがありません。

※参考
  「eeprom.h」の中で
    #define EEMEM __attribute__((section(".eeprom")))
  「.eeprom」というAVRマイコンのメモリー領域に割り当て
  よっと指示されるわけです。


で、このEEMEMを使って配置したEEPROM内のデータ、これ、どういう
わけか並べた順にならないのです。
普通だと、列記した順に先頭からアドレスが割り振られるんじゃないか
と考えます。
ところが・・・実際は逆順に

このあたりを確かめてみました。
一つはEEMEMを使ってのアドレス割り付け。
もう一つがstructを使ってのアドレス確保です。
offsetof()を使って、構造体先頭からのアドレス増加分を得て、これを
EEPROMのアドレスとします。

~~~~~~~~~~~~~~~~~~~~~~~~~~
// EEMEMのテスト
// EEPROMの読み書きで必要なのはアドレス情報
// EEMEMで順に列記
word EEMEM ee0; // 0~3まで
word EEMEM ee1;
word EEMEM ee2;
word EEMEM ee3;
// structでデータを並べる (実体は無い)
struct eeprom{
 word ss0; // 0~3まで
 word ss1;
 word ss2;
 word ss3;
};
// eepromのwordデータをアクセスするマクロ(アドレスを返す)
#define EPADRSW(eep_word) (word *)offsetof(eeprom, eep_word)

// 書式付シリアル出力
void txprintf(const char *s, ...)
{
va_list vp;
char bff[80]; // バッファを確保
  va_start(vp,s);
  vsnprintf(bff,sizeof(bff),s,vp);
  Serial.print(bff);
  va_end(vp);
}

void setup() {
const char s[]="%04X:%4d\n"; // アドレスとデータ
word i;
 Serial.begin(9600); // シリアル通信
 for(i=0; i<4;i++){ // 4データ EEPROMに書き込み
  eeprom_write_word(2*i, 1001+i); // データは1001から
 }
 txprintf(s, &ee0,eeprom_read_word(&ee0)); // ee0~3のアドレス
 txprintf(s, &ee1,eeprom_read_word(&ee1));
 txprintf(s, &ee2,eeprom_read_word(&ee2));
 txprintf(s, &ee3,eeprom_read_word(&ee3));
 Serial.println(); // 改行
 txprintf(s, EPADRSW(ss0),eeprom_read_word(EPADRSW(ss0))); // ss0~3のアドレス
 txprintf(s, EPADRSW(ss1),eeprom_read_word(EPADRSW(ss1)));
 txprintf(s, EPADRSW(ss2),eeprom_read_word(EPADRSW(ss2)));
 txprintf(s, EPADRSW(ss3),eeprom_read_word(EPADRSW(ss3)));
}

void loop() {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~

シリアルモニターした結果。
 ↓
0006:1004  ←EEMEMで記述した部分
0004:1003
0002:1002
0000:1001

0000:1001  ←struct
0002:1002
0004:1003
0006:1004

最初の4データ、「EEMEM」での書式では列記したのとは逆順にアドレス
が割り振られているのが見えています。
structで実体は無いデータを列記した場合は、書いた順序通りに現れます。

これ、データの名前でアクセスする分には何も問題ありません。
しかし、デバッグ時のときなど、EEPROMデータを16進ダンプして
データを見ようとした時、やはり記述した順に並んでいてほしいもの
です。


もう一つの注意点。
ArduinoのブートローダーはEEPROM内の初期化データを扱うことが
できません。
ですので、EEPROMデータの初期化は自前で行わなければなりません。


※AVRマイコンsectionの種類
・http://d.hatena.ne.jp/seinzumtode/20140719/1405789889

 

|

« グラフに「パーミル」って! | トップページ | メモ:早明浦ダム空撮 »

電子工作」カテゴリの記事

Arduino」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




« グラフに「パーミル」って! | トップページ | メモ:早明浦ダム空撮 »