トップ 新規 編集 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

AVRよくある質問(FAQ)

最終更新時間:2009年04月29日 19時29分10秒

AVRについてのFAQ

(PICとAVRではどちらが偉いんですか?等という、自明のこと 宗教戦争の引き金になる事は書かない事。)
AVRマイコンデバイスに関するFAQは「AVRよくある質問(FAQ) デバイス編」にあります。ここはAVR開発環境及びソフトウェアに関するFAQです。

AVRStudio FAQ

 avrgccをAVRStudioでシミュレートするには?

 アセンブラ用のデバイス定義(.INC)ファイルについて

HEROのAS4XML.ZIP README.TXT より

AVR Studio 4.11βから、付属のXMLCONVERT.EXEにより、XMLファイルからデバイス定義インクルード゙(.INC)ファイルを作成するようになりました。XMLCONVERTによるINCファイル作成方法については、HEROサイトのAVRappnt.CHMをご覧ください

 知られているバグなど(バグではないかも)

高速PWMのシミュレート動作がおかしい(4.08/4.11 未解決)

AVRStudio4.08/4.11βのマニュアルにははっきりした記載がない(OCRが変という記載しかない)けど、高速PWM設定が位相基準PWMになってしまう。

mega48でのWDTONヒューズ未プログラムで動くはずのWDTによる割り込み動作がうまくシミュレートできない

 AVRStudio4.11でのSTK500/AVRISPのファームウェア更新方法

症状
  • AVRStudio4.11でSTK500/AVRISPのファームウェア更新がうまく出来ない
  • AVRStudio4.11SP3ではうまく認識できるようです。
原因
  • AVRStudio4.11以降STK500/AVRISPの通信プロトコルが変更になっています
  • AVRStudioで以前のプロトコルのSTK500/AVRISPをうまく認識出来ないようです(組み込まれていない?)
  • 認識できないのでファームウェアの更新の画面が出せません(更新処理が出来ない)
  • AVRStudioの最新ヘルプ(STK500.CHM/AVRISP.CHM)の手動での更新方法の記述も間違っているようです。
対策
  • AVRStudioからの更新ではなくUpgrade.exeによる手動更新を行います
    • Upgrade.exeはAVRStudio4.11をインストールしたフォルダ内のSTK500フォルダ内にあります
更新方法
  • STK500/AVRISPをfirmware-programmingモードにします(途中まではSTK500.CHM/AVRISP.CHMと同じです)
    • STK500の場合(STK500.CHMのSTK500ファームウェア手動更新を参照)
      1. STK500の電源を切ります
      2. STK500電源投入起動中の間、(AT45D021 DataFlash傍に配置された)PROGRAMボタンを押下します
    • AVRISPの場合(AVRISP.CHMのAVRISPの手動ファームウェア更新を参照)
      1. AVRISPへ電力を供給する対象基板を電源OFFにすることにより、AVRISPを電源OFFにします
      2. 図1.や図2.で示されたピン穴を短絡します(AVRISP.CHM参照)
      3. AVRISPへ電力を供給する対象基板への電力供給により、AVRISPを電源ONにします
      4. 5秒間待ちます
      5. 上記の短絡を取り去ります
  • AVRStudio上からではなくAVRStudioをインストールしたフォルダ内のSTK500\Upgrade.exeを直接起動して更新します。
  • 更新が正常に終了したら STK500/AVRISPを電源リセットします
参考・注意点
  • STK500.CHM/AVRISP.CHMの日本語版もあります HEROさん
  • 通信ケーブルは正常に接続されていなければなりません
  • ファームウェアを更新する時にはターゲットデバイスが挿入されていてはなりません
    • 特にAVRISPの場合はターゲットボードから電源供給するので注意してください
    • ターゲットデバイスとは制御CPUのAT90S8535ではなくユーザ用のCPUのこと
  • AVRStudio4.11以降の新しいファームに更新するとAVRStudio4.10以前のAVRStudioでは認識できなくなりますので注意してください
    • ファームウェアのファイルはAVRStudioそれぞれのバージョンのフォルダSTK500の中のstk500.ebnです(古いものはstk500.hexのものもある)
    • 必要ならば古いバージョンのものをバックアップしておきましょう
  • ISPの書き込みクロックの周波数指定が追加されています
    • デフォルトでは書き込み時間が長いので適宜設定してください
    • AVRStudioではプログラマダイアログの[Board]タブの[ISP Freq.]で設定します
    • STK500.EXEでは -I オプションで指定します
      • 例えば stk500 -I1MHz とするとそれに一番近い値で設定されます
    • ターゲットのCPUのクロックに合わせて適当な値を指定します
    • 目安>fck-12MHz未満はfck/4、12MHz以上はfck/6 以内
      • fck-4MHz以上では最高のスピードでも大丈夫です(AVRISP:921.6KHz/STK500:1.845MHz)
    • ATtiny2313/ATtiny13等は出荷時のクロックが低くなっています(1/8分周)ので高い発振周波数を設定するまでは低いレートで書き込みます
      • ATtiny2313の場合は内蔵8MHzの1/8分周で1MHz動作ですので最高でAVRISP:230.4KHz/STK500:115.2KHzを選択
      • [AVRマイコン総合スレ Part4]によると出荷時は内蔵4MHzの1/8分周で512KHz動作らしい。その時はISPクロックはAVRISP:57.6KHz/STK500:115.2KHz(<=128KHz)となる。
      • 上記以外でも新しいCPUは出荷時のクロックが低いものがあるのでデータシートで確認してください
  • ATtiny2313/ATtiny13/ATmega169はSTK500.CHM/AVRISP.CHMの既知の問題点を読んでおいてください(重要)
  • WinAVR20050214のavrdude.exeはSTK500/AVRISPの新ファームには対応していません

WinAVR(avrgcc)FAQ

 インストール

 プログラミング

標準的なC言語のお勉強は自分でがんばってください。ってことで、ここではWinAVR独特の問題だけを対象にしましょう。

まずはここ!(avr-libcのドキュメント)

コンパイル結果を小さくしたい!(小さなコードのために)

  • 登場回数が少ない処理を安易に関数化しない。関数化によるオーバーヘッドがある。マクロやインライン関数だと、周囲との間でレジスタの使い方について最適化が掛かって結構小さくなることもある。
    • ただし、呼び出されるのが1カ所からのみで、引数やreturnなどでの値のやりとりがなければ、コンパイラの方で勝手にインライン化して、関数化しない状態と同様になることもある模様。
  • 割り込みルーチン内で複雑な処理をしない。割り込みルーチンは通常の関数よりもレジスタの復帰退避処理が多くなります。割り込みルーチン内に大きな処理を入れるとほとんど全レジスタを退避・復帰するようなコードを生成する(復帰退避だけで100バイト・100クロック以上)ことがしばしばあります。
  • グローバル変数は最低限にして、ローカル変数を積極的に使う。かさばるlds/sts命令が減る。
  • 関数内でグローバル変数を繰り返し参照する場合、途中で割り込みルーチンなどによる書き換えを考慮してか、そのたびにldsで参照するコードを吐きます。途中で書き換えられることがないと思われる場合は、ローカル変数に一度コピーしてから使用するとレジスタに割り当てられコードサイズが大幅に減ることがあります。
  • あまりに引数の数が多いときは受け渡しに構造体ポインタ渡しも使ってみる。関数のオーバーヘッドが激減することあり。あまりに引数の総データサイズが大きいときにも考慮。
  • stdlib関連、stdio関連の関数にはかなりメモリ食いのものもあります。必要な機能を実現するのに小さな自作関数で実現できないか考えてみる。(例:0-100の整数表示や16進変換にitoa()を使わず自作関数で対応するなど)
  • 8bit変数によるswitch-case分岐をif-elseに書き換えてみる。AVRGCCはデフォルトで16bitでswitch-case扱いますので、switch()内の値が8bit変数であっても、2バイト比較演算で分岐するコードを吐きます。if-elseだと素直に1byte比較となります。1分岐につき1ワードの差になりますので、多数の条件分岐を行う場合は結構大きな差になることがあります。
    #でもswitch-case書きやすいので、うまく最適化してくれるとうれしいな・・・。
  • 関数だけでもアセンブラ使用を考慮
  • 変数を初期化しないで宣言すると "warning: 'hoge' might be used uninitialized in this function" が出てしまう場合、プログラムの流れ上支障がなくても0で初期化するようにしてみるとコードサイズが小さくなることがある(・_・)。
  • 大量にprogram memory内定数を使っていて、EEPROMが余っている場合、これを全てEEPROM上定数に変える。
  • グローバル変数に、使っていないSFIORを使う。in/out命令だけで使えるので、2バイトアドレス指定が必要なメモリよりコードサイズが小さくなる。例:#define gloval_word_memory OCR1A
  • ファイル内から1回しか使われない関数はstaticにしておくと最適化で潰してくれるので、見やすさのため積極的に分割するのもいい。

コンパイラが勝手にループの中の式を削除しちゃうんですけど。

  1. 割り込み処理中で立つフラグをメインループで監視する場合は、変数に volatile 宣言を付ける。( volatile static unsigned int iflg=0; とか )
  2. nop() は #define nop() __asm__ __volatile__ ("nop") にすると良い。

cbi(),sbi(),outp(),inp(),PRG_RDB()などでエラーが起こります

cbi()   , sbi()
outp()  , inp()
__inw() , __outw()
__inw_atomic() , __outw_atomic()
PRG_RDB()

これらのマクロは2005/02/14版のWinAVR(AVR-LibCの1.2.3)から削除されました。下記参照。

main()の末尾にfor(;;)は必須ですか?

main()の末尾におきまりのfor(;;);をつけなくても、avrgccはここに無限ループコードをつけてくれるようですので、不要とも言えます。しかし、以下の理由によりつけた方がいいようです。

  1. 無限ループにしておいて割り込みで処理するようなアプリケーションの場合、main()末尾の無限ループに対応するCコードがないと、AVRStudioによるデバッグでうまくデバッグが働かないようです。(割り込み内にブレークポイントを置いてRunすると、毎回avrgccが用意した無限ループコードで停止してしまう)
  2. 意外にも、無限ループfor(;;);をつけた方がコードが短くなります。以降をunreachable codeとして削除するのでしょう。これをつけないとgccは意味なくmain()の返り値として0x0000を返す(どこに??)ようなコードを付け加えるようです。
// int main(void)で、for無限ループなし
+000000C8:   E080        LDI     R24,0x00         Load immediate
+000000C9:   E090        LDI     R25,0x00         Load immediate
+000000CA:   C000        RJMP    PC+0x0001        Relative jump
+000000CB:   CFFF        RJMP    PC-0x0000        Relative jump
//void main(void)とした場合
+000000C8:   C000        RJMP    PC+0x0001        Relative jump
+000000C9:   CFFF        RJMP    PC-0x0000        Relative jump
//for (;;)で終わってる場合
+000000C8:   CFFF        RJMP    PC-0x0000        Relative jump
//これより後にはコードなし

コンパイル出来上がりサイズはどこでわかるの?

コンパイル後にこんなのが出てきます。(WinAVR20050214の標準Makefile使用時。Makefileによって多少は異なるかも知れません)

AVR Memory Usage:
-----------------
Device: atmega48
Program:     150 bytes (1.8% Full)
(.text + .data + .bootloader)
Data:        100 bytes (19.5% Full)
(.data + .bss + .noinit)
-------- end --------

winavr20050214バージョンでは、一部のデバイスでFLASH総量のデータが誤っているようで、%表示にバグがあります。上記についてもatmega48のFLASHは4096バイトのはずなのに、150/4096*100=3.7%にはなりません。

このサイズ計算は C:\WinAVR\bin\avr-mem.sh の定数定義から行われているようです。

"atmega48") PROGMAX=${AVR8K}; DATAMAX=${AVR512}; EEPROMMAX=${AVR256};;
"at90s2313") PROGMAX=${AVR8K}; DATAMAX=${AVR128}; EEPROMMAX=${AVR128};;

等、誤っている定数を直せばいいみたいです

at90s2313 --> PROGMAX=${AVR2K};
atmega168 --> PROGMAX=${AVR16K};
atmega48  --> PROGMAX=${AVR4K};
attiny11  --> EEPROMMAXの項を削除。*tiny11にEEPROMは無いよね?
↑これらは多分、上の行のコピペミスだろうけど、
at90s4414,4434 の DATAMAX=352 なのが変?なんで${AVR256};じゃないの?
同じくat90s2333,attiny22 の DATAMAX=224 -->  ${AVR128};じゃないの?
↑これらは、わざわざ書き換えているので、意味があるのかもしれない。
どうでしょうか?

[delay.h] _delay_ms(200);で200msec待つコードを作ってくれない

これらのwait疑似関数は待てる最長時間がかなり短くなっています。ターゲットクロック周波数によって異なり、ターゲット10MHzだと_delay_ms()は26msまで、_delay_us()は76.8μsまでとなってしまいます。周波数に反比例して上限時間は短くなります。(20MHzだとその半分)

delay_msについては、1ms単位でいいなら以下の手があるでしょう。

void delay_ms(t) { while (t--) _delay_ms(1); }

これでもいいかも(0.1ms単位まで)

void delay_sms(uint16_t t) { while (t--) _delay_ms(0.1); }
#define delay_ms(t) delay_sms((t)*10)

_delay_us()については、多少設定は粗くなりますが、_delay_ms()を使うことでも解決できます。

_delay_ms(0.04);  //_delay_us(40)のかわりにこれを使う。小数が使えます。
  • _delay_ms()は4clock*65536=262144clockまでのwaitを実現できる_delay_loop_2()を、_delay_us()は3clock*256=768clockまでのwaitを実現できる_delay_loop_1()を使用して実現しているためです。

[util/delay.h] _delay_ms(x);としたら、コードサイズがふくれあがった

 delay.hの提供するウェイトルーチンは、引数としてdouble(倍精度実数)をとります。これとF_CPU(CPUクロックを表すマクロ定義)を元に、内部で実際にウェイトルーチンを形成する_delay_loop_2()に渡すループ回数値(16bit整数)に変換するようになっています。

_delay_ms(1)のように引数に定数を入れているときは、_delay_loop_2に渡す値も定まりますので、単に_delay_loop_2(整数値)に置き換えられます。しかし、_delay_ms(x)のように変数を渡すと、_delay_loop_2に渡す値が定まらないので、馬鹿正直に整数値xを暗黙の型変換でdoubleに変換し、それを内部で_delay_loop_2に渡す値に変換する計算を組み込みます。これはdouble型の実数演算なので、AVRにとってはかなり大きな計算ルーチンとなります。

というわけで、_delay_ms()には原則として定数を渡してください。整数変数を渡したければ先に書いたように_delay_ms(1)をx回ループさせるような関数を組んだ方が良いと思われます。

[util/delay.h] _delay_ms()などで予定のウェイトがかからない

  • _delay_ms()/_delay_us()の引数上限を超える値を渡していないか?(前述)
  • システムクロックを表すマクロ F_CPU を定義していますか?

#include <util/delay.h>より前に定義する必要があります。

 Editor(Programmers NotesPad)

コメントを日本語で書くと化けるんですが

  • Tool / Option / Style / Schemes (Scheme C/C++)で、 Comment と CommentLine の Fontを [Terminal] にする。
  • ↑の方法だと、コメントのフォントと通常行のフォントが違うので、
  //76543210
b=0x00001111

の様な表記で微妙に上下の文字があわないという障害がある。Tool / Option / Style / Schemesで、一旦ResetAllにして戻した後、General/Defaults/CodePageをUnicode(UTF-8)にして、ProgramersNotepadを再起動してみると、ちゃんと日本語が使える(模様)

 プレフィックス

0xは16進数のプレフィックスですが、WinAVR では 0bで2進を表す事が可能です。

0xFF = 0b11111111
  • ただし、これは WinAVR 固有の拡張であり、他の OS 上の avr-gcc で使うことはできません。
  • patch-binary-constantsが当たっていればOS,Targetを問いません。

 mfile,Makefileについて

mfileの使い方

AVRStudio(4.07以降)でavrgccをデバッグする方法を参照。

mfileの各種設定のデフォルト値を変えたい

makefile_template がデフォルトのmakefileになっています。オリジナルのmakefile_templateのバックアップを取った後、よく使う設定をmfileで作成して、できたMakefileをmakefile_templateにコピーしてください。

 avrdude (書き込み)

avrdudeでヒューズビットも含めてコマンドプロンプトから書き込みたい

ATMega8へ、AVRISPを使って、hoge.hexとヒューズ0xD9E4(内蔵8MHz発振)を書き込む

avrdude.exe -p m8 -c avrisp -U flash:w:hoge.hex:i -U hfuse:w:0xD9:m -U lfuse:w:0xE4:m 
  • WinAVR20050214についていくるやつだと、-uをつけないとヒューズがかけません。
    • avrdude.exe -p m8 -c avrisp -U flash:w:hoge.hex:i -u -U hfuse:w:0xD9:m -U lfuse:w:0xE4:m

詳細はC:\WinAVR\doc\avrdude-*.*.*を参照。 なお、Makefileの AVRDUDE_FLAGS = に記入すれば、PNからのprogramでヒューズビットを書く事も可能な筈。

  • C:\WinAVR\doc\avrdude-*.*.*はWinAVR20040720にはあるけどWinAVR20050214にはないみたいですね。
  • ATmega48等の拡張ヒューズがあるデバイスの場合は -U efuse:w:0xff:m の様に指定
  • ロックをする場合は -U lock:w:0xfc:m の様に指定する
  • EEPROMの初期値は -U eeprom:w:hoge.eep の様に指定する
  • ATmega8/88/16/32/64/128等でbootloaderを使用する場合等 -b 38400 の様にボーレートの変更が出来る。

avrdude-4.4.0 で STK500/AVRISPが認識できない

AVRStudio4.11以降通信プロトコルが変更になっています

avrdude-5.x情報 2006-11-28

  • avrdude-5.2が公開されました 2006-10-09
  • avrdude-5.1が公開されました 2006-01-24
  • avrdude-5.0が公開されました (2005-09-21) 2005-09-23更新
概要
  • サポートプログラマの追加
    • JTAGICE-mkII/stk500v2/avrispv2/DASA/PonyProg Serial等
    • serial bit-bangモードの追加により chanさんのCOMポート制御ISPアダプタも定義を追加すれば使用可能
    • chanさんが定義を追加して確認してくださいました
      • avrdude -c avrsp -P com1 ・・・で使用できます
    • USBasp対応
  • サポートデバイスの追加
    • AT90CAN128,AT90PWM2/3
    • ATmega329x/649x/164/324/644
    • ATtiny25/45/85
ファイル
インストール時の注意点
  • 以前のバージョンはバックアップをお願いします
  • 解凍したファイルの中のWinAVRフォルダをそのままWinAVRフォルダにコピーしてください
  • avrdude.confはavrdude-4.4.0のものとは互換性がありません
    • フォーマットが変更になりましたので古いバージョンに戻す時は注意してください
最近のavrdudeとavrsp (Linux限定?)

ChaN氏のCOMポートライタ(avrsp)とavrdude 5.4をLinuxで使っていますが、ChaN氏のサイトにあるavrdude.conf(5.0用)では動作しません。

   # unknown (avrsp)
   # reset=dtr sck=rts mosi=txd miso=dsr
   
   programmer
     id    = "avrsp";
     desc  = "serial port banging, reset=dtr sck=rts mosi=txd miso=dsr";
     type  = serbb;
     reset = 4;
     sck   = 7;
     mosi  = 3;
     miso  = 6;
   ;

このように書き換える必要があります(ピン番号が変わった?)。また、何度もプログラミングしていると途中でハングアップすることがあり、そのときは

   cat /dev/ttyS0 >/dev/null

のように受信バッファを吸い出すとまた動作します。

ubuntu(debian系linux)でAVR

 インストール

  • 要はrootで3つのパッケージを入れるだけ。"apt-get install" でも良い。
   $ sudo su -
   # apt-get install aptitude
   # aptitude search avr
   # aptitude install avr-libc
   # aptitude install binutils-avr
   # aptitude install gcc-avr
  • avrdudeもインストール
   # aptitude install avrdude

 サンプル実行

  • avr-libc のマニュアル日本語版
    • http://cega.jp/avr-libc-jp/
    • Example Projects -> simple project
    • ちなみにsimple projectからソースをDLしなくてもavr-libcパッケージに含まれているのでこれを作業ディレクトリにコピーして使えばいい
  # dpkg -L avr-libc
  ...
  /usr/share/doc/avr-libc/examples/demo
  /usr/share/doc/avr-libc/examples/demo/Makefile
  /usr/share/doc/avr-libc/examples/demo/demo.c
  /usr/share/doc/avr-libc/examples/demo/iocompat.h.gz
  ...

 Eclipse + AVR Eclipse

apt-get install avrdude
  • Eclipseは現在のUbuntu標準のヴァージョンが3.2なので、3.3/3.4(以上)の物が必要。Java等を使わないならCDTヴァージョンをインストールするのが楽。

http://www.eclipse.org/cdt/downloads.php

  • Ubuntu標準のJavaVMだと、AVR Eclipseインストール時にエラーになるので、Sunのヴァージョンに切り替えておく。
host:~/Desktop$ sudo update-alternatives --config java

`java' を提供する 5 個の alternatives があります。

  選択肢       alternative
-----------------------------------------------
          1    /usr/bin/gij-4.2
          2    /usr/bin/gij-4.3
          3    /usr/lib/jvm/java-gcj/jre/bin/java
*         4    /usr/lib/jvm/java-6-sun/jre/bin/java
 +        5    /usr/lib/jvm/java-6-openjdk/jre/bin/java

この例だと、4を選択

  • Eclipseを立ち上げ、Help -> Software Updates... -> Add site... で、「http://avr-eclipse.sourceforge.net/updatesite/」を入力。すると、AVR Eclipseがインストール出きるようになる。
  • Window -> Preference -> AVR / AVRDude を開いて、自分の持っているAVRプログラマをAdd... しておく。
  • そうすると、File -> New... -> C Project にAVR Cross Target Applicationが出てくるので、AVRなプロジェクトを作れるようになる。
  • 注:ディフォールトのターゲットがDebugになっていて.hexファイルが作られないので、アップロードする前に、Project -> Build Configurations -> Set Active からReleaseを選んでからビルドし、AVRにアップロードする。

Bootloader FAQ

 これは何?

  • ATmega8/88/16/32/64/128等の様に自己プログラミング可能なデバイスに前もってローダプログラムを書き込んでおき、ユーザープログラムを後から通信を利用して書き込むものでローダさえ書き込んでおけばライタ(ハード)は必要ない
  • 最近のデバイスでATtiny2313やATmega48等も自己プログラミングが可能だがブートローダ領域は別に存在せず、アプリ用の領域と兼用になっている。
  • 書き込み用のソフトは専用の物が用意されている場合もあるが、AVR910やSTK500プロトコルを採用してAVRDUDE,UISP等のAVR910/STK500サポートプログラマでそのまま書けるものがある。
  • Atmel のAVR230(DES)/AVR231(AES)の暗号化ローダを商業ベースの製品に採用するとプログラムのアップデート時に更新ファイルをエンドユーザに渡してもソフトをリバースエンジニアリングから保護することが出来る。

 どのようなものがありますか