AVR再入門
ここ1年ほどはマイコンプログラムから遠ざかってていろいろ忘れているため、izCORE2.0を作成するにあたって、AVRをもう一度勉強しなおします。
これまでのizCOREはほとんどアセンブラ+一部BASIC(MCS社のBASCOM試用版)でやっていたのですが、今度はCも使ってみたいと思います。
AVRでCを使う場合、商用のコンパイラもありますが、GNU の AVR用のGCCもありますのでそれが使えます。
AVR版のGCCはWinAVRという名称でこちらから入手できます。
これをインストールすると、Atmelの統合開発環境AVR Studio4と連携することができ、面倒なmakeファイル作りなんかも自動でやってくれるので便利です。
で、早速試してみました。
Tiny26(10MHz駆動)のPA7にLEDをつないで点滅させるだけ。
プログラムはこんなの。
→テキスト版のソース(S-JIS)
...うーん点滅しません。
いや、目がついていかないほど高速に点滅してるのか?
ウェイトはいい加減だけどチカチカが見えるほどには入れてるはずなんだけど...
いろいろ試してたら分かりました。
コンパイラオプションの最適化切ったら点滅しました。
WinAVRの最適化オプションは5段階(O0,O1,O2,O3,OS)あり、O0が最適化無し。OSが最大のようで、デフォルトではOSです。
実際コンパイラが出力するlssファイル(C→マシンコードの展開図みたいなの)を見てみると、
最適化しない場合(O0)はwait関数のfor文のループがすべて展開されているのに対して、O1以上では、forの痕跡すらなく、いきなりret となっています。
さらに O3以上だとメインルーチンからコールすらしていません。
早い話、オプティマイザが、「空ループは意味がない」とみなしてwait関数のforは展開せず、さらにはO3以上では「wait関数は呼ぶ必要がない」と判断したようです。
また、O0(最適化無し)の場合でも、forループが展開された部分は、想像以上に大量のマシンコードを吐いているため思ったより処理時間食ってるようで、どのくらいのループでどれくらいの時間がかかるのかが予想がしにくいです。
WinAVRの標準のライブラリには汎用IOを使ったソフトウェアUART関数がないため、自前で実装(orどっかから調達)する必要があるのですが、高速通信なんかで精密なタイミングが必要なときには注意が必要そうです。
これまではアセンブラでクロック単位で計算してウェイトかけたりしてたのですが、Cでやる場合にも正確なタイミングが欲しいときにはアセンブラでサブルーチン書いといてそれを呼ぶといったことが必要そうです。(といっても関数呼び出しのオーバヘッドがどのくらいあるのか分からない...)
タイマ割り込み使う場合でも、割り込みのジャンプのオーバヘッドがどのくらいか、コンパイルして吐き出したマシンコード見てみないと分からないかな。
多分レジスタ退避とかやってるだろうし、どれだけのレジスタを使ってるかも最適化オプションによって変わるだろうからコンパイラ通さないと分からないし。
高度な演算や複雑なロジックをまわす場合、高級言語を使うメリットは大きいのですが、シビアなタイミング制御等には弱そうです。
この辺、Cでやってるみなさんはどうしてるんでしょう?
上のソースをコンパイルしたときに出力されたlssファイルです。
最適化 O0の時 OSの時
(どちらもSJISです。文字化けするようならブラウザの設定を変えてください。)
| 固定リンク
この記事へのコメントは終了しました。
コメント
volatile宣言を使用します。
http://www.kumikomi.net/article/explanation/2003/10kumi/13.html
投稿: ほり | 2007.10.28 00:01
ほりさんこんにちは。
情報ありがとうございます。
教えていただいた通り、forのループカウンタにvolatileを指定すると最適化レベルOSでもその部分の最適化はされずにちゃんと展開され、コールもされるようにもなりました(もちろん点滅します)。
ただ、やはりそこで吐かれるコード量と処理時間はCソースからは分からないので、やっぱり厳密時間が欲しいウェイトはアセンブラ関数がいるかなと思っています。
そんななので、クロック同期式のMMCはともかく、115kbpsや650kbpsクラスのソフトUARTに関してはオールCで書くのは絶望的な気がしてます。
(現行izCORE内のプロセッサ間通信は650kbpsくらい。外部PCとのやり取りは115kbps。)
で、現在、アセンブラ関数を用意してCから呼び出すテストをしていますが、うまくいっているようなのでやっぱこれかな、と。
アセンブラで組んでたソフトUARTやMMCアクセスルーチンもあまり手を加えずに移植できそうですし。
投稿: いずみかわ | 2007.10.28 01:16