使用CPU:R5F104JG(RL78/G14)
フラッシュセルフプログラミングライブラリType01を使っております。
目的の内容は以下のことです。
このとき、実行中プログラムはベクタ領域0x0000~と、プログラム領域0x3000~を使用しています。
別プログラムはセクション設定でプログラム領域を0x4000~に変更しました。
ここから質問になります。
誠に申し訳ありませんが、宜しくお願い致します。
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; }
NoMaYさん
ご察しの通りSelfFlashWriter.exeは1000Hから上位のhexデータを送信して書き換え後にブートスワップして1000H-1FFFHを0000H-0FFFHにスワップする仕様みたいですね。
RL78でベクタアドレスを変更する機能はFSL_ChangeInterruptTable()しかないので、ちょっと使いにくいですね。
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の領域が元に戻って、再びブートローダが起動する。たぶん、これで済んでしまうのではないか、という気がするのです、、、