第17章  システム初期化処理


本章では,システム初期化処理について解説しています。

17.1 概  要

以下に,リセットの発生から処理プログラム(タスク)に制御が移るまでに実行される処理の流れを示します。

図17−1  処理の流れ(システム初期化処理)



17.2 ブート処理ファイル(ユーザ・オウン・コーディング部)

ブート処理ファイルには,以下を記述します。

1 ) ブート処理関数(PowerON_Reset_PC( ))

2 ) kernel_ram.hおよびkernel_rom.hの取り込み

備考 RI600PXで提供するサンプルのブート処理ファイルは“resetprg.c”です。

17.2.1 ブート処理関数(PowerON_Reset_PC( ))

ブート処理関数はリセットベクタに登録されるプログラムで,スーパバイザ・モードで実行します。通常は,以下のような処理を行います。

- プロセッサ,ハードウエアの初期化
RX MCUの高速割り込みを使用する場合は,FINTVレジスタを高速割り込みハンドラの開始アドレスに初期化してください。


- C/C++言語ソフトウエアの実行環境の初期化(セクションの初期化など)

- RI600PXを起動(vsta_knlivsta_knlの呼び出し)

- ブート処理関数の基本型
ブート処理関数は“void PowerON_Reset_PC (void)”としてください。これ以外の関数名とする場合は,システム・コンフィギュレーション・ファイルでinterrupt_fvector[31]にその関数名を定義する必要があります。
ブート処理関数の例については,「17.2.4 ブート処理ファイルの例」を参照してください。



備考 静的API“interrupt_fvector[]”については,「20.22 固定ベクタ/例外ベクタ情報(interrupt_fvector[])」を参照してください。

- ブート処理関数に関する留意事項

- スタック
以下のように#pragma entryディレクティブを記述してください。これにより,ブート処理関数の先頭でスタック・ポインタ(ISP)をシステム・スタックに設定するコードが生成されます。


 #pragma entry PowerON_Reset_PC


- PSWレジスタ
カーネル初期化部(vsta_knl, ivsta_knl)を呼び出すまでは,全割り込みを禁止した状態とスーパバイザ・モードを維持してください。CPUリセット直後はこの状態(PSW.I = 0,PSW.PM=0)となっているので,通常はPSWレジスタを変更しないでください。


- EXTBレジスタ(RXv2アーキテクチャ)
必要に応じ,EXTBレジスタをFIX_INTERRUPT_VECTORセクションの先頭アドレスに初期化してください。2.6.4節の「FIX_INTERRUPT_VECTORセクション」も参照してください。


- サービス・コールの発行
ブート処理関数はカーネル初期化部(vsta_knl, ivsta_knl)の実行前に実行されるため,vsta_knl,ivsta_knlを除くサービス・コールを呼び出してはなりません。


17.2.2 kernel_ram.hおよびkernel_rom.hの取り込み

cfg600pxが出力したRAM定義ファイル(kernel_ram.h)とROM定義ファイル(kernel_rom.h)を,ブート処理ファイルの最後で,この順にインクルードしてください。

17.2.3 ブート処理ファイルのコンパイラ・オプション

以下のコンパイラ・オプションの指定が必須です。

- “-lang=c”または“-lang=c99”

- “-nostuff”

- 適切な“-isa”または“-cpu”

備考 コンパイラ・オプションメ-isaモは,コンパイラ CC-RX V2.01以降でサポートされています。

17.2.4 ブート処理ファイルの例

 #include    <machine.h>
 #include    <_h_c_lib.h>
 //#include  <stddef.h>                  // Remove the comment when you use errno
 //#include  <stdlib.h>                  // Remove the comment when you use rand()
 #include    "typedefine.h"              // Define Types
 #include    "kernel.h"                  // Provided by RI600PX
 #include    "kernel_id.h"               // Generated by cfg600px
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 void PowerON_Reset_PC(void);
 #ifdef __cplusplus
 }
 #endif
 
 // #ifdef __cplusplus                // Use SIM I/O
 // extern "C" {
 // #endif
 // extern void _INIT_IOLIB(void);
 // extern void _CLOSEALL(void);
 // #ifdef __cplusplus
 // }
 // #endif
 
 #define FPSW_init 0x00000000  // FPSW bit base pattern
 
 // extern void srand(_UINT);     // Remove the comment when you use rand()
 // extern _SBYTE *_s1ptr;        // Remove the comment when you use strtok()
 
 // #ifdef __cplusplus                // Use Hardware Setup
 // extern "C" {
 // #endif
 // extern void HardwareSetup(void);
 // #ifdef __cplusplus
 
 // #endif
 
 // extern "C" {                  // Sections C$INIT and C$END will be generated
 // #endif
 // extern void _CALL_INIT(void);
 // extern void _CALL_END(void);
 // #ifdef __cplusplus
 // }
 // #endif
 ////////////////////////////////////////////////////////////
 // Section definition
 ////////////////////////////////////////////////////////////
 #pragma section P PS
 #pragma section B BS
 #pragma section C CS
 #pragma section D DS
 
 #pragma entry PowerON_Reset_PC
 
 ////////////////////////////////////////////////////////////
 // Boot processing
 ////////////////////////////////////////////////////////////
 void PowerON_Reset_PC(void)
 {
 #ifdef __ROZ                        // Initialize FPSW
 #define _ROUND 0x00000001           // Let FPSW RMbits=01 (round to zero)
 #else
 #define _ROUND 0x00000000           // Let FPSW RMbits=00 (round to nearest)
 #endif
 #ifdef __DOFF
 #define _DENOM 0x00000100           // Let FPSW DNbit=1 (denormal as zero)
 #else
 #define _DENOM 0x00000000           // Let FPSW DNbit=0 (denormal as is)
 #endif
 
 //    set_extb(__sectop("FIX_INTERRUPT_VECTOR"));// Initialize EXTB register
                                                  //  (only for RXv2 arch.)
     set_fpsw(FPSW_init | _ROUND | _DENOM);
 
     _INITSCT();                     // Initialize Sections
 
 //  _INIT_IOLIB();                  // Use SIM I/O
 
 //  errno=0;                        // Remove the comment when you use errno
 //  srand((_UINT)1);                // Remove the comment when you use rand()
 //  _s1ptr=NULL;                    // Remove the comment when you use strtok()
 
 //  HardwareSetup();                // Use Hardware Setup
     nop();
 
 //  set_fintv(<handler address>);   // Initialize FINTV register
 
 //  _CALL_INIT();           // Remove the comment when you use global class object
 
     vsta_knl();                     // Start RI600PX
                                     // Never return from vsta_knl
 
 //  _CLOSEALL();                    // Use SIM I/O
 
 //  _CALL_END();            // Remove the comment when you use global class object
 
     brk();
 
 }
 /////////////////////////////////////////////////////////////////////////////
 // RI600PX system data
 /////////////////////////////////////////////////////////////////////////////
 #include "kernel_ram.h"     // generated by cfg600px
 #include "kernel_rom.h"     // generated by cfg600px


17.3 カーネル初期化部(vsta_knl, ivsta_knl)

カーネル初期化部は,vsta_knlivsta_knlの呼び出しによって実行されます。vsta_knlivsta_knlは,通常はブート処理関数(PowerON_Reset_PC( ))から呼び出します。

カーネル初期化部では,以下に示した処理が実行されます。

1 ) ISPレジスタを,SIセクションの最終アドレス+1に初期化

2 ) INTBレジスタを,cfg600pxによって生成された可変ベクタ・テーブル(INTERRUPT_VECTORセクション)先頭アドレスに初期化

3 ) システム時刻を0に初期化

4 ) システム・コンフィギュレーション・ファイルで定義された各種オブジェクトの生成
ここで異常を検出した場合は,システム・ダウンとなります。


5 ) MPU(Memory Protection Unit)を初期化
ここで異常を検出した場合は,システム・ダウンとなります。


6 ) 基本クロック用タイマの初期化(基本クロック用タイマ初期化ルーチン(_RI_init_cmt_knl( ))の呼び出し)

7 ) スケジューラに制御を移す

17.4 セクション初期化関数(_INITSCT( ))

ブート処理関数(PowerON_Reset_PC( ))から呼び出されるセクション初期化関数“_INITSCT( )”は,コンパイラによって提供されます。_INITSCT( )は,セクション情報ファイル(ユーザ・オウン・コーディング部)に記述されたテーブルにしたがって,未初期化データ・セクションの0クリア,および初期化データ・セクションの初期化を行います。

初期化対象のセクションは、セクション情報ファイルのセクション初期化用テーブル(DTBL,BTBL)へ記述する必要があります。_INITSCT()が使用するセクションの先頭アドレスおよび最終アドレスを、セクションアドレス演算子を用いて設定します。セクション初期化用テーブルのセクション名は、未初期化データ領域をC$BSEC、初期化データ領域をC$DSECで宣言します。

また,DTBLに記述した初期化データ・セクションは,リンカ・オプション“-rom”を用いてROMからRAMにマップする必要があります。詳細は「2.6.5 初期化データ・セクション」を参照してください。

備考 _INITSCT( )の詳細は,「CubeSuite+ RXコーディング編」を参照してください。

17.4.1 セクション情報ファイル(ユーザ・オウン・コーディング部)

セクション情報ファイルは,ユーザ・オウン・コーディング部としてユーザが作成する必要があります。

以下に,セクション情報ファイルの例を示します。

備考 RI600PXが提供するサンプルのセクション情報ファイルは“dbsct.c”です。

 #include "typedefine.h"
 
 #pragma unpack
 
 #pragma section C C$DSEC
 extern const struct {
     _UBYTE *rom_s;       /* Start address of the initialized data section in ROM */
     _UBYTE *rom_e;       /* End address of the initialized data section in ROM   */
     _UBYTE *ram_s;       /* Start address of the initialized data section in RAM */
 }   _DTBL[] = {
     { __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("DS"), __secend("DS"), __sectop("RS") },
     { __sectop("DS_2"), __secend("DS_2"), __sectop("RS_2") },
     { __sectop("DS_1"), __secend("DS_1"), __sectop("RS_1") },
     { __sectop("DU_SH"), __secend("DU_SH"), __sectop("RU_SH") },
     { __sectop("DU_SH_2"), __secend("DU_SH_2"), __sectop("RU_SH_2") },
     { __sectop("DU_SH_1"), __secend("DU_SH_1"), __sectop("RU_SH_1") },
     { __sectop("DU_MASTERDOM"), __secend("DU_MASTERDOM"),
                                             __sectop("RU_MASTERDOM") },
     { __sectop("DU_MASTERDOM_2"), __secend("DU_MASTERDOM_2"),
                                             __sectop("RU_MASTERDOM_2") },
     { __sectop("DU_MASTERDOM_1"), __secend("DU_MASTERDOM_1"),
                                             __sectop("RU_MASTERDOM_1") },
     { __sectop("DU_DOM_A"), __secend("DU_DOM_A"), __sectop("RU_DOM_A") },
     { __sectop("DU_DOM_A_2"), __secend("DU_DOM_A_2"), __sectop("RU_DOM_A_2") },
     { __sectop("DU_DOM_A_1"), __secend("DU_DOM_A_1"), __sectop("RU_DOM_A_1") },
     { __sectop("DU_DOM_B"), __secend("DU_DOM_B"), __sectop("RU_DOM_B") },
     { __sectop("DU_DOM_B_2"), __secend("DU_DOM_B_2"), __sectop("RU_DOM_B_2") },
     { __sectop("DU_DOM_B_1"), __secend("DU_DOM_B_1"), __sectop("RU_DOM_B_1") }
 };
 
 #pragma section C C$BSEC
 extern const struct {
     _UBYTE *b_s;         /* Start address of non-initialized data section */
     _UBYTE *b_e;         /* End address of non-initialized data section */
 }   _BTBL[] = {
     { __sectop("B"), __secend("B") },
     { __sectop("B_2"), __secend("B_2") },
     { __sectop("B_1"), __secend("B_1") },
     { __sectop("BS"), __secend("BS") },
     { __sectop("BS_2"), __secend("BS_2") },
     { __sectop("BS_1"), __secend("BS_1") },
     { __sectop("BU_SH"), __secend("BU_SH") },
     { __sectop("BU_SH_2"), __secend("BU_SH_2") },
     { __sectop("BU_SH_1"), __secend("BU_SH_1") },
     { __sectop("DU_MASTERDOM"), __secend("DU_MASTERDOM"),
                                             __sectop("RU_MASTERDOM") },
     { __sectop("DU_MASTERDOM_2"), __secend("DU_MASTERDOM_2"),
                                             __sectop("RU_MASTERDOM_2") },
     { __sectop("DU_MASTERDOM_1"), __secend("DU_MASTERDOM_1"),
                                             __sectop("RU_MASTERDOM_1") },
     { __sectop("DU_DOM_A"), __secend("DU_DOM_A"), __sectop("RU_DOM_A") },
     { __sectop("DU_DOM_A_2"), __secend("DU_DOM_A_2"), __sectop("RU_DOM_A_2") },
     { __sectop("DU_DOM_A_1"), __secend("DU_DOM_A_1"), __sectop("RU_DOM_A_1") },
     { __sectop("DU_DOM_B"), __secend("DU_DOM_B"), __sectop("RU_DOM_B") },
     { __sectop("DU_DOM_B_2"), __secend("DU_DOM_B_2"), __sectop("RU_DOM_B_2") },
     { __sectop("DU_DOM_B_1"), __secend("DU_DOM_B_1"), __sectop("RU_DOM_B_1") }
 };
 
 #pragma section C C$BSEC
 extern const struct {
     _UBYTE *b_s;         /* Start address of non-initialized data section */
     _UBYTE *b_e;         /* End address of non-initialized data section */
 }   _BTBL[] = {
     { __sectop("B"), __secend("B") },
     { __sectop("B_2"), __secend("B_2") },
     { __sectop("B_1"), __secend("B_1") },
     { __sectop("BS"), __secend("BS") },
     { __sectop("BS_2"), __secend("BS_2") },
     { __sectop("BS_1"), __secend("BS_1") },
     { __sectop("BU_SH"), __secend("BU_SH") },
     { __sectop("BU_SH_2"), __secend("BU_SH_2") },
     { __sectop("BU_SH_1"), __secend("BU_SH_1") },
     { __sectop("BU_MASTERDOM"), __secend("BU_MASTERDOM") },
     { __sectop("BU_MASTERDOM_2"), __secend("BU_MASTERDOM_2") },
     { __sectop("BU_MASTERDOM_1"), __secend("BU_MASTERDOM_1") },
     { __sectop("BU_DOM_A"), __secend("BU_DOM_A") },
     { __sectop("BU_DOM_A_2"), __secend("BU_DOM_A_2") },
     { __sectop("BU_DOM_A_1"), __secend("BU_DOM_A_1") },
     { __sectop("BU_DOM_B"), __secend("BU_DOM_B") },
     { __sectop("BU_DOM_B_2"), __secend("BU_DOM_B_2") },
     { __sectop("BU_DOM_B_1"), __secend("BU_DOM_B_1") }
 };
 #pragma section
 
 /*
 ** CTBL prevents excessive output of L1100 messages when linking.
 ** Even if CTBL is deleted, the operation of the program does not change.
 */
 _UBYTE * const _CTBL[] = {
     __sectop("C_1"), __sectop("C_2"), __sectop("C"),
     __sectop("W_1"), __sectop("W_2"), __sectop("W"),
     __sectop("CU_MASTERDOM"),
     __sectop("CU_DOM_A_1"), __sectop("CU_DOM_A_2"), __sectop("CU_DOM_A"),
     __sectop("CU_DOM_B_1"), __sectop("CU_DOM_B_2"), __sectop("CU_DOM_B"),
     __sectop("WU_SH_1"), __sectop("WU_SH_2"), __sectop("WU_SH"),
     __sectop("LU_SH"),
     __sectop("CU_SH_1"), __sectop("CU_SH_2"), __sectop("CU_SH"),
     __sectop("CS_1"), __sectop("CS_2"), __sectop("CS"), __sectop("P")
 };
 
 #pragma packoption


17.5 固定ベクタ・テーブル/例外ベクタ・テーブルのレジスタなど

MCUによっては,固定ベクタ・テーブル(RXv1アーキテクチャ)/例外ベクタ・テーブル(RXv2アーキテクチャ)内の0xFFFFFF80〜0xFFFFFFBF番地に,エンディアン選択レジスタやオンチップ・デバッガIDコード・プロテクトなどが割り当てられています。これらを設定するには,システム・コンフィギュレーション・ファイルに“interrupt_fvector[]”を記述してください。詳細は,「20.22 固定ベクタ/例外ベクタ情報(interrupt_fvector[])」を参照してください。