XMEGAを使ってみる4


たぬ

たぬ

たぬ!
ねむいさんもついにたぬたぬのOWNERになれた…
良いことあると良いですね〜♥法明院で見たとき以来惚れこみました♥
ちなみにこの子、前回たぬき村行った時にゲッツしたと言っていた物です!





…さて本題、Windows上でGCCにてAVR/XMEGAの開発が手軽にできる"WinAVR"は、
20100110版で開発は終了しており現在はATMEL公式から配布されている
AVR ToolChain
へとひきつがれています。
そして以前から非公式で海外の掲示板で出回っていた有用なProgramMemory
アクセスの為のマクロが今回から正式にとりこまれていたりするのでここいらで
ちょっとまとめてみたいと思います。



そもそものはじまりはXMEGA触り出した去年にさかのぼります。いろいろ
文句垂れながらXMEGAを動かして来たわけですがARMではお茶の子さいさいで
できたはずの"FontX2ファイルのような大容量のデータを配列として埋め込む"
ことができないという点で躓いたことからでした。これAVRの制約というより
AVR-GCCの制約と言った方が正しいのですが、

1.引数が32767以上の配列を確保することができない
2 uint32_tの配列としてバイト数を稼ごうとしてもそもそも合計32767バイト
  以上になる配列を確保することができない
3.64kb以上のメモリ領域のアドレスに通常のポインタを使って容易に
  アクセスができない

と分かる範囲で上げましたが、普通はAVR使いの人はフラッシュメモリ容量64kb
以下のAVRを使いフォント等の大容量のデータはSDカードに置いてそこから
アクセスするという手段が常套となっていて今回私のように横着してCの配列
として大容量のデータをフラッシュに焼きこむようなことを安易に考えると
この問題に引っかかるというわけです。


これ何とかならないかといろいろ検索して調べていると数年前に「PIC 
AVR 工作室」のnekosan氏も同じ問題
当たられていたようでこの制約について非常に深い考察をされていました。
nekosan氏は最終的に制約に引っかからないようにいくつか分割した配列として
アクセスする方式にされたようです。また同日のコメント欄にはnekosan氏と
Chuck氏のやり取りがあり、その中で中にGET_FAR_ADDRESSという単語が
出てきています。これは後述しますが"3."の制約を解消するための非常に
重要なキーワードとなります。


さて、制約はわかったけど実際どうすりゃいいのと言う話になりますが、
私はフォントファイルを直接オブジェクトにして焼きこんでCからは
インデックスだけ引っ張って来たらいいんじゃね?と考え、さらにググってみると
avr-freaksのフォーラムにavr-objcopyで行う方法の
議論がありました…って何年も前だけどこれあっちではFAQレベルなのか…



置き場にあるxmegaのFatFS+TFT-LCD表示のデモにはmakeファイル中に
具体的に美咲フォントをAnkと漢字ともにオブジェクト化しelfに取り込むための
記述をしてあります。

んでこれをCからアクセスするためにはavr-objcopyで吐かれたラベルを
参照すればおkです♥

…と言いたい と こ ろ だ が!

64kByte以上プログラムメモリを持つAVRにおいて、64kByte以上の領域に
いつもの調子でアクセスしようとするとお次は"3."の制約にあたってしまいます。
そもそもavr-gccはアドレスが16bitとして処理されていて、64kb以上の
メモリ領域にアクセスする時は非常に都合が悪いです(int型が16bitなのから
お察しできると思います)。たとえば…

prog_char inaisan[] = "daisuki!";

というプログラムメモリ上のデータを参照する際にこのデータがプログラム
メモリ上の64kByte以上のアドレスの領域にあった場合、

pgm_read_byte_far((uint_farptr_t)inaisan);

ってやっても配列inaisanの頭のデータ'd'は読み出せません。本来のアドレス
から65535さっぴかれたアドレスにある頓珍漢なデータが返ってくるでしょう。
これは本来24bitあるはずの配列のインデックスのアドレスを頭8bit分カット
した16bitで渡してしまうからです(ポインタ変数を介在させてもポインタの
サイズも16bitで、16bit分のアドレスしか表現できないから同じ結果)。
これを解消するのがGET_FAR_ADDRESSというマクロで、uint32_t型の値を返します。

このマクロを通すとpgm_read_byte_far等のELPMを使う関数へ24bitアドレ
として正常に値を渡すことができます。また、このマクロは長らく非公式でしたが
現在ATMELから配布されているAVR Toolchainではpgm_get_far_address
名をかえて公式にとりこまれることとなりました。めでたしめでたし。
…私の説明分かりずらいから各自pgmspace.h見た方が早いと思います…。


↑んで、見た目は去年と全く変わり映えしませんが上記のすべてを反映させて、
 AVR Toolchainでビルドして動かしたXMEGAのデモさん。
 やっぱARMの方が組みやすいなぁ…と思うことひとしきり




つらつらとまとまりきれないまとめを書いてみましたが、WinAVRからAVR Toolchainに
変わってから気づいたことのTipsとか

●unixライクなツール群
 WinAVRにはARMマイコンのビルドにも重宝したutilsフォルダ内のmakeを含む
unixライクなツール群があったのですがATMEL公式から配布されたAVR Toolchain
には存在しません!代わりにavr-gccと同じフォルダに同等の機能のものが一切
合財ぶち込まれていますが、使いやすさを考えるとWinAVRのutilsフォルダだけ
保存しといて旧来のWinAVRよろしくビルド時にはそこからmake呼び出せられるように
すればモアベターだと思います。
私みたいなコマンドラインビルド野郎向けですがー!

20121130追:
 WinAVRはもはや時代遅れです。WinAVRについていたutilsの代用は
 こちらをご覧ください

●EBIのSRAMモード
 24ビットアドレスのアクセスの問題はプログラムメモリの時の問題だけではなく、
 もちろんI/O領域にも波及しやがります。厳密に言うとAVR Toolchainとはあんまし
 関係ないのですが、ATMEL配布のXMEGAのEBIのSRAMアクセスのデモが地味に
 バージョンアップしていて、pgm_get_far_addressよろしく24bitアドレス用の
 マクロが用意されています。
 
 ねむいさんxmega使ってこれ以上やる気ナッシングになってしまいましたから
 あんまし関係ないですが…

●delay.h
 AVR Toolchainに変えたらmakefileで正しくクロック周波数を設定してヒューズも
 間違ってないのに以前と違ってちゃんと動かねぇ!1!とお嘆きの方、utils/delay.hを
 よ〜く見てください。
 HAS_DELAY_CYCLESというdefineを1から0にすると幸せになれるかも…。
 若しくは私みたいmakefile中でavr-gccにHAS_DELAY_CYCLES=0の定義を渡して
 やるとよいです。

or

 この問題、意外と根は深いようですね…

Go to top of page