TestLab:番外編

AVRで遊ぼう

AVRってなあに?

AVRは、Atmel社(http://www.atmel.com/)が、 作成している8bit RISC Flash Microcontrolerです。 プログラム用には1000回の書き込み保証のあるフラッシュメモリが搭載され、 データ用に10万回の書き込み保証のあるEEPROMが内蔵されています。 32本の8ビット汎用レジスタを持ち、 入出力に利用可能なパラレルポートがチップによって 3本から48本の範囲で用意されています。 このポートは5VでLEDを直接点灯できる能力があるものです。 チップによってはA-Dコンバータも用意されていますので、 かなり高度な処理が可能ということが分かって頂けると思います。 また、基本的にプログラムはシリーズ全てで互換性があります [1] ので、 コストやプログラムの規模に見合ったチップを利用することができます。 各チップの機能概要については http://www.atmel.com/atmel/products/prod199.htmを 参照してください。

AVRのためのプログラムライタにはいろいろなものがあります。 代表的なものは以下の通りです。

Figure 1. 秋月電子通商のATMEL AVR マイコンプログラマキット

最近になってFreeBSD portsに、devel/avr*という 開発環境が入りました。 devel/avrprogはライター用のプログラムで、 簡単な回路を作成することで、 パラレルポートからプログラムの書き込みや消去が可能になります。 また、devel/avr-binutilsをつかうことで、 アセンブラのプログラムやIntel HEXフォーマットへの変換が可能です。 devel/avr-gccdevel/avr-libcを 利用することで、 C言語での開発も可能になっています。

今回は、AVRを題材にして、 アセンブラでプログラムを作成することを目標にします。 この時、できるだけお手軽に遊んでみることを目標にしますので、 portsなどあるものは使ってしまいます。

クロス開発環境の製作に興味のある方は、 内川さんの記事の方も是非参照してください。

AVRの情報源

AVRの情報としては、最近出版された教科書[1]が、 まずあげられます。 CPU毎の特徴や命令一覧も含まれていますし、 応用回路もたくさん含まれていますので、是非手元に置いてください。

もう少し前の記事としてはトランジスタ技術の特集[2] があります。 こちらは命令などが一覧できる表でまとまっており、 大体の命令の内容が分かっている場合には便利でしょう。 また、PICも特集に含まれていますので、 両方に興味がある人が概要をつかむにはよいでしょう。

Web上のリソースとしては、 まずはAtmel社(http://www.atmel.com/)のページが 大変参考になります。 PDFなどの形で仕様などを手にいれることができます。 2001年12月末現在の構成では、トップページから[Flash Microcontroller]、 [AVR 8-Bit RISC]でAVR関連の情報のページにたどり着けます。 [DataSheets]で仕様書が、 [Application Notes]にはAVRを用いた応用回路の説明が手に入ります [3]。 応用回路にはかなり面白いものも含まれていますので、 いちど覗いてみてください。 これらのドキュメントのウチ、仕様書などの一部の日本語訳は レディオテクニカ(http://homepage1.nifty.com/radio_tech/)から たどれるリンクで入手可能です。

日本語としてまとまったWebページとしては まろりさんの「AVRに関するページ」 (http://ww2.tiki.ne.jp/~maro/AVR/)が 仕様などの詳細をわかりやすくまとめてあり、良いでしょう。 今回説明しなかった、avr-libcを使ったプログラミングについても まとまっています。 devel/avr-gccに関しては更に、 http://www.enteract.com/~rneswold/avr/chexample.htmlの ドキュメントも一読をお勧めします [4]

FreeBSDに特化した情報は、 avrprogに関しては http://www.bsdhome.com/avrprog/を参照してください。 あとは、各ツールのマニュアルや付属ドキュメントを参照してください。

ライター回路を作ろう

avrprogが仮定している回路は、前述の http://www.bsdhome.com/avrprog/で見ることができます。 また、devel/avrprogをインストールすることで、 /usr/local/share/doc/avrprog/avrprog.pdfにも、 いわゆる「Tony Friebel氏の回路」(Figure 2)がインストールされます。 ZIFソケットを使わなければ、両者とも1000円もあれば作成できますので、 自分で部品を買って来て作成することをお勧めします。

Figure 2. Tony Friebel氏の回路図

Figure 3. 製作したTony Friebel氏の回路

「Tony Friebel氏の回路」で、6ピンの謎のジャンパーがあるのですが、 これはIN-SYSTEM-PROGRAMMER用のものなので、 ライターとしての用途だけには必要ありません。

どちらの回路を作っても、avrprogは対応していますので、 好きな方を作ればいいでしょう。 私は、回路図があると言う理由で「Tony Friebel氏の回路」を作成しました。

両者の回路とも、パラレルポートから電源を取る形になっていますが、 ノートパソコンの一部ではこれが不可能な場合があります。 この場合、外付の電源(5V)を用意してやる必要があります。 手元ではアルカリ乾電池4本(6V)の電源でも動作しました。

ライターソフトウエアavrprog

ライター用のソフトウエアavrprogは、 パラレルポートを利用して、書き込みを行うプログラムです。 プログラムの書き込みに必要な結線はそれほど多くないため、 シンプルにしようと思えばとことんシンプルに作成することも可能です。

avrprogでは、 設定ファイル/usr/local/etc/avrprog.confに 結線などの情報を書くことで、自分で設計した回路での利用も可能です。 デフォルトは前述のページの最もシンプルな回路になっていますが、 Tony Friebelの回路もコマンドラインオプションで指定可能ですし、 デフォルトの変更のために設定ファイルを変更することも可能です。

詳細な情報はman avrprogを参照してください。 コマンドラインオプションをTable 1にまとめておきます。

Table 1. avrprogのコマンドラインオプション

オプション意味備考
-p 1200(AT90S1200)| 2313(AT90S2313)| 2333(AT90S2333)| 4433(AT90S4433)| 4434(AT90S4434)| 8515(AT90S8515)| 8535(AT90S8535)| 103(ATMEGA103) CPUモデル指定指定必須
-cbsd(default)|dt006|alfライターIDavrprog.confを参照
-C設定ファイル名標準とは異なる設定ファイルを指定する 
-e チップの内容を消去プログラム書き込み前には必須
-f i [a] |s [b] |r [c] |a [d] 転送フォーマット 
-F デバイスシグネチャを無視して処理 
-ifilename転送するファイルを指定 
-meeprom|flash書き込むプログラムエリアを指定 
-n 書き込まない(デバッグ用) 
-ofilename結果を出力するファイル指定 
-Pパラレルポートのデバイスファイル名デフォルトの/dev/ppi0以外のポートを指定 
-t ターミナルモードへ詳しいコマンドはhelpやman avrprogを参照
Notes:
a. Intel HEX フォーマット
b. Motorola S-record
c. rawバイナリ(リトルエンジアン)
d. 自動検出(デフォルト)

パラレルポート/dev/ppi0のパーミッションがユーザが 利用可能になっていないと、もちろんavrprogは動作できません。 また、lpdがパラレルを握っていないようにすることも 注意してください。 標準ではパーミッションが

crw-------  1 root  wheel   82,   0   6/22  2000 /dev/ppi0
となっていますので、グループのrw権限をつけてwheelに自分を登録するか、 オーナやグループを変更するか、 sudo経由で実行することになるでしょう。

注意する点は、プログラムを書き込む前に -eを利用して消去を行っておく必要があることです。

まずはアセンブラから

さて、ここでは実際にプログラミングしてみましょう。 アセンブラによるプログラミングにはdevel/avr-binutils だけあれば十分です。 AVR用のアセンブラなどには、avr-というプレフィックスが つきますので、注意してください。

今回のプログラム作成に利用するコマンドをTable 2にまとめました。

Table 2. 今回利用するコマンド

コマンド名機能備考
avr-asアセンブラ命令はAVR Instruction Setを参照
avr-objcopyフォーマット変換Intel HEXフォーマットやMotorola S-recordへの変換
avr-objdumpオブジェクトファイルの情報表示逆アセンブラとして利用可能

今回の回路で利用するチップはAT90S1200Aです。 このチップにはクロック発振器が内蔵されています [5] ので、 電源(3-6V程度) [6] と抵抗、LEDがあればいわゆるKnight2000のような、 LEDを左右に点滅させる回路を構成することが可能です。 回路図をFigure 4に示します。

Figure 4. Knight2000風LED点滅を実現する回路の回路図

Figure 5. Knight2000風LED点滅を実現する回路の回路

プログラムをFigure 6に示します。 これを作成するためのMakefileFigure 7に示します。

Figure 6. LEDを点滅させる回路(Knight2000風):led.s

/* 定数の定義 */
.equ	DDRB,	0x17	/* PortB 入出力指定レジスタ */
.equ	PORTB,	0x18	/* PortB データ用レジスタ */
.equ	LOOP,	100	/* タイマ用空ループ回数:3Vで適当な値 */
	
/* 割り込みベクトルの初期化 */
	rjmp	reset
	reti
	reti
	reti
/* r18: 一時変数 */
/* r19: LEDの点灯方向 右=-1(LSB方向) , 左=1(MSB方向) */
reset:	
	/* PortB を全て出力モードとして設定 */
	ldi	r18,0xff	
	out	DDRB,r18
	ldi	r18,0x01	/* ここ以降r18は出力データとして使う */
	ldi	r19,0x01	/* 左(MSB)方向への移動から開始 */

/*** メインループ ***/	
top_loop:
	out	PORTB,r18
	/* 方向を確認して分岐 */
	tst	r19		
	brmi	left		/* マイナスならばleft:へ */
right:	
	ror	r18		/* キャリーフラグを含めた右rotate */
	rjmp	common
left:
	rol	r18		/* キャリーフラグを含めた左rotate */
	rjmp	common
common:
	rcall	timer
/* 出力が0になったら方向を変える */
	tst	r18
	brne	top_loop	/* ゼロでない限りはtop_loop:へ */
	neg	r19
	rjmp	top_loop

/*** タイマーサブルーチン ***/	
timer:
	ldi	r16,LOOP
loop:
	nop
	nop
	dec	r16
	brne	loop
	ret

Figure 7. led.sを作成するためのMakefile

# Variables
TARGET_CPU=at90s1200
HEX_FORMAT=ihex
TARGET=led.hex

# Common rules
.SUFFIXES: .hex .o .s
all:	$(TARGET)
write::
	avrprog -p 1200 -c alf -e
	avrprog -p 1200 -c alf -i led.hex
.o.hex: $(.IMPSRC)
	avr-objcopy -O $(HEX_FORMAT) $(.IMPSRC) $(.TARGET)
.s.o:	$(.IMPSRC)
	avr-as -mmcu=$(TARGET_CPU) -o $(.TARGET) $(.IMPSRC)
clean:
	rm -f *.o *.hex *~

書き込みは、以下のような手順で行います。

	> avrprog -p 1200 -c alf -e
	avrprog: AVR device initialized and ready to accept instructions

	avrprog: Device signature = 0x1e9001

	avrprog: erasing chip
	avrprog: done.

	avrprog done.  Thank you.
	> avrprog -p 1200 -c alf -i led.hex
	avrprog: AVR device initialized and ready to accept instructions

	avrprog: Device signature = 0x1e9001

	avrprog: reading input file "led.hex"
	avrprog: input file led.hex auto detected as Intel Hex

	avrprog: writing flash:
	  48 0xe1 
	avrprog: 52 bytes of flash written
	avrprog: verifying flash memory against led.hex:
	avrprog: reading on-chip flash data:
  	  48  0xe1
	avrprog: verifying ...
	avrprog: 52 bytes of flash verified

	avrprog done.  Thank you.
      
ちなみに、Figure 7には、 make writeで これらのコマンドを実行するターゲットを登録してあります。

おわりに

今回は基板の作成からアセンブラを使ったプログラミングまでを説明しました。 楽しみのためにアセンブラを使ったのは10数年ぶり [7] なんですが、 結果が目に見えるので非常に楽しかったです。

libcを使ったプログラミングまで書けなかったことが残念です。 いずれ、稿を改めて書きたいと思います。 他にもAVRに関して取り上げて欲しい事などがありましたら、 編集部まで御連絡ください。

今回の記事を書くにあたって、 奈良工業高等専門学校からくり同好会の藤田さんには さまざまな情報を提供頂き、査読していただきました [8]devel/avrprogの制作者でありMAINTAINERのBrian Dean氏と devel/avr-*MAINTAINERのJoerg Wunsch氏には 有用な情報提供を頂きました。 また、Tony Friebel氏は回路のオリジナル作者で、 この回路図はJoerg Wunsch氏によって描かれています。 ここに、感謝させて頂きます。

Special thanks to:

Bibliography

[1] 加藤芳夫, マイクロコンピュータAVR入門, CQ出版, 2001年9月20日.

[2] トランジスタ技術: 特集:PIC & AVR製作パラダイス, CQ出版, 2000年7月.

Notes

[1]

もちろん、存在しない入出力に対する操作は意味を持ちませんし、 それに対応している命令は用意されていませんので、 完全に互換性があるわけではありません。

[2]

ただし、このプログラムを書き込むためには、 先にライタが必要になります。

[3]

[Software]にはWindows用のSoftwareなどもありますが、 必要ないでしょう(^-^;)

[4]

2002年1月8日現在で、avr-libc付属のドキュメントよりも こちらの方が新しいので、こちらを参照しましょう。 インストール部分に誤りがあるそうですが、 portsを使うのならば関係ありません;-)

[5]

Aの付かないAT90S1200もクロックが内蔵されているのですが、 工場出荷時点では外部クロックを利用する設定になっています。 これの変更にはヒューズビットの書き換えが必要なため、 今回は、若干高価ですがAT90S1200Aをターゲットにしています。

[6]

電源電圧で内部クロックの周波数は変わりますので、 クロックを仮定してプログラムを作る場合は、 外部クロックを利用するべきです。

[7]

PC-9801vm21でVRAMを反転させて遊んで以来…

[8]

また、遊びましょう;-)