カテゴリー「AVR」の9件の記事

2007.11.11

■備忘録■tiny26 と tiny261/461/861の違い

GCCを使ってtiny861でタイマ割り込みによる一定間隔でAD変換を行い、UARTでPCに送るところまでテスト完了。

これまで tiny26で組んでいたものを tiny861に移植するにあたって、その違いにより少しハマったところをざっと記しておく。
(従来のアセンブラソース→Cへの違いを除いたプロセッサ仕様上の違い。)

ATtiny261/461/861はATtiny26の機能強化版。ATtiny261/461/861はそれぞれ、メモリ容量が
 ATtiny261: 2KB , 128B , 128B
 ATtiny461: 4KB , 256B , 256B
 ATtiny861: 8KB , 512B , 512B
と違っている他の仕様は同じ。
(左からプログラム領域のFLASH, SRAM , EEPROM)

ちなみにATtiny26 は
 ATtiny26 : 2KB , 128B , 128B

機能上の主な強化点は タイマ関連とADC関連、あと新機能として外部からの供給クロックを分周してシステムクロックとする機能。
このあたりの微妙な違いによってtiny26のソースがそのままでは意図どおり動作してくれなくなる。

■システムクロックを外部供給された物から分周
 外部クロックで動かす場合、クロック分周はI/OレジスタCLKPRのCLKPS0~3で分周無しから最大256分周の範囲で設定できるようになったようだが、その初期値はヒューズビット CKDIV8 によって決まってくる。
 CKDIV8 がプログラム(0)されると起動時はこれが8分周される設定となる。
 つまり、10MHz与えてもシステムクロックは1.25MHzとして動作する。
 非プログラム(1)の場合は分周なしで起動。 即ち10MHz与えたら最初から10MHzで駆動する。

 出荷時設定はヒューズビットCKDIV8 はプログラム(0)となっているようなので、注意が必要。
 最初、こんなのが追加されていることを知らなかったのでうまく通信が出来なくてハマりました。

Robo20071111_1AVR Studioのライタで見た場合は、[Fuses]タブで "Devide clock by 8 internally; [CKDIV8=0]" にチェックが入った状態で出荷されている。

このチェックが入っていると、供給クロックを8分周したものが起動時のシステムクロックとなる。
外せば起動時で分周なし。

分周値は動的に変更可能なので、チェックが入ったままで起動時に分周値を1に変更してやってもいい。

余談となるが、この動的なシステムクロック分周変更をうまく使えば、システムクロック256分周、タイマ0前置分周1024として16ビットタイマのオーバフロー割り込みとすれば、10MHzの外部クロックでも最大1718秒もの長周期のタイマ割り込みが使えることになる。
処理のときはシステムクロックを1/1にしてやればいいので、処理時のプロセッサパワーと待機時の低消費電力を両立できる。

■タイマ0が16ビット化(または8ビットx2)されている。
 機能拡張に伴い、従来とタイマ関連のI/Oレジスタ名等が変更されている。

■ADCで内部基準電圧を使う場合、これまでのソースコードのままだと1.1Vが基準になってしまう。
 ATtiny26の場合内部基準電圧は2.56Vのみだったが、ATtiny861では2.56Vと1.1Vが選択可能となっており、その切り替えは新設されたI/OレジスタADCSRBのREFS2ビットで行われる(デフォルトは1.1V)。
 そのため、内部基準電圧2.56Vの従来通りのソースをそのまま動かす(ADCSRレジスタはADCSRAに変更が必要)と、1.1Vが内部基準電圧として使われることとなり、取得値も当然違ってくる。

およそこんなところか。

必要に応じてデータシートを見比べる必要があります。
HERO'S Downloadで日本語訳されたデータシートで比較するとATtiny26とATtiny261/461/861で1.5倍ほどのボリューム差があります...

| | コメント (0)

2007.11.10

もう1つのオチ

AVR Studioをインストールしなおしてシミュレータのtiny861のI/Oレジスタが直ったのはいいのですが、それでもタイマ0は回ってくれません。

何か設定が悪いのか(といってもデバイス選択以外に設定できそうなことも無いのだけども)と思ってシミュレータのHelpを見ていたら、 Known Issues として、


Notes for ATtiny261/461/861

Timer/Counter 0 and Timer/Counter 1 are not simulated.  ←!!

The ADC noise reduction function is not supported. Setting the ADIF flag will not wake the CPU from sleep mode. The initial dummy conversion after enabling ADC is not simulated.

The Watchdog is not simulated.



..... orz.....

いや、実機でちゃんと動いてるからいいんですけどね。
ここ数日いらぬことで悩んでたな。

| | コメント (0)

直りました

AVR Studioのシミュレータの件、AVR Studioをインストールしなおしたら直りました。

ウチの環境が悪かったようです。
お騒がせしました。

| | コメント (0)

さらに不可解

AVR Studioのシミュレータでのtiny861の続き。

機動モバイル兵器 VAIO-U50 上で動かしてみるとまた状況が違うようだ。

昨日動かしたときはさらにひどくて、主力DELLノートでおかしかったところに加え、タイマ0に関連するところとして、カウンタもおかしかった。

本来、tiny861ではタイマ0に16ビットタイマが使えることから、タイマ0のカウンタは TCNT0H(上位バイト)と TCNT0L(下位バイト)に分かれており、この2つは独立した8ビットカウンタとしても使用できる。

しかし、昨日VAIO-U50で動かしたときには、タイマ0用カウンタとしては、8ビット用カウンタ TCNT0 1本しか存在しなかった。(他にもぱっと見でおかしいところはあったがキリがないので割愛。)

さらにしかし、先ほどその画面のスナップショットを取って注釈入れようとしたら.... VAIO-U50側、正しいじゃん。
昨日言っていた TCCR0AやPCMSK0,PCMSK1のアドレスもデータシート通りだし...
すべてのI/Oレジスタ見たわけじゃないけど、合ってそうな感じ。

Robo20071110_1

ナゼ?

バージョンはどちらも、
AVR Studio Version 4.13 Service Pack 1 Build 557
AVR Simulator 1, 0, 2, 0
WinAVR 20070525


原因が分からず直っても、どういう条件だとおかしくなるか分からないので気持ち悪い。
DELLノートの方は相変わらずダメだし。

もちろん、GCC使わずに Atmel AVR Assembler で新規プロジェクト立てても同様です(GCCは無実)。

| | コメント (3)

2007.11.09

AVR Studioのtiny861の定義

AVR Studioのデバッグ用シミュレータのtiny861のI/Oレジスタ定義って間違ってないっすか?

ここのところ、GCCでtiny861のタイマ割り込みのテストしてるのですが、シミュレータ上でタイマのカウントすら動いてくれません。
まだ実機確認したわけではないのですが、シミュレータのI/Oレジスタのアドレスがどうもデータシートと違うように思います。

たとえば、タイマ0設定関連のTCCR0Aですが、データシートではアドレスが 0x15(0x35) となっているところ、シミュレータでは 0x2A(0x4A)となっています。

シミュレータ上の 0x15(0x35) には ピン変化割り込み関連の PCMSK0とPCMSK1 の2つが張り付いています。
(1つのアドレスに2種類のレジスタが張り付いてること自体もおかしいし。)

データシートではPCMSK0とPCMSK1はそれぞれ、0x23(0x43) , 0x22(0x42) となっています。

実際、GCC上で、

 TCCR0A=0b10000000;

としてコンパイルし、シミュレータでステップ実行すると、TCCR0Aは変化せず、

 PCMSK0=0b10000000
 PCMSK1=0b10000000

と変化します...
コンパイラは TCCR0Aは0x15(0x35)としたマシンコード吐いてるのに、シミュレータが 0x15(0x35)はPCMSK0とPCMSK1だとして処理している結果ですね。


う~ん、この辺、ネット上には転がってなさそうでしたがどなたか情報お持ちじゃないですか?

| | コメント (1)

2007.11.05

ソフトUARTとMMC関数移植完了

やっとAVR GCC用にソフトUARTとMMC関数移植完了しました。

MMCは難航しました。
tiny26でテストしていたのですが、UARTでデバッグ情報を出力してたら、その文字列リテラルでなけなしのRAM(128バイト)が食いつぶされてたり、ループカウンタが最適化の煽りでうまく回ってなかったりで、どうも本質的なことでつまるというより、環境によるものが多かったです。

教訓としては、
・デバッグ用なんかの文字列はめんどくさくてもFLASHのプログラム領域に置くようにする。
・最適化は最初は外してテストすること。容量が許すのであれば最適化は不要。

なんとなくコツも分かってきましたし、とりあえずこれでCでizCOREのメイン部分が組めそうです。

ソフトUARTとMMC周りのコンパイル後のサイズですが、最適化なしで1200バイトくらい食いました。
最適化最大で800バイトくらい。

ちなみにオールアセンブラだと2年前のおよそ同様の実装で600バイト強くらいでした。

こんな感じなのでtiny26はプログラム領域が2Kバイトしかなく、この先苦しそうなので、tiny861買いました。

| | コメント (0)

2007.10.28

アセンブラ関数でソフトUART

昨日書いた通り、WinAVR(AVR用GNU Cコンパイラ)やってます。

実はWinAVRには標準でUART関数がありません。多分。

ハードウェアUARTを持っているAVRであればI/Oレジスタ叩くだけでいいのでCでも簡単に実装できそうですが、私が主に使っているTiny系ではハードウェアUARTは無い物がほとんどです。
(AT90S2313やATTiny2313にはハードウェアUARTがありますが、izCORE2.0メインプロセッサとして必須要件として考えているADコンバータがありませんし、UARTも複数系統使いたいですし。)

仕方ないので汎用I/Oポートをソフトウェア制御してシリアル通信をしてやる必要があります。
これまでは主にアセンブラでやっていたので、Atmelが公開しているアプリケーションノート(AVR305: Half Duplex Compact Software UART)を参考にソフトウェアUARTを実装していましたが、高速になればなるほど(115.2kbpsとか)、通信パルス幅が10MHzの1クロック分程度の誤差で通信できなくなってしまいます。

アセンブラであれば、実行命令時間を正確に計算することが出来るので調整がきくのですが、Cだとコンパイラ任せなのでそうもいきません。

数命令程度ならまだしも、全部をインラインアセンブラでやるのはかなり大変そうだと思いましたが、調べてみるとWinAVRにはアセンブラ関数という機能があるようで、アセンブラソースを別に書いといて、それを関数として使用することが出来るようでした。

試してみると、マクロ命令系を除いて、これまで使用していたソースコードをほとんど変えることなく使用することができました。

これでフツーにCの関数としてUART通信を実行出来るようになりました。

確認したところではATTiny26 10MHz駆動時、クロック単位の微調整は要りますが、PCのUSBシリアル変換に対して230.4kbpsまではいけました。
460.8kbpsは駄目でしたが、PC側の規格速度に拘らず、10MHzのAVR同士でこのソフトUART同士なら600kbps~2Mbps位でもいけると思います。

このソフトUARTで出来るのは1バイト送受信ですが、こいつがCの関数と同様に扱えるので、C上で文字列送受信の関数もついでに実装してみました。

なるほど。これはかなり快適です。
アセンブラだとこういうのは苦手だから。

あとはMMCアクセス関連とADC関連を移植すれば要素部品は完了。

でも、やっぱりこうなるとこの構想ではメインプロセッサはATTiny26でしたが、RAM128バイト程度では明らかにメモリが足りなさそうです。

アセンブラだとなんとかやりくりできるかなって感じだったのですが、コンパイラ任せだとスタックや変数領域にどれだけ使うか分からないので、やはりATTiny861(RAM512バイト)かな。
前はどこにも売ってなかった(見つからなかった)けど、最近はこちらで入手可能なようだし。

Mega系を使わない理由は、単に物理的に大きいからです。
DIP品でないと手配線できないし。

ああ、DIPタイプ20ピン以下のMegaがあればいいのに...
(ラインナップ的にそれはTinyだろ!ってのはナシのことで。)

WinAVR(AVR-GCC)におけるアセンブラ関数の作り方は、以下ページを参考にしました。

AVR Wikiavrgccでアセンブラを使う
ChaNさんアセンブラ関数の書き方(avr-gcc)

感謝。

| | コメント (0)

2007.10.27

AVR再入門

ここ1年ほどはマイコンプログラムから遠ざかってていろいろ忘れているため、izCORE2.0を作成するにあたって、AVRをもう一度勉強しなおします。

これまでのizCOREはほとんどアセンブラ+一部BASIC(MCS社のBASCOM試用版)でやっていたのですが、今度はCも使ってみたいと思います。

AVRでCを使う場合、商用のコンパイラもありますが、GNU の AVR用のGCCもありますのでそれが使えます。

AVR版のGCCはWinAVRという名称でこちらから入手できます。

これをインストールすると、Atmelの統合開発環境AVR Studio4と連携することができ、面倒なmakeファイル作りなんかも自動でやってくれるので便利です。

で、早速試してみました。

Tiny26(10MHz駆動)のPA7にLEDをつないで点滅させるだけ。
プログラムはこんなの。
Robo20071027_2_3 →テキスト版のソース(S-JIS)


...うーん点滅しません。
いや、目がついていかないほど高速に点滅してるのか?
ウェイトはいい加減だけどチカチカが見えるほどには入れてるはずなんだけど...

いろいろ試してたら分かりました。
コンパイラオプションの最適化切ったら点滅しました。

WinAVRの最適化オプションは5段階(O0,O1,O2,O3,OS)あり、O0が最適化無し。OSが最大のようで、デフォルトではOSです。
実際コンパイラが出力するlssファイル(C→マシンコードの展開図みたいなの)を見てみると、
最適化しない場合(O0)はwait関数のfor文のループがすべて展開されているのに対して、O1以上では、forの痕跡すらなく、いきなりret となっています。
さらに O3以上だとメインルーチンからコールすらしていません。

早い話、オプティマイザが、「空ループは意味がない」とみなしてwait関数のforは展開せず、さらにはO3以上では「wait関数は呼ぶ必要がない」と判断したようです。

また、O0(最適化無し)の場合でも、forループが展開された部分は、想像以上に大量のマシンコードを吐いているため思ったより処理時間食ってるようで、どのくらいのループでどれくらいの時間がかかるのかが予想がしにくいです。

WinAVRの標準のライブラリには汎用IOを使ったソフトウェアUART関数がないため、自前で実装(orどっかから調達)する必要があるのですが、高速通信なんかで精密なタイミングが必要なときには注意が必要そうです。

これまではアセンブラでクロック単位で計算してウェイトかけたりしてたのですが、Cでやる場合にも正確なタイミングが欲しいときにはアセンブラでサブルーチン書いといてそれを呼ぶといったことが必要そうです。(といっても関数呼び出しのオーバヘッドがどのくらいあるのか分からない...)

タイマ割り込み使う場合でも、割り込みのジャンプのオーバヘッドがどのくらいか、コンパイルして吐き出したマシンコード見てみないと分からないかな。
多分レジスタ退避とかやってるだろうし、どれだけのレジスタを使ってるかも最適化オプションによって変わるだろうからコンパイラ通さないと分からないし。

高度な演算や複雑なロジックをまわす場合、高級言語を使うメリットは大きいのですが、シビアなタイミング制御等には弱そうです。

この辺、Cでやってるみなさんはどうしてるんでしょう?


上のソースをコンパイルしたときに出力されたlssファイルです。
最適化 O0の時 OSの時
(どちらもSJISです。文字化けするようならブラウザの設定を変えてください。)

| | コメント (2)

2007.04.16

■備忘録■AT90S2313をAVRISPmkIIで使えるようにする

AVRISPmkII非対応の旧デバイスAT90S2313をAVRISPmkIIで使えるようにします。

C:\Program Files\Atmel\AVR Tools\Partdescriptionfiles
(AVRStudio4のインストール先がデフォルトのままの場合)
にある AT90S2313.xml を開きます。
このファイルの最後の方、
------------------------
      :
    </STK500_2>
  </ICE_SETTINGS>
</AVRPART>
------------------------
となっているところを
------------------------
      :
    </STK500_2>
    <AVRISPmkII/>
  </ICE_SETTINGS>
</AVRPART>
------------------------
とします。 ("<AVRISPmkII/>"を追加。)Robo20070416_2拡大

Robo20070416_3これでめでたく AVRStudio4 - AVRISPmkII -AT90S2313の組み合わせで使用できます。

読み・書きとも問題なく動くことを確認しました。

ただしAT90S2313の場合、ヒューズビットやロックビット変更はパラレルライタが必要で、ISPは使えませんので注意。
(AT90S2313の場合はあまり使わないと思いますが、AT90S1200等を同様にして対応させてもクロック元の内部/外部切り替えの設定変更は出来ないと思います。)


■背景■
これまではizCOREに使用しているAVRマイコンの書き込みには、パラレルポート直結の自作プログラマ(ライタ)を使用していましたが、現在のメインPC(DELLノート)にはパラレルポートがありません。

残念ながらこの手のレガシーポートを直駆動するタイプのアプリケーションはUSBからの変換などでは動かないことが多く、仕方なく旧デスクトップが巨大なマイコン書き込み機として残っていました。

Robo20070416_1USBでも利用できるプログラマとして、自作事例やキット等もあるのですが、この際なのでATMELの純正プログラマ AVRISPmkIIを購入してみました。

しかし、残念なことにAVRISPmkIIでは現行izCOREで使用しているAT90S2313のような旧デバイス(名前にTinyとかMegaとかついてないやつ)はサポート対象外です。

このこと自体は購入前から分かっていたことなのですが、この『サポート対象外』は「サポートしないけど繋げば動くんじゃないかなぁ」くらいに楽観的に考えて購入しました。

で、試しに繋いでAVRStudio4からAVRISPmkIIでAT90S2313に書き込もうとしてみましたが、ホントに動きません...○| ̄|_

いや、今後AT90S2313使わなければいいのですが、現izCORE等、まだまだウチでは現役です。
(秋月で安かったのでスペアにいっぱい買っちゃいました。)

このままでは旧デスクトップも相変わらず書き込み機として現役続投させる必要があります。 困りましたね。
ってことで調べてみました。

ネタ元は2chのAVRマイコン総合スレです。

| | コメント (0)