フラッシュ書き換えについて

使用CPU:R5F104JG(RL78/G14)

フラッシュセルフプログラミングライブラリType01を使っております。

目的の内容は以下のことです。

  • 実行中プログラムで、別プロブラムのmotファイル内容をシリアルで受け取る。
  • ライブラリを使用して、motファイル内容を書き込む。
  • 別プログラムを実行する。

 このとき、実行中プログラムはベクタ領域0x0000~と、プログラム領域0x3000~を使用しています。

 別プログラムはセクション設定でプログラム領域を0x4000~に変更しました。

 ここから質問になります。

  • ベクタ領域は「セクション設定」で変更する項目がありませんでしたが、変更する方法はあるのでしょうか?
  • 変更する方法がなければ、別プログラムのベクタ領域(0x0000~)を、ブートクラスタ1のベクタ領域(0x1000~)へ書き込んで良いのでしょうか?
  • ブートクラスタ1のベクタ領域(0x1000~)とプログラム領域(0x4000~)の書き換え後、アドレスジャンプで、0x1000へ飛べば、別プログラムは実行されるのでしょうか?(次回からは、最初の実行中プログラムから立ち上げたいので)

誠に申し訳ありませんが、宜しくお願い致します。

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

    以下はType01のマニュアルの画面コピーなのですが、FSL_InvertBootFlag()を呼び出す必要は無く、FSL_SwapBootCluster()を呼び出すだけで良いと思います。ただ、私が赤枠で囲った所は要注意かもと思いました。また、constセクションに関するCC-RLのエラーですが、constセクションはミラー領域に配置しなければなりませんので、それでエラーになったのでは?と思います。それで、正直に言うと自分でブートスワップを行うアプリケーションを作ったことが無くて思い付きになってしまいますが、対処案としては以下のようにすることではないだろうか、と思います。

    (0) 新規に .vect2 とか .option_byte2 とか .security_id2 といったセクションを使うことにします
    (1) リンカ設定でそれぞれのセクションを適切なアドレスに配置する(他にもソース上で#pragmaでも出来た気もします)
    (2) ソース上で const uint16_t vect2[0x40] といった変数を用意する
    (3) ソース上で#pragmaでそれらの変数をそれぞれのセクションに配置する

    上に書いた方法は面倒とは言え手堅い方法だと思いますが、自分でもやってみないと出来るかどうか自信が無いのですが、以下の方法も考えられます。

    (A) リンカにプログラムの一部をバイナリ(or HEX)データとして切り出す機能があったと思います
    (B) 逆に、バイナリ(or HEX)データをプログラム(or データ)として取り込む機能もあったと思います
    (C) これらの機能を巧みに組み合わせて所望のフラッシュメモリイメージを作成出来るかも知れません

    あと、ひょっとして、これが知りたかった回答に繋がる話なのかも?と思ったのは、私の前の投稿で伝えた『RL78/G13フラッシュ・セルフ・プログラミング実行編 』のサンプルプログラムで、以下に関して私がまだ読み取れていないことに気付きました。現在、調査中です。

    (謎) どうやって新しいプログラムのHEXの0x0~0x0FFFのアドレスを0x1000~0x1FFFのアドレスに付け替えているのか?
    SelfFlashWriterという書き込みツールがデータ送信時にアドレスを付け替えているのか?
    サンプルプログラム内でSelfFlashWriterから送られてきたデータのアドレスを付け替えているのか?
    HEXファイル作成時に何らかの手段で付け替えているのか?

    RL78ファミリ フラッシュ・セルフ・プログラミング・ライブラリ Type01 日本リリース版
    www.renesas.com/jp/ja/doc/products/tool/doc/015/r01us0050jj0105_rl78.pdf

  • Kirinさん、NoMaYです。プリーズ ヘルプ ミー!です。(もし御存知なら教えて下さい。)

    『RL78/G13フラッシュ・セルフ・プログラミング実行編 』のサンプルプログラムを追い掛けているのですが、以下の点に関して、SelfFlashWriterがアドレスの付け替えをしているのではないか?と考え始めているのですが、既にKirinさんの方で調査済みであれば、教えて頂けるとうれしいです。

    > (謎) どうやって新しいプログラムのHEXの0x0~0x0FFFのアドレスを0x1000~0x1FFFのアドレスに付け替えているのか?
    > SelfFlashWriterという書き込みツールがデータ送信時にアドレスを付け替えているのか?
    > サンプルプログラム内でSelfFlashWriterから送られてきたデータのアドレスを付け替えているのか?
    > HEXファイル作成時に何らかの手段で付け替えているのか?

    追い掛けた結果、以下からSelfFlashWriterがアドレスの付け替えをしているのではないか?と考え始めているのですが、『RL78/G13フラッシュ・セルフ・プログラミング実行編 』のドキュメントに記載が無くて、私が勘違いしているのかも知れない?とも思うのです、、、

    根拠

    (1) サンプルプログラムに同梱されている以下の確認用ビルド済みHEXファイルは新しいブート部も0x0000番地から始まっている。

    an_r01an0718ej0102_rl78g13_flash\r01an0718_praxis01\TestData\r_fsl_praxis01_write_test.hex

    :0400000300000000F9
    :020000020000FC
    :02000000D80026

    :100B8B000472AC0616C5F647DD07621199A5B7EFDF
    :050B9B00F5C2C4C6D73D
    :020000020000FC
    :100BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55

    :100FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11
    :100FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01
    :10100000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
    :10101000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0

    :101FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01
    :101FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1
    :020000020000FC
    :04200000EC042000CC
    :020000020000FC
    :10200400CBF8D4FE36C2F5FC0B0B00410036DC20C5

    (2) 以下のサンプルプログラムのソースを見る限り、サンプルプログラム内でSelfFlashWriterから送られてきたデータのアドレスを付け替えてはいない。しかも、ブロック0~3(0x0000~0x0FFF)のデータが来たらエラーを返すようになっている。(赤文字箇所)

    an_r01an0718ej0102_rl78g13_flash\r01an0718_praxis01\src\boot\r_fsl_praxis01_boot_write.c

    UB prBootWriteProgram( void )
    {

            /* Communication loop */
            while( duhSelfLoop == true )
            {
                /*-- Receive from SelfFlashWriter --*/
                do
                {   /* Receive Uart command message */
                    dubMsgResult = prUartRcvMsg( &prDubMsgBuffer[0], &dubCommnad );
                    
                    if( dubMsgResult != PR_MSG_RET_NORM_END )
                    {   /* Send error to SelfFlashWriter if an error is found in the command. */
                        prUartSendMsg( dubCommnad, dubMsgResult );
                    }
                }
                while( dubMsgResult != PR_MSG_RET_NORM_END );
                
                /*-- Process according to the type of the command. --*/
                switch( dubCommnad )
                {
                    /*-- WRITE Command --*/
                    case PR_MSG_COMM_WRITE:
                    {
                        UB  dub_i;
                        UB  dubStartEraseBlock;
                        UW  duwStartWriteAddress;
                        UB  dubBlockLength;
                        
                        /*-- Store received data (Block to program, address, size) from buffer. --*/
                        dubStartEraseBlock    = prDubMsgBuffer[ PR_MSG_BLOCK_NUM ];
                        duwStartWriteAddress  = ( (UW)( prDubMsgBuffer[ PR_MSG_ADDR_HI  ] ) ) << 16;
                        duwStartWriteAddress |= ( (UW)( prDubMsgBuffer[ PR_MSG_ADDR_MID ] ) ) <<  8;
                        duwStartWriteAddress |= ( (UW)( prDubMsgBuffer[ PR_MSG_ADDR_LOW ] ) );
                        duwWriteSize          = ( (UW)( prDubMsgBuffer[ PR_MSG_SIZE_HI  ] ) ) << 8;
                        duwWriteSize         |= ( (UW)( prDubMsgBuffer[ PR_MSG_SIZE_LOW ] ) );
                        duwEndWriteAddress    = duwStartWriteAddress + duwWriteSize  - 1;
                        dubBlockLength        = (UB)( ( duwWriteSize - 1 ) / PR_BLOCK_SIZE ) + 1;
                        
                        /* Parameter check (blocks 0-3 protection, inhibit 0 size writing, etc.) */
                        if( ( dubStartEraseBlock >= 4                ) &&   /*  */
                            ( dubStartEraseBlock <  PR_MAX_BLOCK_NUM ) &&   /*  */
                            ( duwWriteSize       != 0                ) )    /*  */
                        {
                            /* Check state of blocks subject to programming and erase processing */
                            for( dub_i = 0 ; dub_i < dubBlockLength ; dub_i++ )
                            {
    #ifdef PR_USE_OCD_MODE      /* Do nothing on monitor area in OCD mode. */
                                if( ( dubStartEraseBlock + dub_i ) != PR_OCD_MONITOR_BLOCK )
                                {
    #endif
                                    DI();
                                    dubSelfResult = FSL_BlankCheck( dubStartEraseBlock + dub_i );
                                    
                                    /* If the target block is nonblank. */
                                    if( dubSelfResult == FSL_ERR_BLANKCHECK )
                                    {
                                        
                                        dubSelfResult = FSL_Erase( dubStartEraseBlock + dub_i );
                                    }
                                    
                                    EI();

    #ifdef PR_USE_OCD_MODE      /* Do nothing on monitor area in OCD mode. */
                                }
                                else {
                                    dubSelfResult = FSL_OK;
                                }
    #endif
                            }
                            
                            /* Set address to write. */
                            duwWriteAdressIndex = duwStartWriteAddress;
                            
                            /* Convert flash self programming result to a transmit parameter. */
                            dubMsgResult = prFslErrorCheck( dubSelfResult );
                        }
                        else {
                            dubMsgResult = PR_MSG_RET_PRM_ERR;
                        }
                        
                        /* Send result. */
                        prUartSendMsg( dubCommnad, dubMsgResult );
                        break;
                    }

     

  • Kirinさん、こんにちは。NoMaYです。リプライ有難う御座いました。

    SelfFlashWriter.exeは単に1000Hから上位のHEXデータを送信しているだけであって、HEXデータの0x0~0x0FFFのアドレスを0x1000~0x1FFFのアドレスに付け替えてはいないので私の勘違いだった、ということですね。

    でも、そうなると、最終的に0x1000~0x1FFFの領域は全てFFの値でしかなくて、ブートスワップしたら暴走してしまうのではないでしょうか???

    [追記]

    以下はSelfFlashWriter.exeの画面コピーなのですが、もしかしたらChip(BootSwap)モードとBlockモードで挙動が違う(前者はアドレスを付け替えるが後者はアドレスを付け替えない)とかかも?



    [追記その2]

    このスレッドであれこれ調べて思ったのですが、ブートスワップ機能を本来想定されている使い方ではなくて、miesuge2さんの発想で使うと、ブート領域/フラッシュ領域の分割の話が簡単な話になるような気がしてきました。(ただし、0x1000~0x1FFFの4Kバイトは、そのカラクリの為の予約領域と割り切って、その分だけROMサイズが小さくなることに相当すると割り切る必要がありますが。)

    具体的には、以下のようにしてブートローダとアプリケーションをビルドすれば良いだけの話になって、RL78のフラッシュセルフプログラミングでやっかいな話である、ブート領域とフラッシュ領域に分けてもベクタ領域は両者で共有されなければならない、という問題から解放されるような気がします。(CA78K0Rはコンパイラの便利機能のおかげで殆ど意識しなくて済みますが、CC-RLは割り込み用のジャンプテーブルを自分でメンテしなければならないとかコード生成機能で生成したソースの#pragma interruptのベクタ部分をコード生成する度に手作業で削除しなければないらないとか大変面倒なことになっているのではないかと想像します。)

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

    ● 0x1000~0x1FFFと0x2000以降でブートローダが使う領域を空ける以外は普通にプログラムを作ればよい。
    ● コード生成もOK。(いつもと同じように使うだけで良い。)
    ● RAMも普通に使って良い。

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

    ●0x1000~0x1FFFの領域を空ける以外は普通にプログラムを作ればよい。(普通と言ってもセルフプログラミングは行います。)
    ●なお、セルフプログラミングでアプリケーションを書き込む時、ビルドしたアプリケーションの0x0~0xFFFの領域がフラッシュメモリの0x1000~0x1FFFの領域に書き込まれるように、書き込みのシステムを作っておきます。
    ● コード生成もOK。(いつもと同じように使うだけで良い。)
    ● RAMも普通に使って良い。
    ● 1つ特殊なことはブートローダからアプリケーションに制御を移す時にFSL_SwapBootCluster()を使うことです。そうすると、0x0~0xFFFの領域と0x1000~0x1FFFの領域が入れ替わって、入れ替わり後のリセットベクタが指すアドレスに制御が移る。(ただし、CPUリセットが行われるわけではない。) そして、次にCPUリセットが行われた時は、FSL_SwapBootCluster()で一時的に入れ替わっていた0x0~0xFFFの領域と0x1000~0x1FFFの領域が元に戻って、再びブートローダが起動する。

    たぶん、これで済んでしまうのではないか、という気がするのです、、、

  • 返信ありがとうございます。

    ここまで調べて下さり大変助かります。
    一つずつ調べていきますのでまた結果をお知らせ致します。
  • Kirinさん、こんにちは。NoMaYです。

    SelfFlashWriterの動作を確認して頂いて、どうも有難う御座いました。やはり、Chip(BootSwap)モードとBlockモードで挙動が違ったのですね。(前者はアドレスを付け替えるが後者はアドレスを付け替えない。) これで辻褄が合いました。

    # ちなみに、Kirinさんの投稿が以下のContent Under Reviewになってしまうのは、何故なんでしょうね、、、 私が以前に頻繁に遭遇したのは、私の投稿を読んだ人が資料に辿り付き易くなるようにリンクのURLを多量(といっても10個程度、URL文字列を直接書いたら4個でもダメな時期がありましたが)に貼り付けた時ですね。ブログシステムがそういう投稿を自動的にContent Under Reviewにするようです。厄介なのは、ブログシステムがURLっぽい文字列をURLだと誤認する時があり、大丈夫なように書いた筈の投稿がContent Under Reviewになったこともありました。あと、Preview表示させた時に何も言って来なくて、Postすると言ってくるのも、困惑してしまいます。

    Content Under Review

    This content is currently pending review by moderators and is not available. Please try again later.

    Kirinさんが苦肉の策でgifファイルとして貼り付けた内容を、普通にテキスト入力して投稿しただけですよね。メモリダンプ形式のような16進数の羅列もダメだったりとかするのかな、、、

  • Kirin様 NoMaY様

    管理人のAyrです。

    プログラムのソースコード等で書き込みが上手くいかないときは

    プログラムの部分だけ、テキストファイルにしておいて

    書込みフォームに入ってから画面下の"USE RICH FORMATTING"をクリックした後に

    テキストをドラッグアンドドロップしてみてください。

     

    ここにテキストファイルをリンクしてみます。

    TEST.txt
    
    
    
    -----------------------------------------------------------------
    EVP(Chip/BOOTSWAP) 01 00 08 05 04 00 10 00 04 00 26
    ACK 01 00 03 05 00 09
    WRITEDATA 01 01 02 06 
    D8 00 FF FF 05 02 0C 20 0A 02 14 20 18 20 1C 20 
    20 20 24 20 28 20 2C 20 30 20 34 20 38 20 3C 20 
    40 20 44 20 48 20 4C 20 50 20 54 20 58 20 5C 20 
    60 20 64 20 68 20 6C 20 70 20 74 20 78 20 7C 20 
    80 20 84 20 88 20 8C 20 90 20 94 20 98 20 9C 20 
    A0 20 A4 20 A8 20 AC 20 B0 20 B4 20 B8 20 BC 20 
    C0 20 C4 20 C8 20 CC 20 D0 20 D4 20 D8 20 DC 20 
    E0 20 E4 20 E8 20 EC 20 F0 20 F4 20 F8 20 FC 20 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF E8 84 00 00 00 00 00 00 00 00 00 00 FF FF 
    FF FF FF FF FF FF FF FF 61 CF 51 00 71 8C 71 09 
    FE CB F8 20 FE FC 7E 07 00 36 C2 F5 FC 0B 0B 00 
    53 C0 F6 93 93 58 20 FE DF F9 41 00 36 44 02 34 
    BC 01 00 08 05 08 00 20 00 04 00 3A
    -----------------------------------------------------------------
    EPV(Block) 01 00 08 05 04 00 10 00 04 00 26 
    ACK 01 00 03 05 00 09 
    WRITEDATA 01 01 02 06 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    0A

  • NoMaYさん
    FTDIのNull modem cable usb(ケーブルの両端がUSB Aコネクタ)を使うとCOMポート出力を別のCOMポートで受けられるので、GUIから出力されたデータをターミナルソフトで簡単に見ることができます。
    (RL78のボードを使わず確認してます^-^)
  • Ayrさんコメントありがとうございます。
    Ayrさんは非表示になった投稿見えるんですねー^^
  • 返答が遅くなり、大変申し訳ありません。
    検証が終わりました。


    NoMaY様が2019/3/24に回答されました方法を試しました。

    アプリケーション(0x1000~0x1FFF、0x4000~0x4FFF)、
    ブートローダ(0x0000~0x0FFF、0x3000~0x3FFF)に配置されるように作成。
    ※アプリケーションは単体での動作確認済み。

    以下、検証結果になります。



    1)0x04000~0x17FFFをFSL_Eraseで消去。
    ※戻り値が全て「FSL_OK」なのを確認。

    2)ブートローダ側で、アプリケーションのmotファイルを読み込み、FSL_Writeにて全て書き込みました。
    ※戻り値が全て「FSL_OK」なのを確認。
    ※アプリケーションのベクタ配置は変更が出来なかったので、ブートローダでmotファイル読み込み時に、0x0000~0x0FFF→0x1000~0x1FFFへ振替。
    ※書き込み後、ブートローダは正常に実行されていた。

    3)書き込み後、FSL_SwapBootClusterを実行するとCPUがリセットされ、ブートローダ側が再び起動した。
    電源を入れ直しても、ブートローダ側が起動された。

    4)FSL_SwapBootClusterのマニュアルを読むと、「FSL_ChangeInterruptTableで割り込みの飛び先をRAMの~」とあるが、
    RAMのどの位置を指定すればよいのか、また、RAMへ何かデータをコピーする必要があるのか不明です。



    CPUがリセットするのは、FSL_ChangeInterruptTableでRAMを指定してないのが原因でしょうが、使い方が判りません。

    色々と回答を書いて頂き、誠にありがとうございます。
  • FSL_SwapBootClusterの処理が完了する前に割り込みの必要がなければ、FSL_ChangeInterruptTableを実行する必要はありませんでした。
    誠に申し訳ありません。


    しかし、FSL_SwapBootClusterを実行するとCPUがリセットしてしまい、ブートローダ側が起動する問題の原因が判りません。

    試しに、FSL_InvertBootFlagを実行してブートフラグを反転してみたら、CPUがリセットして何も起動しなくなり、
    電源を入れ直しても、何も起動しなくなりました。切替部分を教えて頂けないでしょうか?
  • 誠に申し訳ありません。
    FSL_SwapBootClusterで、アプリケーション側に正常に切り替わりました。

    FSL_Write時のアドレス指定を間違えており、修正すると正常に動きました。

    色々と教えて頂き、誠にありがとうございます。
    本当に助かりました。
Reply
  • 誠に申し訳ありません。
    FSL_SwapBootClusterで、アプリケーション側に正常に切り替わりました。

    FSL_Write時のアドレス指定を間違えており、修正すると正常に動きました。

    色々と教えて頂き、誠にありがとうございます。
    本当に助かりました。
Children
No Data