.bss.sysmmr と .bss.coremmr

先日のやりとりの結果、Mayaさんが遭遇していた「bfin-elf-gccで作ったLDRファイルがBlackfinでロードしない」と言う問題は、Makefileの中の次のコマンドの副作用によるものでした。

$(OBJCOPY) -R .bss.sysmmr -R .bss.coremmr $(OBJFILE)

このコマンドの起源はなかなかに複雑です。

事の発端

もともとの動機は、「gdbでシステム・レジスタデバッグしたい」というものでした。VisualDSP++はフリーで使い続けることができず、かつ、Windowsでしか動作しないため、私の開発環境であるLinuxでは不便です。一方で、bfin-elf-gdbは当然のようにBlackfinのレジスタを解しないため、デバッグが不便でした。
そこで、.bss.sysmmr .bss.coremmrというセクションを、システム・レジスタ、コア・レジスタと同じアドレスに被せ、中身を初期化しない変数をシステム/コア・レジスタとして宣言することでgdbにシステム・レジスタを変数と思い込ませる方法です。
ところが、これは思いがけない問題を呼び起こしました。ELFはセクションの属性としてNOBITSを指示すると、その領域を初期化しないことになっています。レジスタ領域に変な値を書き込むと暴走しますから初期化はしたくありません。その点、gdbはNOBITSセクションを初期化せずに放って置いてくれます。ところが、ubootはこのセクションを0フィルします。ELF的にはおかしいのですが、ubootのコミュニティはかなり強行です*1

そこで、渋々上のコマンドをMakefileに差し込んだのです。MakefileをいじるとTOPPERS/JSPの公式リリースから離れていくので嫌だったのですが、背に腹は代えられません。
ところが、今度は bfin-elf-ldrです。LDFファイルは最後のセクションに"BFLAG_FINISH"というフラグを置くことで、Blackfinのブートローダーに「ロード後、実行せよ」と指示します。ところが、上のコマンドを入れたばっかりにELFの最後のセクションが削除されてしまいました。そのため、bfin-elf-ldrはBFLAG_FINISHを生成せず、ローダーは正常にブートしませんでした。
まったく、踏んだり蹴ったりです。いや、酷い目に遭ったのはMayaさんですが。

さて、どうする

今後の方針ですが、いくつか考えられます。

  1. MMRの表示をすっぱりあきらめる
  2. MMRのシンボルを別ファイルにする
  3. Makefileをかき分ける
  4. MMRに新しいセクションを加える

最後の方法は、先ほど実験して効果を確かめました。要するに .bss.coremmr が最後のセクションであることが原因なわけで、メモリ最上位にダミーの「最後のセクション」を置く方法です。これがちゃんとBFLAG_FINISHをつくってくれるのですが…なんかダメな気がします。結局ubootでこけそうですよね。
そういうわけで、2,3あたりが合理的じゃないかと思います。2の方法は、レジスタアドレス絡みのトリックを全部外に出して独立したアプリケーションとしてビルドし、必要に応じてgdbのadd_fileコマンドでシンボルを追加する方法です。ubootの問題も回避できますし、これが一番よさそうです。

*1:私はこれでubootへの印象をだいぶ悪くした

Unzen基板

新しい基板を設計中です。
この基板はマルチ・アーキテクチャのオーディオ・プラットホーム Uzumeの実装作業用に開発している物です。プロセッサはADSP-BF592で、モーターなどの小規模組み込み用DSPですが、I2Sを持っています。このチップはBGALFCSPなのでとても私の手に負えませんが、MayaさんがこいつをDISPサイズのミニ基板に実装したACB-BF592を使う事で、両面基板での組み立てが可能になっています。オーディオコーデックはポーランド製のコーデック・モジュールMMCODEC01でこれは既にLPCXpresso 1768と組み合わせたTakachihoKirhishimaで実績があります。

TakachihoやKirishima同様、Unzenはオーディオ信号処理の実験専用につくってあり、4つのVR、4つのLED、4つのボタン・スイッチを持っています。ADSP-BF592はADCを持っていないため、I2C ADC AD7995を実装しています。
ほとんどの部品はスルーホール実装ですので組み立ては容易です。ただ、I2C DACだけはパッケージの大きな物が見つかりませんでしたので0.65mmピッチの8pin ADCを使っています。ここが組み立ての最大の難関になるでしょう。他二やら菜といけないことがあるため、設計はしたものの手を付けるのは冬休みになりそうです。
蛇足ながら、Uzumeプラットホームの名前は日本神話のアメノウズメからいただいています。最初の実験基盤となったTakachihoの名前は、アメノウズメが踊った天の岩戸があるとされる高千穂峡からとっています。続くKirishima、Unzenは九州の観光地の名前です。

96bitの割り込みマスクを作るには?

まやさんがBF548へのTOPPERS/JSPの移植で躓いている様子。

BF548のハードウェアリファレンスマニュアルを確認すると、IRQが96種類定義されています。他のプロセッサでは64種以内におさまっていたため、割り込みマスクをunsigned long longで各ビットに割り当てて表現できていたわけですが、int128という定義がないため、配列を使用しないと96bitを表現できません。

私だったら、という前提でお話ししますが、これは単にchg_ims()やget_ims()の定義を変えてしまいます。たとえば

typdef unsigned int[3] MS;
extern ER chg_ims ( MS ims );
extern ER get_ims ( MS ims );

typedefの使い方、これでいいんでしたっけ orz

LDRファイルを作る

Blackfinファミリは外部からチップ内部にプログラムをロードするメカニズムを複数持っています。
たとえば、BF518であれば、SPIフラッシュ、フラッシュ、UART、SPI hostなどからプログラムをロードすることができます。一方で、この仕組みを使うには、特別なフォーマットにプログラムをパックする必要があります。
以前はGNUツールチェーンにLDRファイルを作る機能が無く、VisualDSP++のものを拝借していたりしました。今回、調べたところ、bfin-elf-ldr を使えばLDRファイルを生成できます。
便利ですね。

ビルド出来た

TOPPERS/JSP for BF506ですが、とりあえずsample1のビルドはできました。
BF506は命令メモリが32KBしかありません。そのため、外部Flashにプログラムを置いてその場実行するのですが、その際、SRAM16kBはキャッシュに割り当てることになります。sample1のサイズはだいたい20kBですから、16kBをキャッシュにすると、今度はSRAM上でデバッグできません。結局LDスクリプトを二つ用意することになります。
また、ロード児にキャッシュをオンにする設定が必要になります。
このあたり、こまめなケアをしていかないとアプリケーションの開発が面倒ですね。基本的にROMデバッグかな。