外部RAMから実行するコードのコンパイル


13

PIC18F85J5ベースのミニマリストゲームシステムの設計を検討しています。私の設計の一部は、チップを再プログラミングしたり、プログラムメモリをフラッシュしたりせずに、SDカードからゲームをロードできることです。このチップを選択したのは、外部SRAMからコードを実行できる外部メモリインターフェイスを備えているためです。

基本的な考え方は、内部プログラムメモリにsdカードを参照するためのインターフェイスが含まれ、ユーザーがプログラムを選択すると、sdカードから外部ramに16進ファイルがコピーされ、実行が外部ramスペースにジャンプするというものです。 。

内部プログラムメモリには、グラフィックス、コントローラ入力、およびその他のさまざまなユーティリティ用のさまざまなライブラリもあります。

内部ファームウェアパーツを正常に動作させる方法を知っていると確信しています。問題は、外部RAMから実行するプログラムを作成することです。通常の写真をターゲットにするのと同じようには感じず、内部メモリで使用可能なライブラリ関数を認識している必要がありますが、再コンパイルはせず、それらにリンクするだけです。また、ゼロではなく、32kの内部フラッシュの直後にアドレスの使用を開始する必要があります。これらのタイプの制約を使用してプログラムをコンパイルする良い方法はありますか?

MPLab IDEを使用していますが、MPLab IDE、またはこの種のカスタマイズ方法についてはあまり詳しくありません。


しばらくここで見た中で最高の質問の1つです...アイデアと答えを聞くのを楽しみにしています。
ジョンL

いくつかの興味深い代替アプローチは、electronics.stackexchange.com
questions / 5386 /で

私はそれを見ましたが、彼らは主にフラッシュへの書き込みを推奨しています。私のハードウェア設計は、受け入れられた回答のアプリケーションノートの図6のようになります。
captncraig

回答:


8

次の2つの問題があります。

  1. 外部RAMアドレス範囲のコードを構築します。

    これは実際には非常に簡単です。必要なことは、コードに使用させたいアドレス範囲のみを含むリンカーファイルを作成することだけです。これらの外部アプリ用に特定のプログラムメモリアドレス範囲を予約するだけでなく、一部のRAMスペースも予約する必要があることに注意してください。このRAMスペースは、プログラムメモリアドレスのように、固定され、既知である必要があります。これらの固定および既知のアドレス範囲のみをリンカーファイルで使用できるようにします。基本コードリンカーファイルで使用できないようにすることを忘れないでください。

    基本コードは、新しいアプリを外部メモリにロードした後、その実行方法を知る必要があります。最も簡単な方法は、おそらく最初の外部RAMロケーションから実行を開始することです。これは、コードがその絶対開始アドレスに1つのCODEセクションを必要とすることを意味します。これには、残りのコードの右側のラベルへのGOTOが含まれており、これらはすべて再配置可能です。

  2. 基本コードのライブラリルーチンへのアプリのリンク。

    既存のMicrochipツールでこれを行う簡単な方法はすぐにはありませんが、それほど悪くはありません。

    はるかに大きな問題は、ベースコードの変更への対処方法です。単純な戦略は、ベースコードを構築し、結果のマップファイルに対してプログラムを実行してグローバルアドレスを収集し、グローバルに定義されたすべてのシンボルのEQUステートメントでインポートファイルを書き込むことです。このインポートファイルは、すべてのアプリコードに含まれます。アプリのソースコードには基本的にベースコードエントリポイントへの固定アドレス参照が含まれているため、リンクするものはありません。

    これは簡単に実行できますが、基本コードを変更するとどうなるかを考慮してください。マイナーなバグ修正でさえ、すべてのアドレスが動き回る可能性があり、その場合、既存のすべてのアプリコードは役に立たず、再構築する必要があります。すべてのアプリを更新せずにベースコードの更新を提供する予定がない場合は、これを回避できるかもしれませんが、それは悪い考えだと思います。

    より良い方法は、基本コード内の選択された既知のアドレスに定義されたインターフェース領域を持つことです。アプリコードが呼び出すことができるサブルーチンごとに1つのGOTOがあります。これらのGOTOは固定の既知のアドレスに配置され、外部アプリはそれらの場所のみを呼び出し、その後、サブルーチンがベースコードのビルドで実際に終了した場所にジャンプします。これには、エクスポートされたサブルーチンごとに2プログラムメモリワード、実行時に2サイクル余分にかかりますが、それだけの価値があると思います。

    これを正しく行うには、GOTOの生成プロセスと、外部アプリがサブルーチン(実際にはGOTOリダイレクタ)アドレスを取得するためにインポートする結果のエクスポートファイルを自動化する必要があります。MPASMマクロの巧妙な使用法で対処できるかもしれませんが、これを行う場合は、前処理時に外部ファイルに書き込むことができるため、必ずプリプロセッサを使用します。プリプロセッサマクロを記述して、各リダイレクタを1行のソースコードで定義できるようにすることができます。マクロは、フードの下ですべての厄介なことを行います。これは、GOTO、実際のターゲットルーチンへの外部参照を生成し、そのルーチンの既知の定数アドレスを含む適切な行をすべて適切な名前でエクスポートファイルに追加することです。おそらく、マクロは通常の名前(ランタイム拡張可能配列のような種類)でプリプロセッサ変数の束を作成し、すべてのマクロ呼び出しの後にエクスポートファイルが1回書き込まれます。私のプリプロセッサがMPASMマクロではできない多くのことの1つは、文字列操作を行って他の名前から新しいシンボル名を作成することです。

    私のプリプロセッサとその他の関連するものは、www.embedinc.com / pic / dload.htmから無料で入手できます。


固定ジャンプテーブルのアイデアが本当に好きです。フラッシュメモリの最後から開始するだけで、システムコールごとに場所を固定できます。あなたが説明するプリプロセッサのブードゥーをすべて理解できない場合は、おそらく、すべてのサブルーチンのアドレスを含む手動で管理されたヘッダーファイルで逃げることさえできます。
captncraig

5

オプション1:解釈された言語

これは直接質問に答え(これは素晴らしい質問です、ところで、私はそれに直接対処する答えから学びたいと思っています)が、外部プログラムをロードして外部プログラムを書くことができるプロジェクトを行うときは非常に一般的ですインタプリタ言語。リソースが限られている場合(このプロセッサ上にある場合、PIC32または小さなARMプロセッサを使用することを考えましたか?)、言語を完全な仕様のサブセットに制限するのが一般的です。チェーンのさらに下にあるのは、ドメイン固有の言語であり、いくつかのことだけを行います。

たとえば、eluaプロジェクトは、低リソース(64 kB RAM)の解釈言語の例です。一部の機能を削除すると、これを32kのRAMに圧縮できます(注:8ビットアーキテクチャである現在のプロセッサでは機能しません。外部RAMの使用はおそらくグラフィックスには遅すぎます)。最小限のAPIを提供すれば、新しいユーザーが簡単にゲームをプログラムできる高速で柔軟な言語を提供します。オンライン言語用のドキュメントがたくさんあります。同様の方法で使用できる他の言語(ForthやBasicなど)もありますが、現時点ではLuaが最適な選択肢であると思います。

同様に、独自のドメイン固有言語を作成できます。より本格的なAPIと外部ドキュメントを提供する必要がありますが、ゲームがすべて類似している場合、これはそれほど難しくありません。

いずれにせよ、PIC18はおそらく、カスタムプログラミング/スクリプティングおよびグラフィックスを伴うものに使用するプロセッサではありません。このクラスのプロセッサに精通している方もいるかもしれませんが、ディスプレイドライバーとより多くのメモリを備えた何かを使用する良い機会になることをお勧めします。

オプション2:全体を再プログラムする

ただし、すべてのゲームを自分でCでプログラミングすることを既に計画している場合は、SDカードからゲームロジックのみをロードすることに煩わされないでください。再プログラムするのに32kBのフラッシュしかないので、4 GBのmicroSDカードを簡単に入手できます。(注:大容量のカードは多くの場合SDHCであり、インターフェイスがより困難です)。32 kBのすべての最後のバイトを使用すると仮定すると、必要なゲームロジックを備えたファームウェアの131,072コピーのためにSDカード上に空きができます。

APPノートの多くは次のように、PICのためにブートローダを書き込むためにありますAN851。メモリの特定の領域(おそらくメモリ領域の最上部、これをリンカーで指定します)を占有するようにブートローダーを設計し、完全なファームウェアプロジェクトがこの領域に到達しないように指定する必要があります。このノートでは、これについて詳しく説明します。「PIC18F452のブートセクション」を「リンカで指定したブートセクション」に置き換えるだけで、すべて意味があります。

次に、ブートローダーは、ユーザーがSDカードから実行するプログラムを選択し、全体をコピーできるようにするだけです。UIは、ユーザーが選択モードに入るためにプッシュボタンを押さなければならないことです。通常、ブートローダーはリセット時にこのボタンのステータスを確認するだけで、押されていない場合はゲームを起動します。それが押されている場合、ユーザーがSDカード上のファイルを選択し、プログラムをコピーし、[新しい]ゲームを起動し続けることを許可する必要があります。

これが私の現在の推奨事項です。

オプション3:HEXファイルの一部のみを保存するディープマジック

あなたの想定されるメカニズムとのトラブルは、プロセッサがAPIや関数呼び出しを扱っていないということです、それはを扱う数字命令ポインタがジャンプして、APIの仕様に応じて関数呼び出しを実行するコードがあることを期待することができます先のアドレス- 。プログラムの一部だけをコンパイルしようとすると、リンカはcheck_button_status()またはを呼び出したときに何をすべきかを知りませんtoggle_led()。これらの関数はプロセッサの16進ファイルに存在することを知っているかもしれませんが、どのアドレスにあるかを正確に知る必要があります。

リンカはすでにコードを複数のセクションに分割しています。理論的には、いくつかの呪文-sectionと追加のセクションにこれを分割できます#pragma。私はこれをやったことがないし、どのようにわからない。上記の2つの方法が失敗するまで(または誰かがここに素晴らしい答えを投稿するまで)、私はおそらくこのメカニズムを学習しないので、あなたにそれを教えることはできません。


番号2に対する私の反対は、フラッシュメモリのチップの寿命中の消去サイクルの数が制限されていることです。8ビットミニマリズムを使用するため、より強力なmcuを使用したくありません。
captncraig

@CMP-少なくとも10,000回の消去サイクルがあります。誰かが毎日異なるゲームをプレイする場合、2039年まで続きます。Flashは、ほぼ確実に残りのサーキットよりも長持ちします。アーケードで毎日何十回もプレイされない限り、これについて心配する必要はないと思います。
ケビンフェルメール

1
第二に、8ビットのミニマリズムはクールに見えるかもしれませんが、プログラミングには不向きです。プロセッサの限界に挑戦しているので、頑丈なマイクロコントローラを入手してレトロに見せることは、レトロに見せることを強いられるよりもはるかに簡単です。
ケビンフェルメール

1
どちらも非常に公平な点です。部品点数を少なくしたとしても、pic32のコストや外部コンポーネントはこれとそれほど変わらず、512Kの内部フラッシュがあれば勝ちます。
captncraig

実用的な解決策は、pic32を使用してブートローダーを作成し、SDカードから再フラッシュすることです。ブートローダーとユーザーコードの両方が必要とする関数を再利用するのは困難ですが、12kブートフラッシュに保持する限り、ユーザーコードにチップ全体を提供し、ソースで必要なライブラリを含めることができますレベル。
captncraig
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.