内蔵ROM(コードフラッシュメモリ)で動くプログラムを外部SDRAMで動かしたいのですが、上手くいきません。。。

こんにちは。お世話になっております。

RX72Nを使っておりまして、現在、CPUの内蔵ROM(コードフラッシュメモリ)でプログラムが動いております。
プログラムを外付けSDRAMで動かしたいのですが、上手くいきません。外部SDRAMに関しては、初期化後、
値をwrite,readして読めています。(0x08000000~0x09FFFFFF、 外部アドレス空間(SDRAM 領域)、SDRAM 32MByte)
初期値ありの変数Dなどに関しては内蔵RAMにセクション設定など設定して展開してあります。

-動作環境--
使用マイコン:RX72N(ROM容量4MByte)
開発環境:e2stdio
リアルタイムOS:NORTi
ビルド・ツール:CC-RX V3

CC-RXコンパイラ仕様書、ネット情報を見て書いてみたのですが、理解ができていません。

以下、SDRAMへの展開で、追加で書いてみた箇所です。

#pragma section C C$DSEC
extern const struct {
unsigned char *rom_s; /* 初期化データセクションのROM上の先頭アドレス */
unsigned char *rom_e; /* 初期化データセクションのROM上の最終アドレス */
unsigned char *ram_s; /* 初期化データセクションのRAM上の先頭アドレス */
} _DTBL[] = {
{ __sectop("D_8"), __secend("D_8"), __sectop("R_8") },
{ __sectop("D"), __secend("D"), __sectop("R") },
{ __sectop("D_2"), __secend("D_2"), __sectop("R_2") },
{ __sectop("D_1"), __secend("D_1"), __sectop("R_1") },
{ __sectop("PRAM"), __secend("PRAM"), __sectop("RPRAM") }  //←ここを追加

};

/*****************************************************************************
* Main Function (Initialize Handler ・・)
*
******************************************************************************/
#pragma section P PRAM  //←ここを追加
int main(void)
{
/* initialize system */
・・・・
/* create application task */
・・・・
/* start task */
・・・・
/* start system */

・・・・

e2stdioのセクション設定も変えてみました。(赤い線の箇所、右図の青選択箇所を追加)

コンパイルすると、以下のエラーが出ています。
E0562330:Relocation size overflow : ".・・\SRC\app\RX72n.obj"-"PRAM"-"00000003"

数日かかっているのですが、どこから手をつけていいのかもあまりわかっていません。

どなたかご教授いただけないでしょうか。

よろしくお願いいたします。

  • hiroroさん、こんにちは。NoMaYです。

    > main関数以降すべてのプログラムをSDRAM(08000500~)で動かすにはどのようにすればいいのでしょうか。。。

    ここは、こうですよ。

    08000500│B_1,R_1,B_2,R_2,B,R,P,C_1,D_1,C_2,D_2,VECT,C,D,W*,L,C$DSEC,C$BSEC│外部SDRAM

    [追記]

    それから、PRAMセクションやRPRAMセクションは無しにして下さい。

  • NoMaYさん こんにちは

    やってみたのですが、上手くいきません。

    RAM関係の初期化の前に止まってしまいます。。。

    お手上げ状態になっています。

  • hiroroさん、こんにちは。NoMaYです。

    > RAM関係の初期化の前に止まってしまいます。。。

    これは具体的には、どのソースのどこで止まるのですか?
    あと、念の為の確認ですが、デバッガのCPUリセットボタンを押した時、resetprg.cのスタートアップルーチンの
    先頭に実行マークが表示されて、ステップ実行するとちゃんとステップ実行されていきますでしょうか?

    今のやり方の考え方は素朴で、

    (1) デバッガでSDRAM制御レジスタの設定を正しく行いプログラムを丸ごとSDRAM領域にデバッガでダウンロードする(リセットベクタは除く)
    (2) リセットベクタは内蔵フラッシュメモリに配置する(というか、0xFFFFFFFC番地以外に配置することは出来ない)
    (3) CPUリセットするとPCがresetprg.cのスタートアップルーチンの先頭に来る(スタートアップルーチンは上記(1)でSDRAM上にダウンロードされている)
    (4) ステップ実行するとSDRAM上にダウンロードされたスタートアップルーチンをステップ実行していく

    (5) ステップ実行していくと、やがてmain()へPCが移る(このmain()も上記(1)でSDRAM上にダウンロードされている)
    (6) そこから、Go実行すると、main()から呼ばれるNORTiの初期化ルーチンやら最初のタスクやら後続のタスクやら、上記(1)でSDRAM上にダウンロードされたものが、どんどんSDRAM上で実行されていく
    (7) 割り込みベクタテーブルも割り込みルーチンも、上記(1)でSDRAM上にダウンロードされたものが、どんどんSDRAM上で実行されていく

    というものなのですけれども。

    すみません、MAPファイルをzipファイルに固めてリプライに添付して頂くなどして、見せて頂けませんか?

    あと、上記(1)で、SDRAM制御レジスタの設定、と書いてしまったのですが、SDRAMが普通に使えるようになる為の全ての設定が必要です。もしかしたら、SDRAM制御レジスタという範疇から少し外れたレジスタの設定も必要かも知れません。

  • NoMaYさん こんにちは

    NORTiのプログラムなので少しことなるのですが、リセット処理といったらいいのでしょうか。
    CPUの初期化(RAMの初期化、CPUのモード設定)の前で止まっており、そもそもステップ実行が

    一回もできない状態です。

    以下のマップファイルはプログラムをROMで動かしているときのマップです。
    map.zip

    おおまかな処理の流れはわかりました。

  • hiroroさん、こんにちは。NoMaYです。

    ステップ実行が1回も出来ないとのことですけれども、その状況が分る画面コピーを見せて頂けないでしょうか?また、無意識に(今までのクセで)つい最初にデバッガのCPUリセットボタンを押してしまったりしていないでしょうか?(押してしまうとSDRAM制御レジスタが初期化されますので、スタートアップルーチンのフェッチも出来なくなります。)

    それで、そのことで思い出したのですけれども、NORTi独自のスタートアップルーチンがある(というかFIT/CGは使っていない)ですけれども、ダウンロード後のPCの値は、そのスタートアップルーチンの先頭でしょうか?CPUリセットしてはいけませんので、プログラム中(リンカが生成したabsファイル中)の、とある情報、を使いデバッガがPCの値をスタートアップルーチンの先頭に移動させるというのを想定していたのですが、その、とある情報、を生成させるようなソースコードなりリンカオプションなりになっているのかどうか気になります。また、正直なところ今更ですが、e2 studioでやったくれていたかな?、とも気になり始めています。(でも、もしそうなら、皆さんどうされていたのかな、とも。)

    ソースの記述の場合: #pragma entry 関数名
    リンカオプションの場合: -entry=_関数名

    それで、MAPファイルですが、SDRAMにダウンロードする場合のものも見せて頂けませんか?それと、先ほど頂いたROMにダウンロードする場合のものを見て気付いたのですが、以下のセクションが含まれていましたけれども、これらはどうなっていますか?今まで頂いた投稿の中で記載されていなかっただけで、実際はセクション設定されていますか?それともリンク時にワーニングになっていたりしませんか?

    B_8 (現状サイズ0)
    R_8
    C_8
    D_8

     


  • プログラムをRAMで動かそうとしたとき、
    例えば、以前のコメントいただいた以下のセクションに変更したとき
    08000500│B_1,R_1,B_2,R_2,B,R,P,C_1,D_1,C_2,D_2,VECT,C,D,W*,L,C$DSEC,C$BSEC│外部SDRAM
    [追記] PRAMセクションやRPRAMセクションは無し

    デバックを開始するとPSWの初期値から処理が始まるのですが、1回ステップ実行すると0xffffffffに設定されます。
    ※上記のMAPのROMで動かす場合は問題なく実行できます。
    画面コピーはNORTiがつくったソースを公開することになるので、やめておこうと思っています。

    map3.zip

    個人的には、ROMにあるPやVECTをSDRAM初期化の後、以下のようにZRAM,ZVECTのようにコピーすればうごのかと思い、e2stdioのセクション、ROMからRAMへのマッピングもDなどと同様に設定してビルドしたのですが、上記と同様に1回ステップ実行すると0xffffffffに設定されます。

    map2.zip

    #pragma section C C$DSEC
    extern const struct {
    unsigned char *rom_s; /* 初期化データセクションのROM上の先頭アドレス */
    unsigned char *rom_e; /* 初期化データセクションのROM上の最終アドレス */
    unsigned char *ram_s; /* 初期化データセクションのRAM上の先頭アドレス */
    } _DTBL[] = {
    { __sectop("D_8"), __secend("D_8"), __sectop("R_8") },
    { __sectop("D"), __secend("D"), __sectop("R") },
    { __sectop("D_2"), __secend("D_2"), __sectop("R_2") },
    { __sectop("D_1"), __secend("D_1"), __sectop("R_1") },
    { __sectop("P"), __secend("P"), __sectop("ZRAM") },
    { __sectop("VECT"), __secend("VECT"), __sectop("ZVECT") }
    };


    ワーニングに関しては、なっていません。
    以下の設定です。
    #pragma section C C$DSEC
    extern const struct {
    unsigned char *rom_s; /* 初期化データセクションのROM上の先頭アドレス */
    unsigned char *rom_e; /* 初期化データセクションのROM上の最終アドレス */
    unsigned char *ram_s; /* 初期化データセクションのRAM上の先頭アドレス */
    } _DTBL[] = {
    { __sectop("D_8"), __secend("D_8"), __sectop("R_8") },
    { __sectop("D"), __secend("D"), __sectop("R") },
    { __sectop("D_2"), __secend("D_2"), __sectop("R_2") },
    { __sectop("D_1"), __secend("D_1"), __sectop("R_1") }
    };

    #pragma section C C$BSEC
    extern const struct {
    unsigned char *b_s; /* 未初期化データセクションの先頭アドレス */
    unsigned char *b_e; /* 未初期化データセクションの最終アドレス */
    } _BTBL[] = {
    { __sectop("B_8"), __secend("B_8") },
    { __sectop("B"), __secend("B") },
    { __sectop("B_2"), __secend("B_2") },
    { __sectop("B_1"), __secend("B_1") }
    };

    #pragma section
    unsigned char * const _CTBL[] = { /* セクションが空の時のワーニング防止用 */
    __sectop("C_1"), __sectop("C_2"), __sectop("C"), __sectop("C_8"),
    __sectop("W_1"), __sectop("W_2"), __sectop("W"),
    __sectop("L"), __sectop("STACK"),
    };

  • hiroroさん、他の皆さん、こんにちは。NoMaYです。

    すみません、他の皆さんに御相談なのですけれども、以下に書いたこと以外にe2 studioの何かノウハウがありますでしょうか?



    画面コピー無しで状況を推測しないといけないとなると、なかなか厄介ですね。それにmap2のケースでは、以前より状況が悪くなっていますね。少なくとも、以前はmain()はSDRAMで動かせていた、ということでしたので。SDRAM上で、プログラムを動かしたいのは以下のことをしたいから、というケースにおいては、プロジェクト全体において、基本、プログラムセクションその他もろもろをリンカのセクション設定でSDRAM上に配置する、ことで発想はあっているとは思うのです。つまり、いちいち全ての個別のソースにおいて#pragam section P PRAMといった記述を追加するとしたら、それはおかしいのでは?、という発想は、もっともであり、あっていると思うのです。

    > ひょっとして、ミスポさん提供のTCP/IPスタックとかUSBスタックとか他もろもろとか、そういうのが丸ごと動いている状態で(それらの機能を使った上で)、ファームウェアアップデートをしたい、ということでしょうか?

    そして、SDRAM上にプログラムをダウンロードするのに、定番である筈の、デバッガの機能でSDRAM関連のレジスタをダウンロード前に初期化しておいてから、デバッガの機能でダウンロードする、という発想も普通にあっていると思うのです。ただ、e2 studioは、この時に、(ちょっとCS+ではやらないような、) 小技が必要だった、という、かふぇルネの過去のスレッドはありました。(カッコ内は私の印象です。)

    また、ダウンロード後に、CPUリセットせずに(そうするとSDRAM関連のレジスタがリセットされてSDRAMからフェッチ出来なくなるから)プログラムを実行させれば、あるいはステップ実行すれば、スタートアップルーチンから実行が行われる、というのも、普通はそういうものだと思うのです。(少なくともHEWやCS+では出来て当然みたいに個人的には思っているのですけれども。)

    今の状況は、ここで、なぜか実行が出来ない、というところで普通とは違う、というのが現在の私の印象なのです。画面コピー無しで、ということで、チェックポイントを書くと以下のようなものが思い浮かびます。

    (1) SDRAM上にホントにちゃんとダウンロード出来ているか --> メモリウィンドウで確認
    (2) PCがスタートアップルーチンの先頭になっているか --> レジスタウィンドウで確認

    この2つが期待どおりであれば、(少なくともHEWやCS+では)あとはどうしたって動くよね、というものの筈だと思うのですけれども、、、(HEWやCS+では、外部メモリ空間にRAMが配置されていることをGUI上にて事前に設定しておくようなことが必要だったような気もしますけれども、これは設定すれば良いことですし、、、)



    自分の印象としては、SDRAM上でプログラムを動かすのに、内蔵フラッシュメモリからSDRAMへプログラム自身でコピーをして実行させる、というのは普通は早い段階ではやらない発想のような気がします。上に書いた定番みたいなことをやっていて、実験目的としては(あるいは自分のクセとしてどうしてもCPUリセットボタンを押してしまうので)何か不便だなあ、ということを考え始めて、そういう手もありそうだ、と気付いてやり始めることのような気がします。

    あとは、定番である筈の出来て当然みたいなことが、どうしてもe2 studioで出来ない、という場合の策として、というので、もう今回はこちらの路線で考えた方が良いのかも知れません。



    もうひとつは、最終的に実現することは、外付けシリアルフラッシュからSDRAMにコピーしてファームウェアアップデートを行うこと、ということですので、先にそちらを実装することでしょうか。そして、もうe2 studioのデバッグ機能は使用せずにprintfデバッグを行う、といったことでしょう。(今でもデバッガを使わずにprintfデバッグのみというひともおられる筈です。)



    あと、リンカのワーニングに関しては、以前に投稿されていた情報と実際の設定が違いますね。(最初の画面コピーをよく見れば気付きそうでは?、というのはありますけれども。)

    以前の投稿:

    08000500│B_1,R_1,B_2,R_2,B,R,RPRAM        │外部SDRAM
    。。。
    FFC00000│P,C_1,D_1,C_2,D_2,VECT,C,D,W*,L,C$DSEC,C$BSEC │内蔵ROM
                 ,PRAM

     
    MAPファイルの内容:

    -start=B_1,R_1,B_2,R_2,B,R,B_8,R_8,P,VECT,C$DSEC,C$BSEC,C_1,C_2,C,C_8,D*,W*,L/08000500,STACK/08800000,STACK_END/08880000,FIXEDVECT/0FFFFFF80

     
    [追記]

    また、どこかの時点でリプライしなければ、とは思っていたのですけれども、外付けシリアルフラッシュからSDRAMにコピーするのであれば、以下のオプション設定は無くて良い、と思います。(所謂、dataセクションもbssセクションもSDRAMに配置する予定のようですので。)

    -rom=D=R,D_1=R_1,D_2=R_2,D_8=R_8

     

  • NoMaYさん こんにちは

    回答ありがとうございます。

    勘違いしていたのですが、map3.zipの状態で、デバッガを接続後、ダウンロードや実行する前に
    SDRAM初期化のコマンドを送っていませんでした。。

    私の理解がおいついていなく、的外れなことをいっているのかもしれません。デバッカ機能を使わないで(E2liteなど使わない)、普通にプログラムを動かすとき、SDRAMでプログラムを動かすにはどのようにすればいいのでしょうか。

    最終的に実現すること:こちらも少し伝え方を間違っていました。
    基板の電源を入れた状態(内臓ROMからSDRAMにプログラムを展開し、SDRAMで動かしている状態から)で外付けシリアルフラッシュを使い内臓ROMのプログラムを更新し、リセットしてプログラムがROMからSDRAMに展開されて更新されることを想定しています。

  • hiroroさん、こんにちは。NoMaYです。

    > 外付けシリアルフラッシュを使い内臓ROMのプログラムを更新

    ひょっとして、外付けシリアルフラッシュメモリは、常に基板上にあるのでは無くて、ファームウェアアップデートする場合のみ、基板上に用意されたコネクタに接続するような、何か小さな別基板に搭載されているのですかね?(別方向へ話がそれるかも知れない危惧はありますが、何かこう、USBメモリに、アップデートするファームウェアを入れておいて、USBメモリが挿入されていたらファームウェアアップデートする、みたいなシステムがありますが、それが、USBメモリでは無くて、シリアルフラッシュが搭載された小さな別基板である、みたいなものでしょうか?)



    と思ったのですけれども、それだと、NORTiのTCP/IPスタック?やUSBスタック?といったものは動いている必要がないですね、、、すみません、まだイメージが掴めないです、、、



    実験目的といったような段階では無くて、デバッガなんかは繋がない最終的な段階においては、こうだと思うのです。(すみません、ひとまず、外付けシリアルフラッシュメモリは、常に基板上にある、とします。それが常に基板上にありますので、その内容を内蔵フラッシュメモリにもコピーする必要性が思い浮かばない、というのが私の頭の中のイメージなのです。なので、RX72Nとしては、(ラインナップに存在しないと思いますが、) 内蔵ROM/RAM=64KB/4KB、みたいなものでも良い筈、というのが私の頭の中のイメージなのです。)

    (1) 内蔵フラッシュのプログラムで、以下の(1')や(1'')の実行に必要なクロック設定とか、最低限のスタック設定とか、BSSクリアとか、DATAコピーとか、行う
    (1') 及び、SDRAM制御レジスタの設定、外付けシリアルフラッシュメモリを読むのに必要な設定(SPIを使うならSPIの設定も含む)、なども行う
    (1'') そして、外付けシリアルフラッシュメモリからプログラムを読み出してSDRAMへコピーする、その後、コピーしたプログラムへジャンプする
    (1''') 他方、外付けシリアルフラッシュメモリへ書く、ということは、この段階では行われないので、後回しにして考慮しなくてよい

    ↑ 内蔵フラッシュに格納される所謂ブートローダと呼ばれるものの処理    ↓アプリケーションの処理

    (2) SDRAMにジャンプしたら、SDRAM上のアプリケーションで、NORTiの初期化に必要な最低限のスタック設定とか、アプリケーションのBSSクリアとか、もろもろ行う
    (2') 今まで頂いていた情報からですと、アプリケーションの、所謂BSSセクションとかDATAセクションとか、それらもSDRAM上に配置される予定かな、と受け取れました
    (2'') なお、NORTiですので、本番のタスクのスタックは、タスク毎にSDRAM上のしかるべき領域に確保されていきます

    (3) NORTiの初期化を行う、NORTiのことを把握出来ていませんが、これ以後自動的にタスクが生成されて自動的にタスクが起動されていく?

    (4) 今までに頂いた情報からですと、アプリケーション側で必要となるメモリは全てSDRAM上のものを使われる、のだと受け取れました
    (4') 巨大なBSS領域も巨大なDATA領域も必要なければRX72Nの内蔵RAMとすることも出来ますが、内蔵RAMも使わない予定、なのだと受け取れました
    (4'') また、アプリケーションは、自分自身で自分自身を丸ごとアップデート(ファームウェアアップーデート)する、ということが可能なセクション設定であるもの
    (4''') そのようにセクション配置したプログラムをCC-RXでコンパイルして、CC-RXのリンカの機能でバイナリファイル(素朴なMOTファイルでもよい)にします

    (5) ファームウェアアップデート時は、NORTiのTCP/IPスタックなりUSBスタックなりで基板外からプログラムを受け取って、外付けシリアルフラッシュメモリに書く
    (5') 基板外から受け取るプログラムというのは、上記(4''')のバイナリファイル(あるいはMOTファイル)のことです
    (5'') 書き終わったら、自分でCPUリセットを掛けて、最初の(1)へ行く

     
    こうなると思うのですけれども。

  • hiroroさん、こんにちは。NoMaYです。

    あと、今になって気になり始めたのですけれども、SDRAM上でプログラムを動かすとなると、かなり性能が低下すると思います。