Sim's blog

電子工作はじめてみました

AT90USBボードを使ってみました

2010-10-31 04:52:33 | AVR
かなり昔に買うだけ買って放置していたストロベリーリナックスAT90USBボードを使ってみました。



開発ソフトは以下をインストールしました。
- AVR Studioのページ
- WinAVRのページ
- FLIPのページ

以下のページを参考にしました。ありがとうございます。

ストロベリーリナックスさんのチュートリアル
製品ページ (組み立て済) キットと組み立て済の2種類の製品があります。

ジャンク宿さんの記事
AT90USB162マイコンボード開発メモ【1】
AT90USB162マイコンボード開発メモ【2】
AT90USB162マイコンボード開発メモ【3】
AT90USB162マイコンボード開発メモ【4】
AT90USB再び
SPI通信

すんさんの記事
Atmel USBマウスデモ
Atmel USB CDCデモ

Atmel
AT90USB162のページ
AVR USB Series2 Software Packages USB関連のデモがダウンロードできるページ
STK526ボードのページ デモはSTK526を前提にしている。


先人の偉業が色々あるので特に書くこともないのですが、とりあえず自分がやったことを記録に残しておきます。やったことはUSBシリアルのデモを動かしました。

(1) Atmelのページ(AVR USB Series2 Software Packages)からAVR272 USB CDC Demonstration(AVR272_USB_CDC_Virtual_Com_Port.zip)をダウンロードしました。

(2) AVR272_USB_CDC_Virtual_Com_Port.zipファイルを解凍すると、3つのzipファイルがあります。AT90USB162はシリーズ2(型番の末尾が2)なので、STK526-series2-cdc-2_0_3-doc.zipを適当な場所に解凍します。私はd:\work\avr\stk526-series2-cdc-2_0_3-docに解凍しました。

zipファイルの構造は次のようになっています。

STK526-series2-cdc-2_0_3-doc
demo
STK526-series2-cdc ← at90usbxxx_cdc.inf、cdc_task.cはここにあります。
conf ← config.hはここにあります。
doc
fig
gcc ← STK526-series2-cdc.apsはここにあります。hexファイルはここにできます。
iar
Debug
Exe
doc
html
lib_board
stk_526 ← stk_526.hはここにあります。
lib_mcu
flash
pll
power ← power_drv.hはここにあります。
uart
usb
util
wdt
modules
scheduler
usb
device_chap9

(3) AVR StudioからSTK526-series2-cdc.apsというプロジェクトを開きます。このプロジェクトファイルはdemo\STK526-series2-cdc\gccにあります。

(4) すんさんのページにあるようにCPUの周波数の設定を8MHzから16MHzに変更します。具体的にはdemo\STK526-series2-cdc\confにあるconfig.hの
//! CPU core frequency in kHz
#define FOSC 8000

//! CPU core frequency in kHz
#define FOSC 16000
に書き換えます。

(5) buildします(私はいつもF7を押してます)。すると、エラーが出ています。

../main.c: In function 'main':
../main.c:107: error: expected expression before 'do'
../main.c: In function '__low_level_init':
../main.c:126: error: expected expression before 'do'

main.cを見てみると107行も126行もClear_prescaler();でした。探してみるとClear_prescaler()はpower_drv.hで定義されているマクロです。power_drv.hはlib_mcu\powerにあります。マクロの定義は次のようになっています。
#ifdef  __GNUC__
#define Clear_prescaler() (clock_prescale_set(0))
#else
#define Clear_prescaler() (Set_cpu_prescaler(0))
#endif

今回はWinAVRを使っているので__GNUC__というマクロが定義されています。したがって#ifdefは上の方のclock_prescale_set(0)を使ったマクロを定義しています。clock_prescale_set()ですが、avr/power.hで定義されています。このファイルはWinAVRをインストールしてフォルダの下のinclude\avrにあります。覗いてみると、clock_prescale_set()もマクロ定義になっていて、do~while(0)で囲まれていました。結局マクロを展開すると、(do ~ while(0));のようにdo~whileのまわりに括弧がいる形になってC言語の文法エラーになっていたということみたいです。たぶん元々は関数で定義されていたので括弧でくくっても問題がなかったんでしょうね。
というわけで、以下のように括弧を取り除いてエラーを修正します。
#ifdef  __GNUC__
#define Clear_prescaler() clock_prescale_set(0)
#else
#define Clear_prescaler() (Set_cpu_prescaler(0))
#endif

ちなみに、もうちょっと下にSet_cpu_prescaler(x)のマクロ定義でも(clock_prescale_set(x))となっているので括弧を取り除いてやります。

これで無事build完了です。私の環境(WinAVR-20100110)だと以下のようなサイズになりました。

Program: 5018 bytes (30.6% Full)
(.text + .data + .bootloader)
Data: 172 bytes (33.6% Full)
(.data + .bss + .noinit)
Build succeeded with 0 Warnings...

(6) Flipを使って、hexファイルを書き込みます。STK526-series2-cdc.hexはdemo\STK526-series2-cdcの下にできます(STK526-series2-cdc.apsと同じフォルダ)。Flipの使い方はストロベリーリナックスのチュートリアルに写真入りで解説されています(サンプルプログラムの書き込み)。

書き込みモードにするときは、リセットのジャンパをつける → ブートのジャンパをつける → リセットのジャンパをはずす → ブートのジャンパをはずす、という順番にします。

書き込みに成功して実行を開始すると、新しいデバイス(AT90USBxxx CDC USB to UART MGM)を認識してドライバをインストールします。ドライバはdemo\STK526-series2-cdcの下のat90usbxxx_cdc.infです。

(7) TeraTermで38400bpsに設定して通信した様子です(PB0とGNDをショートしたときのメッセージ)。


このデモ自体の機能は、以下の3つです。
- USB-UARTから受信した文字をUARTへエコーバックする。その際にPD5に接続されたLED3を反転する。
- ???なトリガーでPD5に接続されたLED2が反転する。cdc_task.cではusb_request_break_generationがTRUEのときに反転することになっています。
- STK526のジョイスティックを倒すと方向に応じたメッセージを出力する。実際は5個のボタンになっていて、上 PB5、下 PB7、左 PB4、右 PB6、push PB0に割りあたっています。STK526のHardware User Guideを見ると、このジョイスティックは押すとpull-downされるが、そうでないときはHi-Zであると書かれていて、AVRの内蔵pull-upを有効にしておく必要があるそうです。

STK526のLEDやジョイスティック関連の定義はstk_526.hの中でマクロとして定義されています。stk_526.h自体はlib_board\stk_526にあります。

ボタンに反応したりといったデモの機能自体はcdc_task.cの中のcdc_task()の中に定義されています。main()は初期化した後、scheduler()という関数を呼び出すだけです。conf_scheduler.hでschedulerが呼び出すタスクを定義していて、task2がcdc_taskということのようです。cdc関連のプログラムを開発するには、このデモを改造するのがよさそうな気がします。
一応、AVR USB Series2 software library templateというseries2-usb_software_library_template-2_0_0-doc.zipファイルもダウンロードできるようです。

試しにcdc_task()の中のUARTに出力しているところ
uart_putchar(uart_usb_getchar()); // loop back USB to USART
を、次のように書き換えてみると、USB-UARTにエコーバックするようになりました。
putchar(uart_usb_getchar()); // loop back USB to USART


というわけで、やってみたことは以上です。

schedule()は、taskを順に呼び出しているだけで、タイマー割り込みとかで時分割処理をしているわけではないので、cdc_task()の中ではあまり長い処理はしない方がよさそうです。結構、使い方は面倒そうな気もします。もっと手軽に使えればいいのにとか勝手なことを思いました。

最新の画像もっと見る

9 コメント

コメント日が  古い順  |   新しい順
Unknown (すん)
2010-10-31 12:52:36
Simさん、こんにちは
AT90USB懐かしいです。私も放置が多くなってますw。このAT90USBはライター不要だし、大変便利だと思います。おもしろい使い道がわかったら、公表をお願いします。
返信する
Unknown (ノンノ)
2010-11-01 00:21:38
こんばんは 何度やってもエラーが取れずに悩んでいたんですが、これで進めそうです。
返信する
re:Unknown (Sim)
2010-11-01 00:38:27
こんにちは、すんさん
おかげさまで、なんとかデモは動かすことができました。
しばらくは、すんさんが公開されたDE0のROM化とQuartusの10.0で遊ぼうと思ってます。

返信する
Unknown (Tsuneo)
2010-11-03 01:53:27
どうも、お久しぶりです。

> cdc_task()の中ではあまり長い処理はしない方がよさそうです。

もしや、Gainer miniでのPICの件を思い出されたのでしょうか。
PICに比べれば、AT90USBはまともなUSBエンジン(SIE)です。PICの、最悪 100us のデッドラインでファームウェアがUSBエンジンの面倒をみなけらばならない、という制約はありません。SETUPトランザクション処理のデッドラインは、スペックどおり、50msに緩和されています。これが普通ですね。

この点で、だめだめなUSBエンジンを搭載しているのは、
- Freescale MC9S08JM, MCF51JM
- Microchip PIC18F, 24F, 32MX
- ST Micro STM32F102-3, STR71/73/91
- TI MSP430x5xx/x6xx

まともなUSBエンジンは、
- Atmel AT90USB, SAM7X, SAM3U
- Cypress EZ-USB/FX2
- NXP LPC ARM family
- Renesas uPD78F, H8SX, SH2/3
- SiLabs C8051F32x/34x
- ST Micro STM32F105-7
- TI Stellaris LM3S5x/9x
返信する
re:Unknown (Sim)
2010-11-03 20:29:33
こんにちは、Tsuneoさん
ごぶさたしてます。

わわ、心が読まれてるw
ええ、まさにあのときのことを考えました。実は、cdc_task()に_delay_ms(300)として、300ミリ秒のウェイトを入れるとUSB Deviceを認識しなくなったので、記事のようなことを書きました。
ハードウェア的に問題がないとすると、ソフトウェア的な問題ということなのでしょうか。AtmelのUSBサンプルはタスク1がusb_task()、タスク2がcdc_task()になっていて、ノンプリエンティティブで動作しています。ノンプリエンティティブなので、各タスクは自分から他のタスクに制御を渡さないといけないのですが、cdc_task()で時間がかかりすぎると、usb_task()がたまにしか動かなくなります。
ソースが読みきれていないのですが、以前のPICのときと似たような話なのかなと思いました。

それにしても、色々なCPUについて調べられているんですね。同じTIなのにMSP430とStellarisで、できが違うのがおもしろいですね。ST Microもいいのと悪いのが割れてますね。いつもながら、いい情報をありがとうございます。
返信する
Unknown (Tsuneo)
2010-11-05 13:24:00
> 実は、cdc_task()に_delay_ms(300)として、300ミリ秒のウェイトを入れるとUSB Deviceを認識しなくなったので、

300 msは、ちょっと長すぎでしょうね。50 ms以下まで落とせば良いでしょう。
このAtemlのコードでは、デフォルトエンドポイントでのリクエストの処理もメインのタスクループでやってます。標準デバイスリクエストにはUSBのスペックで決められたタイムアウトが設定されています。これにひっかかって、ホスト側でデバイスがリクエストに反応しないと判断されてしまいます。

50 ms以上タスクループを占拠したいということであれば、スタックに手を入れて、USBの処理を割込みに移行させることになります。

> 以前のPICのときと似たような話なのかなと思いました。

タスクループが占拠されて、ホストーデバイス間でタイミングエラーが起きる点は、確かに同じです。ただ、PIC(と、他のだめだめUSBエンジン)の場合は、はるかに短い時間(最悪100us)でこのエラーが起きてしまいます。
返信する
re:Unknown (Sim)
2010-11-07 05:59:40
こんにちは、Tsuneoさん
解説ありがとうございます。Atmelもどうせなら割り込み版のUSBスタックを公開してくれればいいのに、とか勝手なことを思いましたw

返信する
プログラムについて (AVR初心者)
2010-12-02 12:12:38
お久しぶりです.
先日AT90USB162のCOMPORTの開き方でヒントをいただいた,AVR初心者です.

あの時は,ありがとうございました.
おかげさまで,何とかなりました(^^)

今回は,プログラムに関する助言をいただきたくコメントさせていただきました.
目的は,光源を複数用意し,様々な角度から,物体に光を当て,そのたびにカメラで撮影するというプログラムの作成です.

まず,信号を受け取ると,PORTB3からHighで出力され,しばらく時間をおいて,PORTD0からトリガーを出します.
PORTD0のトリガー出てしばらく時間をおいてPORTB3の出力をLowにします.
この動作を,PORTB3~7まで続けます.

この動作は正確に時間を制御する必要があり,Simさんの割り込みのページを見せていただいたのですが,どうも上手くいきません.

今は,PORTB3~7を正確な時間でシフトさせ,その間に割り込みでトリガーを立てたいと思ってします.
タイマーを使って正確に時間を制御したいんですが,その使い方が上手くいかず,困っています.

AT90USB162を使用し,USARTを使ってパソコンからはじめの信号を送りたいと思っていますが,まずは,スイッチからの入力で,行うつもりです.


長々と申し訳ありませんm(_ _)m
ヒント・助言があれば,よろしくお願いいたします.
返信する
re:プログラムについて (Sim)
2010-12-05 05:13:12
こんにちは、AVR初心者さん
そうですね。割り込み処理のプログラミングは結構難しいです。私だったらこうするみたいなことで言うと、割り込み処理はフラグを立てるだけにして、メイン処理ではフラグが立つのをポーリングもしくはスリープして待ちます。どの程度精度がいるのかにも依存しますが、少なくともクロック数はそろうはずです。
最初は一つのポートだけについて動くサブルーチンを作って、パラメータだけ帰れば他のポートにも対応できるようにするとかです。
あまり役に立つような助言じゃないですが、こんなところでいかがでしょうか?


返信する

コメントを投稿