SSブログ

Cinerariaのブートプロセス [FPGA]

今回はCinerariaで使っているNiosIIブートローダの仕掛けについて。

DE0用NiosIIプラットフォーム、Cinerariaのダウンロードはこちらから
 → https://t.co/8kMHg0u0


・EPCSブートの仕掛け
 Cyclone以降の世代のFPGAではコンフィグレーションROMにEPCS ROMが使えるようになった。EPCS ROMは中身は単なるSPI FlashROMで、コンフグレーション後はepcs_contollerペリフェラルを使うとユーザーロジックからもアクセスすることができる。
 これを使ったのが、SoPC Builderのaltera_avalon_epcs_flash_controllerで、NiosIIでこのペリフェラルをRESETベクタに指定すると、EPCSメモリの余剰領域に格納したプログラムをメモリに展開して起動するというメモリコピアがIPLとして自動的に追加される。
 この機能を使うにあたり、前提としている構成としては次のようになる。
bootloader.png
  • FPGAのコンフィグレーションとしてEPCS ROM(ASモード)を使うこと
  • EPCS ROMにプログラムを格納できるだけの未使用領域があること
  • epcs_controllerペリフェラルがあること(かつリセットベクタであること)
  • NiosIIからコード・データ領域として使える外部メモリがあること

  • 別にプログラムの展開先は内部メモリでも構わないのだけど、内部メモリならコンフィグレーションで初期値を持てるので、こんな面倒なことをする必要はない。基本的には外部にSRAMやSDRAMといった、揮発性の大容量メモリを使うことを想定している。
     で、この機能をつかうと、
    FPGAコンフィグ(ASモード)

    NiosIIブート
    (EPCSペリフェラルのIPLで起動)

    EPCSからメモリにプログラムをコピー

    実行

    というブートシーケンスを取ることができるわけだ。

    ・Cinerariaでの実装
     ただ、ALTERA標準のメモリコピアには少々使いにくい部分があって、まず該当プログラムをEPCSの空き領域に書き込むのにNiosII IDE/EDSを使わないといけない。つまりコンフィグROMデータとしてワンパッケージにできないという問題。
     また、プログラムデータを圧縮する機能がないので、大きなプログラムを格納できないという問題。
     さらに、コンフィグレーションデータの直後にプログラムを繫げるという方式の都合上、sofだけ差し替えるという手が取りづらいという問題。
     ついでに言うと、以前はこのメモリコピアの自動実装の機能がなかったため、自前のブートローダを作って、長らく手を入れながら使っている。
     また当時は大容量ストレージがなかなか気軽に使えなかったり、ファイルシステムの実装が大変だったりで、EPCSメモリからのブートでやりくりしてしたのだけど、最近ではどのボードもSDカードが使えるようになってたり、ファイルシステムもchan氏のFatFsが広く使われるようになったりと、状況が変わっている。
     プログラム上も普通にSDカードにファイルシステムを載せて使うことが多いので、CinerariaではさらにSDカードI/Fがあることを前提にしたブートローダを作成している。
     project→cineraria_LMi→software→elfconv_v0.3以下のフォルダがそれの一式。

     このelfloader2が前提としている構成はこのとおり
    bootloader2.png
     上のシステム構成にSDカードI/Fが追加となっている。ここで使うSPI I/Fはプログラムの都合上、Alteraの純正ペリフェラルではなくカスタム品。
     project→cineraria_LMi→mmcdmaフォルダ以下がそれのVHDL+SoPC Builderペリフェラルデータになっている。

     で、CinerariaではEPCSにここら辺をまとめたファイルシステム+アブソリュートelfファイルローダを組み込んでいるので、
    FPGAコンフィグ(ASモード)

    NiosIIブート
    (EPCSペリフェラルのIPLで起動)

    EPCSからメモリにelfローダーをコピー

    elfファイルローダー実行

    SDカードからboot.elfをメモリに読み込む

    実行

    という流れでSDカード上のelfファイルからのスタンドアロン起動を実現している。

    ・elfloader2の制限
     ここでおやっ?と思った人はスルドイ。このブートシーケンスではメモリにプログラムを2回展開している。
     NiosIIでは原則としてリロケータブルでないアブソリュートのelfファイルを生成するから、同じシステム構成のプログラムは同じメモリエリアを使う。
     ようするに、実行中のelfローダーは読み込んでいるelfファイルのコードで自分自身を上書きされてしまう。このままではまともにプログラムがロードできないので、なんとかしないといけない。

     通常のNiosIIアプリケーションでは(全てのセクションをメモリに置く場合)、先頭から順にExceptionベクタ、割り込み処理コード、コード、実行時初期化領域、ヒープ、と並び、メモリの最後にスタックが取られる。実行時初期化セクションから後ろはプログラムが実行された時に初期化されるので、メモリの初期値は不問。
     そこで、elfloader2ではリンカスクリプトを弄って、メモリの一番後ろ、通常はスタックとして使われる領域にコードを配置するようにしている。
     当然、ロードするelfファイルはこの領域にコードやデータを配置してないことが前提。それにelfloader2が大きすぎては意味がないので、これ自体もv0.3ではコード+データで8kバイト領域で収まるようにしてある。
     SRAMやSDRAMを外部メモリとして使いながら、スタック領域が8kバイトを切るようなアプリケーションはまずないから、実用上の問題はない。


     これで、NiosII IDE/EDS上でビルドしたプログラムをSDカードへコピーするだけで実行できる、というステキ環境ができる。

    この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。