スマートコンフィグレータ使用時のブート領域、フラッシュ領域の分割方法について

お世話になります。

アプリケーションノート:R20UT4547JJ0100『RXファミリ用C/C++コンパイラパッケージ(CC-RX)ブート領域、フラッシュ領域の分割方法』を参考に、ブート領域とフラッシュ領域を分割したプロジェクト作成をおこなっています。使用環境は以下になります。

【使用環境】

  • RX65N(R5F565NEDDFC:ROM容量2MByte)
  • 開発環境:CS+(V8.03.00),スマートコンフィグレータ(2.3.0)
  • ビルド・ツール:CC-RX(V3.02.00)
  • デバッグ・ツール:RX E1(JTAG)

アプリケーションノートの手順で、新規作成したプロジェクトのブート領域/フラッシュ領域の分割とダウンロードはできました。

ですが、分割予定のプロジェクトはスマートコンフィグレータを搭載しており、ルネサスボードサポートパッケージFITモジュール(r_bsp)ファイルが生成される影響で、プロジェクト作成時に自動生成されるファイルの一部(intprg.c, stack.h, vect.h)がプロジェクトから外されてしまいます。

そのため、アプリケーションノートの

  • 2.1.2:(2)自動生成ファイルの削除
  • 4.1.1:スタックサイズ定義のインクルードと、スタックポインタの設定をコメントアウト
  • 4.1.1:各制御レジスタの設定をコメントアウト

等の方法が分からず、ブート領域の.fsyファイルがスマートコンフィグレータ未使用時と異なる内容が書かれてしまいます。

スマートコンフィグレータ使用時のブート領域、フラッシュ領域の分割方法についてご教授お願いいたします。

 

---.fsyファイル(左:スマートコンフィグレータ未使用時、右:スマートコンフィグレータ使用時)---

                                     

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

    最初に少し気になることがあるのですが、確かに分割するアプリケーションノートはありますけれども、以前に他の人にもリプライしたことがあるのですけれども、もう少し簡単なやり方になっている、ブートローダというカテゴリに関するアプリケーションノートもありますよ。

    Google検索: Renesas RX ブートローダ
    https://www.google.com/search?q=Renesas+RX+ブートローダ

    [関連スレッド]

    可変ベクタテーブルの割り込み
    japan.renesasrulz.com/cafe_rene/f/forum5/7347/thread/39230#39230
     

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

    システムブートローダのご紹介ありがとうございます。こちら、認識はしているのですがサンプルを見つけることができず…

    また、このアプリケーションノードの方法は、一つのプロジェクトにシステムブートローダーの領域とアプリケーション用の領域をセクションで設定し、実行しているのでしょうか?

    [追記]

    現状のプログラムとしたしまして、ブート領域用のプロジェクトとフラッシュ領域用のプロジェクトがそれぞれ存在します。この2つのプロジェクトを1つのマイコンに書き込み、動かすことが望ましいです。

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

    分割するアプリケーションノートの方は、もともとRL78の同様のアプリケーションノートをRXへも展開しようとしたものですけれども、割り込みベクタ領域が固定となっているRL78とは異なり、RXでは割り込みベクタ領域をCPUレジスタで変更可能となっていますので、もう少し簡単なやり方が(以前から)可能であったということです。

    ブートローダのアプリケーションノートでは以下の点がポイントかな、と思うのです。

    (1) RXでは割り込みベクタ領域をCPUレジスタで変更可能

    (1-A) つまり、ブートローダ実行中はブートローダ内の割り込みベクタテーブルを指すようにしておけば良い(というか普通に作るとそうなる)
    (1-B) そして、アプリケーションへ移行後はアプリケーション内の割り込みベクタテーブルを指すようにしておけば良い(というか普通に作るとそうなる)

    (2) 大抵の内蔵周辺は初期化を2回実行しても問題無い(CPUレジスタも)

    (2-A) つまり、1回目の内蔵周辺初期化はブートローダの動作の為にブートローダの起動時に行われる(PSWやSPや割り込みベクタアドレスレジスタなども)
    (2-B) そして、2回目の内蔵周辺初期化はアプリケーションの動作の為にアプリケーションへ移行後に行われる(PSWやSPや割り込みベクタアドレスレジスタなども)

    (3) ブートローダ→アプリケーション、という一方通行なのでRAMのセクション配置は、双方で自由に決めてよい

    (4) ROMのセクション配置は、当然ながら、ブートローダとアプリケーションの領域が双方で重なってはいけない

    (5) ブートローダ→アプリケーション、という遷移が出来るようにアプリケーションの方のエントリポイントアドレスだけは固定番地としなければならない
    (5') あるいは、エントリポイントアドレス値が格納された領域のアドレスを固定番地にする

    (6) 上記により(特に(1)と(2)により)、ブートローダとアプリケーションは別個のプロジェクトとしてそれぞれ普通に作ってしまえば良い(ただし(4)と(5)に注意して)

    [関連スレッド]

    ちなみに、RL78でも、以下のスレッドでの小技を使うと、もう少し簡単に、このようなアプリケーションを作成することが出来ます。

    フラッシュ書き換えについて
    japan.renesasrulz.com/cafe_rene/f/forum21/5700/thread/31700#31700


    [追記その2]

    (1) アプリケーションのビルド方法

    (2) ブートローダのビルド方法

     
    また、ブートローダ→アプリケーション、という遷移は以下の記法で出来ます。

    任意のフラッシュアドレスへのCALL
    japan.renesasrulz.com/cafe_rene/f/forum18/7758/call/40615#40615

        ((void (*)(void)) 0x001234)();

     

  • NoMaYさん。ご説明ありがとうございます。

    ROMのセクション配置が被らないようにし、ブートローダーとアプリケーションプログラムを別々のプロジェクトで作成するという認識でいます。

    なので、以下の流れになるのかと考えています。

    1. 2つのプロジェクト(ブートローダー/アプリケーション)を別々のプロジェクトをで成する。※1ブートローダー側には任意のフラッシュアドレスへのCALLを設ける。※2ROMのセクションが被らないように注意する
    2. デバッグ・ツール>ダウンロード・ファイル設定>ダウンロードするファイルからもう片方のプロジェクトをダウロードする。

    ROMのセクション配置(ビルド・ツールのセクション設定)で、例外ベクタテーブル(EXCEPTVECT)は変更できるのですが、リセット(RESETVECT)が変更できません。

    変更自体はできるのですが、固定アドレスのために変更するとデバッグ開始直後(リセット)に実行アドレスが吹っ飛びます。こちらの変更方、もしくは上記の流れにミスありますでしょうか…

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

    画面コピーはアプリケーションの方のセクション配置ですかね?アプリケーションの方のRESETVECTセクションは(EXCEPTVECTセクションも)、ブートローダ側のそれとは重ならない領域に配置するようにします。リニアモードでくだんの使い方をするのであれば、以下のような場所に配置することになると思います。

    BANK1(アプリケーション): どこでも良いけれど少なくともBANK1内にRESETVECTセクションとEXCEPTVECTセクションを配置
    BANK0(ブートローダ): ROMの末尾のBANK0内のCPU仕様で決められた場所にRESETVECTセクションを配置、EXCEPTVECTセクションはBANK0内のどこかに配置

    こうしておいて、ここでは、先ほどの(5')の考えを使うことにします。

    ・ CPU割り込み発生時はBANK0のRESETVECTセクションのリセットベクタの先へ飛ぶ(CPUが行う)
    ・ ブートローダ→アプリケーションではBANK1のRESETVECTセクションのリセットベクタを関数ポインタ参照して遷移する(自前で行う)

    ・ 割り込みベクタテーブルは、それぞれの初期化ルーチン内で設定されたものをそのまま素朴に使っていれば良い

    ・ (割り込みでは無くて未定義命令例外などの)例外処理に関しては、以下の何れか、もしくは、混合して、使う

    (A) 全てブートローダ側の例外処理関数を使う

    (B) ブートローダ側で一旦受けて、リセットベクタの場合と同様なやり方で、アプリケーション側の例外処理関数を使う

    ごめんなさい、今思えば、例外処理に関することが漏れていて、以下の文は内容が不足していました、、、

    > (5) ブートローダ→アプリケーション、という遷移が出来るようにアプリケーションの方のエントリポイントアドレスだけは固定番地としなければならない
    > (5') あるいは、エントリポイントアドレス値が格納された領域のアドレスを固定番地にする

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

    あっ、もしかして、CS+の方で変更出来ないようになっていますか?

    > ROMのセクション配置(ビルド・ツールのセクション設定)で、例外ベクタテーブル(EXCEPTVECT)は変更できるのですが、リセット(RESETVECT)が変更できません。

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

    画面コピーはアプリケーションの方のセクション配置ですかね?

    >アプリケーションのセクション配置になります。アプリケーション単体で、RESETVECTのセクションをずらした状態で実行できるか確認しています。

    あっ、もしかして、CS+の方で変更出来ないようになっていますか?

    >CS+側でRESETVECTの変更とビルドもできるのですが、デバック開始時にmain関数が起動しません…。(RESETVECTセクションの設定アドレスを変更するとメイン関数が起動しない→https://ja-support.renesas.com/knowledgeBase/19341095)

     

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

    いやいやいや、“アプリケーション単体で”の場合にて動作確認する場合には、ずらしては駄目ですよ。そういうデバッグをしたい場合には、ブートローダという程おおげさなものではなくて、少なくとも以下程度の処理をするプログラムをブートローダ代わりに同時にダウンロードするなどしてはどうかな、と思いました。

    > >アプリケーションのセクション配置になります。アプリケーション単体で、RESETVECTのセクションをずらした状態で実行できるか確認しています。

    ブートローダ代わりのプログラム

    void PowerON_Reset_PC_TmpEntry(void) [追記] むしろ以下の方が分かり易いかも?
    void PowerON_Reset_PC(void) [追記2] これらよりも以下の方が分かり易いかも?
    void main(void)
    {
        アプリケーション側のエントリポイントへ遷移する
    }

     

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

    別案として今しがた思い浮かんだのですけれども、同等のリセットベクタテーブルをBANK1とBANK2の2箇所用意する手もあります。RXスマートコンフィグレータのRESETVECTセクションは以下のテーブルになっているのですが、同じようなテーブルをもうひとつRESETVECT2セクションとして自前のソースに定義するようにして、CPUリセット時にはそちらが使われるようにする、というものです。(なお、CS+上でブートローダとアプリケーションの両方をダウンロードした場合、後からダウンロードした方のリセットベクタが上書きをしますので、その点は注意して下さい。)


    RXスマートコンフィグレータの通常のRESETVECTセクション → 今回はBANK1に配置/ブートローダからの遷移時に使われる

    src/smc_gen/r_bsp/mcu/rx65n/vecttbl.c

    #include "platform.h"
    途中省略
    #if defined(__CCRX__) || defined(__GNUC__)
    R_BSP_ATTRIB_SECTION_CHANGE_RESETVECT void (* const Reset_Vector[])(void) =
    {
        R_BSP_POWER_ON_RESET_FUNCTION                   /* 0xfffffffc  RESET */
    };
    R_BSP_ATTRIB_SECTION_CHANGE_END
    #endif /* defined(__CCRX__), defined(__GNUC__) */

     

    アプリケーション単体でデバッグする場合の利便性向上の為のRESETVECT2セクション → ROMの末尾のBANK0内のCPU仕様で決められた場所に配置/CPUリセット時に使われる

    src/vecttbl_for_standalone_debug.c (例えばのソースファイル名です)

    #include "platform.h"

    #pragma section C RESETVECT2
    void (* const Reset_Vector2[])(void) =
    {
        R_BSP_POWER_ON_RESET_FUNCTION                   /* 0xfffffffc  RESET */
    };
    #pragma section

     

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

    ご説明ありがとうございます。

    いやいやいや、“アプリケーション単体で”の場合にて動作確認する場合には、ずらしては駄目ですよ。

    >リセットベクタ変更した場合、単体で動かないので複数プロジェクトをダウンロードしても駄目だと考えており、そこで躓いていました…。ありがとうございます…!

    ご教示いただいたRESETVECT2の割り当てと、

    void main(void)
    {  
     ((void (*)(void)) 0xXXXXXXXX)(); //XXXXXXXX=main関数のアドレス
    }

    と書き込んで、ひとまずアプリケーション側のプログラムはRESETVECTを変更した状態で動作できました。

    > (5) ブートローダ→アプリケーション、という遷移が出来るようにアプリケーションの方のエントリポイントアドレスだけは固定番地としなければならない。

    >>おっしゃるように、アプリケーション側のエントリポイントアドレス(上記の場合main関数)のアドレスを固定しなければならないです。現在、void main(void)をsectionで配置していますがうまくいかず…。__near/__farを使用したほうが良いかと考えてはいるのですが、実装方法が分からず、教えていただけないでしょうか。