2012年8月25日土曜日

Linux上でavraを使ってtiny10のアセンブラソースを書く

ATtiny2313をはじめATmega88,ATmega328などのデバイスに対応しているアセンブラ avra を利用しています。ATtiny10もavraのサポート対象に入っているのですが、先のATtiny10のライタを作ったときに添付したLチカプログラムのアセンブラソースをアセンブルしてみると下のようなエラーでアセンブルが途中で中断してしまいます。

> avra -l init.lst init.asm

AVRA: advanced AVR macro assembler Version 1.3.0 Build 1 (8 May 2010)
Copyright (C) 1998-2010. Check out README file for more info

   AVRA is an open source assembler for Atmel AVR microcontroller family
   It can be used as a replacement of 'AVRASM32.EXE' the original assembler
   shipped with AVR Studio. We do not guarantee full compatibility for avra.

   AVRA comes with NO WARRANTY, to the extent permitted by law.
   You may redistribute copies of avra under the terms
   of the GNU General Public License.
   For more information about these matters, see the files named COPYING.

Pass 1...
Pass 2...
init.asm(95) : Error   : PUSH instruction is not supported on ATtiny10
init.asm(96) : Error   : PUSH instruction is not supported on ATtiny10
init.asm(110) : Error   : POP instruction is not supported on ATtiny10
init.asm(111) : Error   : POP instruction is not supported on ATtiny10
done

Used memory blocks:
   Code      :  Start = 0x0000, End = 0x002E, Length = 0x002F

Assembly aborted with 4 errors and 0 warnings.
make: *** [init.hex] エラー 1

エラーの内容は、”ATtiny10では、push/popインストラクションをサポートしてません。”なのですが、そんな訳は無くATtiny10のデータシートのインストラクションセットのページにちゃんと紹介されています。

(ATtiny10 Datasheetより抜粋)

それではということで、AVRAのソースを調べてみる事にします。AVRAを展開したディレクトリ avra-1.3.0/src を見ると、mnemonic.c というファイルがあります。この中にはAVRAで使えるニーモニックが記述されていて、どのデバイスでどのニーモニックが利用可能かが定義されています。 230行目あたりに下のリストに示した記述が見当たります。

231         {"ror",   0x9407,          0},
232         {"asr",   0x9405,          0},
233         {"swap",  0x9402,          0},
234         {"push",  0x920f,  DF_TINY1X},
235         {"pop",   0x900f,  DF_TINY1X},
236         {"tst",   0x2000,          0},
237         {"clr",   0x2400,          0},
238         {"lsl",   0x0c00,          0},
で、この DF_TINY1X が何であるかは src/device.c の中に定義されています。
 47 struct device device_list[] =
 48 {
 49   /*        Name, Flash(words),RAM start, RAM size, EEPROM, flags */
 50   {         NULL,     4194304,      0x60,  8388608,  65536, 0}, // Total instructions: 137
 51   /* ATtiny Series */
 52   // ATtiny4
 53   // ATtiny5
 54   // ATtiny9
 55   {   "ATtiny10",         512,      0x00,        0,      0, DF_NO_MUL|DF_NO_JMP|DF_TINY1X|DF_NO_XREG|DF_NO_YREG|DF_NO_LPM_X|DF_NO_ELP    M|DF_NO_SPM|DF_NO_ESPM|DF_NO_MOVW|DF_NO_BREAK|DF_NO_EICALL|DF_NO_EIJMP},
 56   {   "ATtiny11",         512,      0x00,        0,      0, DF_NO_MUL|DF_NO_JMP|DF_TINY1X|DF_NO_XREG|DF_NO_YREG|DF_NO_LPM_X|DF_NO_ELP    M|DF_NO_SPM|DF_NO_ESPM|DF_NO_MOVW|DF_NO_BREAK|DF_NO_EICALL|DF_NO_EIJMP},
と言うわけでどうやら ATtiny10ではこのコマンドをサポートしない様に指定されているようです。
このままでは ATtiny10で push / pop が使えないので、先の mnemonic.c の中で
234         {"push",  0x920f,          0},
235         {"pop",   0x900f,          0},
236 //      {"push",  0x920f,  DF_TINY1X},
237 //      {"pop",   0x900f,  DF_TINY1X},
として push / pop をこの制限から外してしまいます。 
DF_TINY1X はATtiny10の他にもtiny11/tiny12/tiny15/tiny28/90S1200 でも使われているので、
これらのデバイスを使う際には注意が必要ですが、当面使う予定がないのでこれをコメントアウトして
avra をコンパイルし直します。
問題なく push / pop がコンパイルされるようになります。 

2012年5月18日金曜日

Linuxで使えるATtiny10 programmerを作る



昨年から秋月電子で取扱いの始まったATMELのATtiny10をいじっています。いや、本当は取扱いが始まってあまり時間の経っていない時にデバイスは入手したのですが、デバイスにプログラムを書き込むプログラマが手に入らず、テスト用のLEDチカチカプログラムを書いたものの、それが書き込めない状態がつい最近まで続いていました。WindowsプラスATMEL純正プログラマや、USBaspを使ったプログラマでデバイス書き込みをしている記事をちらほらと見ますが、どちらも望んでいるものからは少し距離がある感じでした。仕事も一段落して時間に余裕ができ、あまり長い間ほったらかしにするのもなんだしなぁ、、などと思ったりもし、”無いものは自分で作るか!”とプログラムを書いてそれなりに動くものが出来たのでそのプログラマを公開します。


1)必要なハードウェア

私の定番の実験基板であるFT232RLとATtiny2313を使ってみました。ライタがホストPCとUSBで繋がっていると電源を用意する必要がなく、シリアルポートの無いPCでも使えると考えると妥当な所ではないでしょうか。他のAVRシリーズのCPU同様tiny10も単一5Vでの書き込みと、resetピンに+12Vを与える高電圧書き込みが用意されています。後者はresetピンにアサインされているPORTB-3を汎用ピンとして使用する設定にした場合、resetピンに+12Vを与えた状態でデバイスにプログラム書き込む必要があります。高電圧書き込み用にレベルシフタも用意しました。


+12V印可のために2SA1015(pnp) 2SC1815(npn)を1本づつ使用して+5Vから+12Vにレベルシフト、これだけだと出力をGNDに落せないのでオープンコレクタ動作の2SC1815(npn)をもう1本追加して、計3本のトランジスタで構成されています。
これらの回路は下の図の様になります。


書き込みのテストでは、これらをブレッドボード上で接続して行いました。写真では分かりませんが青色LEDが1秒間隔で点滅を繰り返しています。


2)コンパイル

2)-1 ホストPC側ドライバ
"tpiwrite" は、Perlスクリプトで特別なモジュールも使用していないため、Perlがインストールされていればコンパイル無しで実行できます。tiny10用のIntel hexファイルを解釈してシリアル経由でプログラマにデータを渡します。全部で55行というコンパクトなプログラム(スクリプト)なので、動作はソースをみていただければ理解できるボリュームのものだと思います。

2)-2 tiny2313ファームウェア
"tpi.c" "usart.c" "waitA.S"のコンパイルに avr-gccが必要です。これらのプログラムは"avr-gcc (GCC) 3.4.6" "avr-gcc (GCC) 4.4.4"でコンパイルを確認しています。今のところ1800バイトぐらいフラッシュを使用していて、200バイトほど空きがあるのでもう少し機能の追加が可能です。

tar/gzipファイルを展開しソースをコンパイルしてください。"make"コマンドを実行するとコンパイル、リンク、hexファイルの生成を行います。適当なプログラマを使って生成されたhexファイルをtiny2313に書き込みます。

tiny10のresetピンを汎用IOピンに変更するには、tpi.cの336行目の"#if 0"を"#if 1"に変更して、tiny2313用のファームをコンパイルしてください。一度Config Byteを書き換えると次の書き込みからは、resetピンに高電圧(+12v)を加える高電圧書き込みでのプログラムの書き込みが必要です。(Config Byteのビット0を"1"にすれば、通常電圧で書き込みができます。)高電圧(+12v)書き込みを行う場合、"Makefile"の14行目行頭を#でコメントアウトして、15行目の#を外してコンパイルして下さい。("HVRST"をdefineする)


3)tiny10用hexファイルの書き込み

tiny2313 と tiny10 を接続して tiny2313 をリセットします。この状態で tiny2313 はホストPCからのデータ待ちになります。Perlスクリプト"tpiwrite"のあるディレクトリでターゲットhexファイル "hoge.hex"を引数にして以下のようにコマンドを実行します。

./tpiwrite hoge.hex

"tpiwrite"の44行目、

select(undef, undef, undef, 0.05);

が、writeデータの送出インターバルを決めています。hexファイルの書き込みに失敗する場合は、この"0.05"を少し大きめの値に設定して送出インターバルをあけてください。現環境で"0.01"での書き込みを確認しています。コマンドを実行すると、1word(2byte)ごとに書き込んだデータを"w12C0" "w2BC0"のように表示していきます。プログラムをすべて書き終えると、ホストPC上に"End of data"と表示されプログラムが終了し、tiny10上で書き込んだプログラムが実行されます。

tiny10用のサンプルプログラムとそのhexファイルを同梱しています。テスト書き込み用にお使いください。


4)それ以外のインフォメーション

制御コマンドや書き込みデータは、バイナリ化されずにそのままホストPCとtiny2313の間を行き来しています。ターミナルソフト(TeraTermなど)を、"38400bps/ストップビット1/8ビットデータ/パリティ無し/ハードフロー制御" に設定して、ホストPCとtiny2313を繋ぐとデータのやりとりを見ることができます。

このプログラムの作成にあたって、ATMELのATtiny 10 DocumantAtmel AVR918: Using the Atmel Tiny Programming Interface (TPI)そのサンプルプログラム 、 個人のWebページSimon Says Game Using an ATtiny10を参考にさせていただきました。

プログラムソース一式は、ここからダウンロードしてください。 このプログラムは、無保証、無サポートです。

++ Myself ++

普通(?)のサラリーマン -- 生活のすきま時間にキーボードとはんだごてを持ち替えてプログラミングと電子工作してます