ニックネーム: 居酒屋ガレージ店主
★ZAQのBlogari停止のため、あれこれ「データ吸い出し」対策しています。 新規記事はとりあえず停止。 コメント書き込みはまだ有効です。 (JH3DBO 下間憲行)
2013年03月28日(木)
AVRマイコンのCコンパイラ 具体的に
AVRのコンパイラ(AVR GCC)で悩んでいる内容、こんなのです。
  (半角スペースだと圧縮されてしまうので全角にしています)

割り込みルーチン内で処理されるワードデータを読み書き
するために作った関数です。
<1>は比較のための関数でタイマーを直接読んでます。
<2>は書き込み処理、
<3>が問題の読み出しルーチンです。
割り込みをいったん禁止してからワードデータを読み出して
います。
AVRマイコンのOPコードは16ビットですが、メモリの読み書きを
処理できるのは8ビット単位ですんでしかたありません。

= = = = = = = = = = = = = =
/***** <1>タイマー1(word)データ読み出し  *****/
uint16_t read_timer1(void)
{
uint8_t sreg;
uint16_t d;
  sreg = SREG;
  cli();    // 割り込み禁止
  d = TCNT1;  // タイマー読み出し
  SREG = sreg; // ◆割り込み状態復帰
  return d;
}

/***** <2>wordデータ書き込み *****/
void write_word(uint16_t *p, uint16_t d)
{
uint8_t sreg;
  sreg = SREG;
  cli();
  *p = d;     // wordで書き込み
  SREG = sreg;  // ◆
}

/***** <3>wordデータ読み出し *****/
uint16_t read_word(uint16_t *p)
{
uint8_t sreg;
uint16_t d;
  sreg = SREG;
  cli();
  d = *p;    // ★1
  SREG = sreg;  // ★2
  return d;
}
= = = = = = = = = = = = = =

これをコンパイルして出てきたコードがこれ↓

= = = = = = = = = = = = = =
<1>
0000005a <read_timer1>:
 5a:  8f b7   in r24, 0x3f  ; 63
 5c:  f8 94   cli
 5e:  2c b5   in r18, 0x2c  ; 44
 60:  3d b5   in r19, 0x2d  ; 45
 62:  8f bf   out 0x3f, r24  ; 63 ◆
 64:  c9 01   movw  r24, r18
 66:  08 95   ret

<2>
00000068 <write_word>:
 68:  fc 01   movw  r30, r24
 6a:  8f b7   in r24, 0x3f  ; 63
 6c:  f8 94   cli
 6e:  71 83   std Z+1, r23  ; 0x01
 70:  60 83   st Z, r22
 72:  8f bf   out 0x3f, r24  ; 63 ◆
 74:  08 95   ret

<3>
00000076 <read_word>:
 76:  fc 01   movw  r30, r24
 78:  8f b7   in r24, 0x3f  ; 63
 7a:  f8 94   cli
 7c:  8f bf   out 0x3f, r24  ; 63 ★2
 7e:  80 81   ld r24, Z    ★1
 80:  91 81   ldd r25, Z+1  ; 0x01
 82:  08 95   ret
= = = = = = = = = = = = = =

★1と★2の順番が問題。
リターンししなにメモリを読もうとして禁止した割り込みが先に再開され
てしまっています。
これではあきません。
特定アドレスのデータを直接示すと大丈夫なんですが、ポインタにすると
このようにアウト。
書き込みではうまく行くのに…

そして、コンパイラオプションを「最適化無し」にすると、こんなコードが
でてきて★1、★2の順になりうまく行くようになります。
けど、こんなコードでマイコンを動かしたくないですよ。

= = = = = = = = = = = = = =
★最適化コンパイルオプション「-O0」で
  (最適化なし)
000000d8 <read_word>:
 d8:  df 93   push  r29
 da:  cf 93   push  r28
 dc:  00 d0   rcall  .+0   ; 0xde <read_word+0x6>
 de:  00 d0   rcall  .+0   ; 0xe0 <read_word+0x8>
 e0:  0f 92   push  r0
 e2:  cd b7   in r28, 0x3d  ; 61
 e4:  de b7   in r29, 0x3e  ; 62
 e6:  9d 83   std Y+5, r25  ; 0x05
 e8:  8c 83   std Y+4, r24  ; 0x04
 ea:  ef e5   ldi r30, 0x5F  ; 95
 ec:  f0 e0   ldi r31, 0x00  ; 0
 ee:  80 81   ld r24, Z
 f0:  8b 83   std Y+3, r24  ; 0x03
 f2:  f8 94   cli
 f4:  ec 81   ldd r30, Y+4  ; 0x04
 f6:  fd 81   ldd r31, Y+5  ; 0x05
 f8:  80 81   ld r24, Z   ★1
 fa:  91 81   ldd r25, Z+1  ; 0x01
 fc:  9a 83   std Y+2, r25  ; 0x02
 fe:  89 83   std Y+1, r24  ; 0x01
100:  ef e5   ldi r30, 0x5F  ; 95
102:  f0 e0   ldi r31, 0x00  ; 0
104:  8b 81   ldd r24, Y+3  ; 0x03
106:  80 83   st Z, r24   ★2
108:  89 81   ldd r24, Y+1  ; 0x01
10a:  9a 81   ldd r25, Y+2  ; 0x02
10c:  0f 90   pop r0
10e:  0f 90   pop r0
110:  0f 90   pop r0
112:  0f 90   pop r0
114:  0f 90   pop r0
116:  cf 91   pop r28
118:  df 91   pop r29
11a:  08 95   ret
= = = = = = = = = = = = = =


その後、あれこれしていましたら、あっさり解決しました。

関数の引数をこんな具合に変えたらOK。
  「uint16_t read_word(volatile uint16_t *p)」

魔法の言葉「volatile」。 出てきたコードがこれ↓
= = = = = = = = = = = = = =
00000076 <read_word>:
 76:  fc 01  movw  r30, r24
 78:  8f b7  in r24, 0x3f  ; 63
 7a:  f8 94  cli
 7c:  20 81  ld r18, Z    ★1
 7e:  31 81  ldd r19, Z+1  ; 0x01
 80:  8f bf  out 0x3f, r24  ; 63 ★2
 82:  c9 01  movw  r24, r18
 84:  08 95  ret
= = = = = = = = = = = = = =

★1と★2の順番がおもわくどうりになりました。




2013年3月28日 09時57分 | 記事へ | コメント(2) | トラックバック(0) |
| ・電子回路工作 |
トラックバックURL:http://blog.zaq.ne.jp/igarage/trackback/3316/
※ブログ管理者が承認するまで表示されません
2013年03月29日(金) 22:55 by きゅうる村
最適化なしオプションとvolatileで、生成コードが異なるんですね。
2013年03月30日(土) 08:42 by 居酒屋ガレージ店主(JH3DBO)
AVRマイコン、ずっとアセンブラでプログラムを書いていました。
もともと容量の小さなマイコンですんで、複雑なことをさせる
必要がなかったということもあります。
先日のArduinoでコンパイラを初体験。
その流れでAVR studioでのコンパイルとなったのです。

コンパイラがはき出すコード、どんなチップでもクリチカルな所は
機械語での動きを確かめておかなくてはなりません。
賢いコードが出てきて感心することもあれば「やめてくれ〜」って
なこともあります。

コメントを記入  
お名前(必須)
 
パスワード:
 
メール:
 
URL:
 
非公開:  クッキーに保存: 
※非公開にチェックを入れると、管理者のみにコメントが届きます。
ブログの画面には表示されません。
captcha


※画像に表示されている文字を入力してください(半角・大文字/小文字の区別なし)。
文字が読みづらい場合はこちらをクリックしてください。
小文字 太字 斜体 下線 取り消し線 左寄せ 中央揃え 右寄せ テキストカラー リンク