printfでお手軽デバッグ
とりあえずここまででライターとコンパイル環境が整いました。あとは実際に目的のプログラムを開発するだけです。
プログラム開発の通常の流れは「ソース修正」→「コンパイル&書き込み」→「実行&デバッグ」の繰り返しです。
実際の開発ではかなり多くの時間がデバッグに費やされますので、デバッグを効率的に行うことが重要です。
仕事でAVRの開発を行うのであれば、ICEなどを購入することでデバッグ効率を上げることができますが、趣味の世界ではなかなかそうもいきません。
とは言ってもマイコンの中がどのように動作しているのかを知ることが出来なくてはデバッグにはなりません。
そこで登場するのがデバッグプリントです。ベテランプログラマーの中には「ICEなんて無くてもprintfさえ使えれば開発できる」と豪語する人もいるくらいです。
AVRはプログラムを書き込むためのISP端子がI/Oポートに割り当てられていますので、ライターがプログラムを書き込んだ後はISP端子を自由に使用することが出来ます。
このISP端子でソフト的なUARTを実現することで、PCとの通信が可能になりデバッグプリントを行います。
(ISP端子でソフトUARTを実現するアイデア、ソースコードを開発されたのはChanNさんです)
ライター製作のページでISP端子のMISOとMOSIをEZ-USBのRxD0とTxD0に接続していることを思い出してください。これによりEZ-USBのUARTとAVRのソフトUARTが通信を行うことが出来るのです。
EZCONS
「AVRのソフトUART⇔EZ-USBのUART」で通信を行うわけですが、このままではPCの画面にデバッグプリントを表示することは出来ません。
EZ-USBが受け取ったデータをPCに取り込むには2つの方法があります。
汎用性が高い方法として、EZ-USB用の仮想COMドライバを使用して、EZ-USBのUARTをPCのシリアルポート(COMn)に割り当ててしまう方法です。PC用の「シリアル⇔USB」変換装置などはこの方法を使用しています。
この方法はPCから見るとEZ-USBがCOMポートに見えますので、TeraTermなどの汎用のターミナルソフトが使用できて大変便利です。
ところがこの方法は仮想COMドライバを開発する必要があるため、それなりに大変です。さらに今回はEZ-USBにAVRライターとしての仕事もさせていますので、こちらとの整合性も取る必要があります。
という訳で今回はもう一つの方法(結局簡単な方へ流れているだけかも?)である、簡単なターミナルソフト(EZCONS)を使用してEZ-USBとやり取りする方法を採用することにしました。
EZCONSはEZ-USBのUARTが受信したデータをコンソール上に表示して、キーボードから入力されたデータをEZ-USBのUARTに渡します。
EZCONSのファームウエアはAVREZUSBと共通です。AVREZUSBでデバイスにプログラムを書き込んだ後に、EZ-USBのリナムレーション(USBの再接続&ファームダウンロード)無しにEZCONSを起動することが出来ます。
EZCONSはデフォルトで、57600BPSの通信速度、起動時にAVRの強制リセットをかけるようになっています。
オプションで「-19200」のように指定することで通信速度の変更。「-NR」を指定することでリセットをキャンセルできます。
EZCONSは「Ctrl + C」キーを押すと終了します。
EZCONSはC:\WinAVR\binにコピーしておいてください。
EZCONS.EXE(ダウンロード)
EZCONSソース(VCにてコンパイル可能)
ソフトUART & printf
ソフトUARTはChanNさんが開発されたアセンブラのソースをEZ-USB用に修正して、C言語から関数で呼び出せるようにしています。(uart.S---- void xmit(unsigned char)、unsigned char receive() )
使用するデバイスのクロックと通信速度(デフォルトは57.6Kbps)に合わせてBPSの定数、MOSI/MISOのビット位置、PORTB/PINBのアドレスなどを変更します。
printf()関数はprint.cで実装しています。関数名がprintf()のままではgccのビルトイン関数のprintf()と競合するのでfを取ってprint()としてあります。
関数のコードをコンパクトにするために使用できる書式は%x、%c、%sのみで桁数などの指定は出来ません。
print("add=%x\n",&i);
のような使い方をします。
ソフトウエアでUARTを実現している関係上print()を呼び出すときには割り込みが禁止された状態である必要があります。(cli()で禁止、sei()で許可)
MISO端子がI/Oピンの出力として設定されている必要があるため、
sbi(PORTB, 3);
sbi(DDRB, 3);
が必要です。
Hello world.
説明が長くなりましたが"Hello world."と表示するプログラムです。
#include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <avr/sleep.h> #include <inttypes.h> void print(char *fmt, ... ); int main(void){ //MISO is output & set 'H' sbi(PORTB, 3); sbi(DDRB, 3); print("Hello world.\n"); return 0; } |
このソースはWinAVRのインストール確認の時に使用したAVR Butterfly用のテストプログラムと同じものです。
AVR Butterfly、ライター(EZ-USB)、PCを接続した状態で"make run"を実行します。
コンパイル終了後、AVREZUSBが起動されプログラム(main.hex)を書き込み、EZCONSが起動されます。
そして、コンソールに"Hello world."が表示されるはずです。
(EZCONSは「Ctrl + C」キーを押すと終了します)
「コンパイル&書き込み」→「実行&デバッグ」が"make run"一発で出来るので快適に開発できると思います。