Everything

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


本章では,RI600V4が提供しているシステム初期化処理について解説しています。
16.1 概  要
以下に,リセットの発生から処理プログラム(タスク)に制御が移るまでに実行される処理の流れを示します。
図16-1  処理の流れ(システム初期化処理)
16.2 ブート処理ファイル(ユーザ・オウン・コーディング部)
ブート処理ファイルには,以下を記述します。
備考 RI600V4で提供するサンプルのブート処理ファイルは“resetprg.c”です。このファイルには,システム・ダウン・ルーチン(_RI_sys_dwn__( ) )も含んでいます。
16.2.1 ブート処理関数(PowerON_Reset_PC( ))
ブート処理関数はリセットベクタに登録されるプログラムで,スーパバイザ・モードで実行します。通常は,以下のような処理を行います。
- プロセッサ,ハードウエアの初期化
RX MCUの高速割り込みを使用する場合は,FINTVレジスタを高速割り込みハンドラの開始アドレスに初期化してください。
- C/C++言語ソフトウエアの実行環境の初期化(セクションの初期化など)
- 基本クロック用タイマの初期化
cfg600が出力する“ri_cmt.h”で実装されている“void _RI_init_cmt(void)”を呼び出してください。
8.9 基本クロック用タイマの初期化」も参照してください。
- RI600V4を起動(vsta_knlivsta_knlの呼び出し)
- ブート処理の基本型
ブート処理関数は“void PowerON_Reset_PC (void)”としてください。これ以外の関数名とする場合は,システム・コンフィギュレーション・ファイルでinterrupt_fvector[31]にその関数名を定義する必要があります。
ブート処理関数の例については,「16.2.4 ブート処理ファイルの例」を参照してください。
備考 静的API“interrupt_fvector[]”については,「19.19 固定ベクタ/例外ベクタ情報(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を除くサービス・コールの発行が禁止されています。
16.2.2 kernel_ram.hおよびkernel_rom.hの取り込み
cfg600が出力したRAM定義ファイル(kernel_ram.h)とROM定義ファイル(kernel_rom.h)を,ブート処理ファイルの最後で,この順にインクルードしてください。
16.2.3 ブート処理ファイルのコンパイラ・オプション
以下のコンパイラ・オプションの指定が必須です。
- “-lang=c”または“-lang=c99”
- “-nostuff”
- 適切な“-isa”または“-cpu”
備考 コンパイラ・オプションメ-isaモは,コンパイラ CC-RX V2.01以降でサポートされています。
16.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 RI600V4
 #include    "kernel_id.h"               // Generated by cfg600
 
 #if (((_RI_CLOCK_TIMER) >=0) && ((_RI_CLOCK_TIMER) <= 3))
 #include    "ri_cmt.h"   // Generated by cfg600
                       // Do comment-out when clock.timer is either NOTIMER or OTHER.
 #endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 void PowerON_Reset_PC(void);
 void main(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
    
 //#ifdef __cplusplus   // Remove the comment when you use global class object
 //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
 #pragma section ResetPRG        // output PowerON_Reset to PResetPRG section
 
 /////////////////////////////////////////////////////////////////////////////
 // Boot processing
 /////////////////////////////////////////////////////////////////////////////
 #pragma entry PowerON_Reset_PC
 
 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();
 
 //  _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
 
 #if (((_RI_CLOCK_TIMER) >=0) && ((_RI_CLOCK_TIMER) <= 3))
     _RI_init_cmt();  // Initialize CMT for RI600V4
             // Do comment-out when clock.timer is either NOTIMER or OTHER.
 #endif
 
 //  _CALL_INIT();           // Remove the comment when you use global class object
 
     vsta_knl();                     // Start RI600V4
                                     // Never return from vsta_kn
 //  _CLOSEALL();                    // Use SIM I/O
     
 //  _CALL_END();            // Remove the comment when you use global class object
 
     brk();
 }
 /////////////////////////////////////////////////////////////////////////////
 // System down routine for RI600V4
 /////////////////////////////////////////////////////////////////////////////
 #pragma section P PRI_KERNEL
 #pragma section B BRI_RAM
 struct SYSDWN_INF{
     W   type;
     VW  inf1;
     VW  inf2;
     VW  inf3;
 };
 
 volatile struct SYSDWN_INF _RI_sysdwn_inf;
 
 void _RI_sys_dwn__( W type, VW inf1, VW inf2, VW inf3 )
 {
    // Now PSW.I=0 (all interrupts are masked.)
     _RI_sysdwn_inf.type = type;
     _RI_sysdwn_inf.inf1 = inf1;
     _RI_sysdwn_inf.inf2 = inf2;
     _RI_sysdwn_inf.inf3 = inf3;
 
    while(1)
    ;
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // RI600V4 system data
 /////////////////////////////////////////////////////////////////////////////
 #include "kernel_ram.h"     // generated by cfg600
 #include "kernel_rom.h"     // generated by cfg600

16.3 カーネル初期化部(vsta_knl, ivsta_knl)
カーネル初期化部は,vsta_knlivsta_knlの呼び出しによって実行されます。vsta_knlivsta_knlは,通常はブート処理関数(PowerON_Reset_PC( ))から呼び出します。
カーネル初期化部では,以下に示した処理が実行されます。
1 ) ISPレジスタを,SIセクションの最終アドレス+1に初期化
2 ) INTBレジスタを,cfg600によって生成された可変ベクタ・テーブル(INTERRUPT_VECTORセクション)先頭アドレスに初期化
3 ) システム時刻を0に初期化
4 ) システム・コンフィギュレーション・ファイルで定義された各種オブジェクトの生成
5 ) スケジューラに制御を移す
16.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コーディング編」を参照してください。
16.4.1 セクション情報ファイル(ユーザ・オウン・コーディング部)
セクション情報ファイルは,ユーザ・オウン・コーディング部としてユーザが作成する必要があります。
以下に,セクション情報ファイルの例を示します。
備考 RI600V4が提供するサンプルのセクション情報ファイルは“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") },
     /* RI600V4 section */
     { __sectop("DRI_ROM"), __secend("DRI_ROM"), __sectop("RRI_RAM") }
 };
 #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") }
 };
 
 #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")
 };
 
 #pragma packoption

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