本文へスキップ

未来の科学技術を子供たちに託す。 ジュニロボ <JRO>

〒619-0237 京都府相楽郡精華町光台8丁目

TEL. 070-5263-2200

jun@kinet-tv.ne.jp

C 言語だけでスタートアップルーチンを記述                        RECRUI


   今回利用する C コンパイラには、通常 C 言語で記述できない特殊な命令を組込み関数として用意されています。
  また、コンパイラの拡張機能( #pragma )を利用することにより、C 言語だけでスタートアップルーチンを記述できます。

  アセンブラで記述していた、vect7709s.src と init.c をプロジェクトから削除( ファイルを選択し、Delete キー )します。

  

  下画面になります。

  



  削除前には、「最適化リンカ」−「カテゴリ:セクション」には、VECT が指定されていますが、削除後にどうなっているか確認しましょう。

  

  VECT セクションが無くなっています。

  

  この状態でビルドするとどうでしょうか? 当然 VECT セクションがないのでリンク時にエラーが発生します。

  

  アセンブラで記述していた、vect7709s.src と init.c 代わりに C 言語で記述された inita.c を追加します。
  inita.c を追加すると、自動的に「Dependencies」部に、7709s.h が現れます。
  これで、ビルドしてみましょう。 今回は、エラー、ワーニングは出ません。

  

  また、エントリポイントがソースコード上で定義されているので、オプション設定で、これを削除します。

  「 inita.c 」のソースファイル内容は、下記の通りです。

/*-------------------------------------------------------------------------------------------------------------------------------------------------------
     Startup Routine
     File Name : inita.c
 C 言語だけで、スタートアップルーチンを記述する。
 " 7709s.h ” をインクルードする為に、init フォルダにコピーする必要がある。
 stacksize で、指定したサイズの S セクションが生成されるようにする。
 entry の設定を行うことで、SP(R15) の設定も行う様にする。
-------------------------------------------------------------------------------------------------------------------------------------------------------*/

/* 組込関数を利用する時に必要 */
#include <machine.h>

/* SH7709s 用のヘッダファイル( 内蔵周辺モジュールを扱いやすくする為の構造体が定義されている。 ) */
#include "7709s.h"

/* スタックセクション S を指定した領域で確保される。 */
#pragma stacksize 1024

/* エントリ関数の作成( startup 関数 ) */
#pragma   entry  startup
#define   INIT_VBR   (void **)0x8c000000
#define   INIT_SR    0x600000f0

/* 別のソースファイルで定義してある関数を呼び出し可能にする為の宣言 */
extern   void  main(void);
extern    int *_D_ROM,  *_B_BGN,  *_B_END,  *_D_BGN,  *_D_END;
void    _INITSCT(void);

#pragma  section  START  /* .section PSTART、 CODE, ALIGN=4  */

void  tartup(void)
{
  /* コードはないが、最初にスタックが設定される。 ミックス表示を有効にして確認しましょう。 */
  /* この位置に様々なシステムの初期化を書きます。 */

  _INITSCT();  /* D ---> R へのコピー、 0 ---> B  */

  set_vbr(INIT_VBR);
  set_cr(INIT_SR);  /* SR の設定( 組込関数 ) */
  main();       /* main 関数呼び出し */
  while(1);      /* もしも、main 関数から戻ったら、無限ループ */
}

void _INITSCT(void)
{
  int *p, *q;
  /* ----- Zero Clear ------ */
  for( p = _B_BGN; p < _B_END; p++)
   *p = 0;
  /* ---- ROM to RAM ----- */
  for( p = _D_BGN, q = _D_ROM; p < _D_END; p++, q++)
   *p = *q;
}
//------------------------------------------------------------------------------------------------------------------


リセットスタートプログラム                        RECRUI


   リセットスタートプログラムは、inita1.c として作成します。これをプロジェクトに追加します。
  リセットスタートプログラムは、上記「 C 言語だけでスタートアップルーチンを記述」を参考に HEW を設定します。

   BSC( バス・ステート・コントロール )等の CPU の初期化を含めたリセットスタートプログラムを下記に示します。
  このプログラムは当然、H’A0000000 番地以降に配置します。
  CPUの初期化は、構造体、共用体を利用して設定します。ここで用いる構造体、共用体の定義は ”7709s.h" で行っています。

   ほとんどのマイコンにおいて、最初に行わなければならないことは、スタックポインタ SP の設定です。ここでも、#praguma の指示により、スタック
  領域と SP ( R15 ) の設定が行われます。 < プログラム中の下記部分 >

     /* スタックセクション S が生成される。 */
     #pragma  stacksize  1024
     /* ここで、指定した関数の先頭で SP ( R15 ) の設定が行われる。 */
     #pragma  entry    startup

            ↓
            ↓

     _startup:                        ; function: startup 、 frame size=0
             MOV.L      L13+2,R15        ; STARTOF S+SIZEOF  S
     L13:
             .RES.W     1
             .DATA.L     STARTOF S+SIZEOF  S

             .SECTION    S,STACK,ALIGN=4
             .RES.B     1024
             .END

    プログラムは BSC、SDRAM、PFC ( ピンファンクションコントローラ )、CPG( Iφ、Bφ、Pφ )及びキャッシュの設定を行います。
    リセットスタートプログラムが置かれているエリア 0( H'A0000000 〜 )は、MD4 と MD3 端子によってバス幅を設定でき、フラッシュROMなでの
   ROM を配置しますので、リセット後、すぐに動作できます。他のエリアはプログラムで BSC の設定が必要となります。SDRAM のモードレジスタは、
   アドレスバスに接続されていますので、ダミーデータをモード設定に応じたアドレスに出力することによって行います。SDRAM の設定が終了すると、
   RAM とのアクセスは可能となります。

    また、SR の設定は特権モード、レジスタバンク1、割り込みブロックビット:1、割り込みマスクレベル:0( マスクしない )となります。
      set_cr( 0x60000000 ); /* SR の設定( 組込関数 )0、 MD:1、RB:1、BL:0、I3 ~ I0:0 */


   inita1.c がどの様に変換されるのかを、ファイルのビルドでアセンブリソースに変換して確認してみましょう。
   HEW オプションメニューから、「SuperH RISC engine Standerd Toolchain.....」を選択します。
   表示されたダイアログボックスの左側のコンフィグレーションから inita1.c を選択します。
   そして、このファイルをデバッグ情報なしにアセンブリソースに変換する様に、C コンパイラに対してオプション設定します。
   設定終了後に、ファイルを選択( inita1.c )し、ファイルのビルドを実行します。

  

   ビルド実行後には、コンフィグレーションフォルダに、inita1.src が生成されますので、エディタで開いてみましょう。
   尚、7709s.h は、ルネサスエレクトロニクス社のホームページのサンプルポログラム集から自由にダウンロードできます。

   < inita1.c >のソースファイル

/*-------------------------------------------------------------------------------------------------------------------------------------------------------
     Startup Routine
     File Name : inita1.c
 C 言語だけで、スタートアップルーチンを記述する。
 BSC やメモリの初期化を始め、様々なシステムの初期化を追加
-------------------------------------------------------------------------------------------------------------------------------------------------------*/

/* 組込関数を利用する時に必要 */
#include <machine.h>

/* SH7709s 用のヘッダファイル( 内蔵周辺モジュールを扱いやすくする為の構造体が定義されている。 ) */
#include "7709s.h"

/* スタックセクション S を指定した領域で確保される。 */
#pragma stacksize 1024
/* エントリ関数の作成( startup関数 ) */
/* ここで、指定した関数の先頭でSP ( R15 ) の設定が行われる。 */
#pragma entry startup

#define INIT_VBR (void **)0xA0001000
#define INIT_SR 0x60000000

#define SDRAM1 (*(volatile unsigned char *)0xFFFFD880)   /* SDRAM mode set Address */
#define SDRAM2 (*(volatile unsigned char *)0xFFFFE880)   /* SDRAM mode set Address */
/* バースト長 1 のバーストリード/シングルライトモード、エリア 2、3、32ビットバス、CASレイテンシ 2 */

/* 別のソースファイルで定義してある関数を呼び出し可能にする為の宣言 */
extern void main(void);
extern int *_D_ROM, *_B_BGN, *_B_END, *_D_BGN, *_D_END;

void _INITSCT(void);

#pragma section START            /* .section PSTART、 CODE, ALIGN=4  */

void startup(void)
{
  /* コードはないが、最初にスタックが設定される。 */

 CPG.WTCSR.WRITE = 0xa507;   /* TIM = 0 WDT 停止、Pφ の分周比 1/4096 */
 CPG.WTCNT.WRITE = 0x5a00;   /* Pφ = 33MHz、オーバーフロー周期:31.8 ms = 1 / ( 33M ÷ 4096 ÷ 256 ) */
 CPG.FRQCR.WORD = 0xa101;    /* モード 2、入力クロック 16.6667M、I:B:P=12:4:2( SH2002 ) */

 BSC.BCR1.WORD = 0xf00f;     /* PULA = 1    A25 ~ A0 プルアップする。
                      PULA = 1    D31 ~ D0 プルアップする。
                      HIZMEM =1  スタンバイ時 High-Z
                      HIZCNT = 1   バス権解放時 RAS、CAS High-Z
                      A0BST = 00   エリア 0 通常メモリ( Flash )
                      A5BST = 00   エリア5 通常モード( )
                      A6BST = 00   エリア6 通常モード( )
                      DRAMTP = 011 エリア2、 エリア3 SDRAM
                      A5PCM = 1   エリア5 PCMCIA 空間
                      A6PCM = 1   エリア6 PCMCIA 空間 */
 BSC.BCR2.WORD = 0x1bf0;     /* A6SZ = 01   エリア6 バス幅 8 ビット( 外部バス:メモリ )
                     A5SZ = 10   エリア5 バス幅 16 ビット( コンパクトフラッシュカード、LED )
                     A4SZ = 11   エリア4 バス幅 32 ビット( LAN0、LAN1、USB )
                     A3SZ = 11   エリア3 バス幅 32 ビット( SDRAM )
                     A2SZ = 11   エリア2 バス幅 32 ビット( SDRAM ) */
 BSC.WCR1.WORD = 0xbff3;     /* WAITSEL = 1 CKIO 立ち下がりでサンプル
                     A6IW1- 0 = 11  エリア6 3アイドルサイクル( 外部バス:メモリ )
                     A5IW1- 0 = 11  エリア5 3アイドルサイクル( コンパクトフラッシュカード、LED )
                     A4IW1- 0 = 11  エリア4 3アイドルサイクル( LAN0、LAN1、USB )
                     A3IW1- 0 = 11  エリア3 3アイドルサイクル( SDRAM )
                     A2IW1- 0 = 11  エリア2 3アイドルサイクル( SDRAM )
                     A0IW1- 0 = 11  エリア0 3アイドルサイクル( FLASH ) */
 BSC.WCR2.WORD = 0xffd7;     /* 111 1、11 11、1 10 1,0 111
                     A6W2 - 0 = 7   エリア6 10ウエイトステート
                     A5W2 - 0 = 7   エリア5 10ウエイトステート
                     A4W2 - 0 = 7   エリア4 10ウエイトステート
                     A3W1 - 0 = 2   エリア3 CAS LATENCY 2
                     A2W1 - 0 = 2   エリア2 CAS LATENCY 2
                     A0W1 - 0 = 7   エリア0 10ウエイトステート( フラッシュメモリ ) */
 BSC.MCR.WORD = 0x516c;      /* TPC = 01    PRECHARGE → ACTIVE 2CLK
                     RCD = 01    ACTIVE → READ/WRITE 2CLK( 30 ns )
                     TRWL = 00   WRITE → PRECHARGE 1CLK
                     TRAS = 01   2CLK , AUTO REFRESH → ACTIVE TRAS + TPC = 3CLK( 45 ns )
                     RASD = 0    AUTO PRECHARGE
                     AMX3 - 0 = 1101 64M Bit
                     RESH = 1    Refresh Enable
                     RMODE = 0   Auto Refesh
                     EDOMODE = 0  EDO Mode Disable */

 BSC.RTCNT = 0xa51c;       /* RTCNT カウンタクリア */
 BSC.RTCOR = 0xa582;       /* 64 ms / 8192 = 7.8 μs 7.8 μs / 0.06 μs = 130 = 0x82 */
 BSC.RFCR = 0xa400;
 BSC.RTCSR.WORD = 0xa508;    /* CKIO / 4 ,  66.6MHz / 4 = 60ns = 0.06 μs */

 while(BSC.RFCR<8);        /* メモリの仕様 */
 SDRAM1 = 0;            /* SDRAM mode set
                     M9 = 1      Single Location Access
                     M8 - 7 = 0     Standard Operation
                     M6 - 4 = 010   CAS Latency 2
                     M3 = 0      Burst Type Sequential
                     M2 - 0 = 000   Burst Length 1 */
 SDRAM2 = 0;            /* SDRAM mode set */
                     M9 = 1      Single Location Access
                     M8 - 7 = 0     Standard Operation
                     M6 - 4 = 010   CAS Latency 2
                     M3 = 0      Burst Type Sequential
                     M2 - 0 = 000   Burst Length 1 */

 BSC.PCR.WORD = 0x0000;     /* PCMCIA */
 INTX.ICR1.WORD = 0x0000;    /* IRQLVL - 0 IRQ3 ~ 0 独立 */

 /* キャッシュの設定 */
 CCR = 0x00000008;         /* Cache invalid */
// CCR = 0x00000001;        /* Cache ON 、 ライトスルー */


 _INITSCT();            /* D → R へのコピー、0→ B  */

 set_vbr(INIT_VBR);
 set_cr(INIT_SR);          /* SR の設定( 組込関数 ) */
 main();               /* main 関数呼び出し */
 while(1);              /* もしも、main 関数から戻ったら無限ループ */
}

void _INITSCT(void)
{
 int *p, *q;

 /*  zero clear  */
 for( p = _B_BGN; p < _B_END; p++)
  *p = 0;

 /*  ROM to RAM  */
 for( p = _D_BGN, q = _D_ROM; p < _D_END; p++, q++)
  *p = *q;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------

   < inita1.src >出力結果

;-------------------------------------------------------------------------------------------------------------------------------------------------------
; FILE NAME : INITA1.SRC
; INITA1.C のアセンブラソースファイル
; 設定確認用
    .FILE "C:\JROBO_WorkSpace\HEW_WSS\JR_cprog\cprog\main\inita1.c"
    .IMPORT __B_BGN
    .IMPORT __B_END
    .IMPORT __D_BGN
    .IMPORT __D_ROM
    .IMPORT __D_END
    .IMPORT _main
    .EXPORT _startup
    .EXPORT __INITSCT
    .SECTION PSTART,CODE,ALIGN=4
_startup:               ; function: startup
                   ; frame size=0
    .STACK _startup=0
    MOV.L L20+12,R15      ; STARTOF S+SIZEOF S
    MOV #-128,R2        ; H'FFFFFF80
    MOV.L L20+16,R1       ; H'0000A507
    MOV R1,R0
    MOV.W R0,@(6,R2)
    MOV #-128,R2        ; H'FFFFFF80
    MOV.W L20,R1        ; H'5A00
    MOV R1,R0
    MOV.W R0,@(4,R2)
    MOV #-128,R2        ; H'FFFFFF80
    MOV.L L20+20,R1      ; H'0000A101
    MOV.W R1,@R2
    MOV.W L20+2,R2      ; H'FF50
    MOV R2,R6
    MOV.L L20+24,R1      ; H'0000F00F
    MOV R1,R0
    MOV.W R0,@(16,R6)
    MOV R2,R6
    MOV.W L20+4,R1      ; H'1BF0
    MOV R1,R0
    MOV.W R0,@(18,R6)
    MOV R2,R6
    MOV.L L20+28,R1      ; H'0000BFF3
    MOV R1,R0
    MOV.W R0,@(20,R6)
    MOV.L L20+32,R1      ; H'0000FFD7
    MOV R1,R0
    MOV.W R0,@(22,R2)
    MOV R2,R6
    MOV.W L20+6,R1      ; H'516C
    MOV R1,R0
    MOV.W R0,@(24,R6)
    MOV R2,R6
    MOV.L L20+36,R1      ; H'0000A51C
    MOV #32,R0         ; H'00000020
    MOV.W R1,@(R0,R6)
    MOV R2,R6
    MOV.L L20+40,R1      ; H'0000A582
    MOV #34,R0         ; H'00000022
    MOV.W R1,@(R0,R6)
    MOV R2,R6
    MOV.L L20+44,R1      ; H'0000A400
    MOV #36,R0        ; H'00000024
    MOV.W R1,@(R0,R6)
    MOV R2,R6
    MOV.L L20+48,R1      ; H'0000A508
    MOV R1,R0
    MOV.W R0,@(30,R6)
    MOV #36,R0        ; H'00000024
    MOV.W @(R0,R2),R6
    MOV R6,R2
    EXTU.W R2,R2
    MOV #8,R1        ; H'00000008
    CMP/GE R1,R2
    BT L11
L12:
    MOV.W L20+2,R6      ; H'FF50
    MOV #36,R0        ; H'00000024
    MOV.W @(R0,R6),R2
    EXTU.W R2,R2
    MOV #8,R1         ; H'00000008
    CMP/GE R1,R2
    BF L12
L11:
    MOV.W L20+8,R2      ; H'D880
    MOV #0,R5         ; H'00000000
    MOV.B R5,@R2
    MOV #0,R6         ; H'00000000
    MOV.W L20+10,R2      ; H'E880
    MOV.B R6,@R2
    MOV.W L20+2,R2      ; H'FF50
    MOV R5,R0
    MOV.W R0,@(28,R2)
    MOV #0,R2         ; H'00000000
    MOV.L L20+52,R6      ; H'A4000000
    MOV R2,R0
    MOV.W R0,@(16,R6)
    MOV #-20,R2        ; H'FFFFFFEC
    MOV #8,R1         ; H'00000008
    MOV.L R1,@R2
    MOV #1,R2         ; H'00000001
    MOV #-20,R6        ; H'FFFFFFEC
    MOV.L R2,@R6
    BSR __INITSCT
    NOP
    MOV.L L20+56,R2      ; H'A0001000
    LDC R2,VBR
    MOV.L L20+60,R1      ; H'60000000
    MOV R1,R4
    LDC R4,SR
    MOV.L L20+64,R3      ; _main
    JSR @R3
    NOP
    MOV #1,R1         ; H'00000001
    MOV R1,R0
    CMP/EQ #0,R0
    BT L13
L14:
    MOV #1,R1         ; H'00000001
    MOV R1,R0
    CMP/EQ #0,R0
    BF L14
L13:
    RTS
    NOP
__INITSCT:             ; function: _INITSCT
    ; frame size=8
    .STACK __INITSCT=8
    ADD #-8,R15
    MOV.L L20+68,R1      ; __B_BGN
    MOV.L @R1,R7        ; _B_BGN
    MOV R7,R2
    MOV.L L20+72,R1      ; __B_END
    MOV.L @R1,R7        ; _B_END
    CMP/HS R7,R2
    BT L16
L17:
    MOV #0,R1         ; H'00000000
    MOV.L R1,@R2        ; *(p)
    ADD #4,R2
    MOV.L L20+72,R1      ; __B_END
    MOV.L @R1,R7        ; _B_END
    CMP/HS R7,R2
    BF L17
L16:
    MOV.L L20+76,R1      ; __D_BGN
    MOV.L @R1,R7        ; _D_BGN
    MOV R7,R2
    MOV.L L20+80,R1      ; __D_ROM
    MOV.L @R1,R7        ; _D_ROM
    MOV R7,R6
    MOV.L L20+84,R1      ; __D_END
    MOV.L @R1,R7        ; _D_END
    CMP/HS R7,R2
    BT L18
L19:
    MOV.L @R6+,R5       ; *(q)
    MOV.L R5,@R2        ; *(p)
    ADD #4,R2
    MOV.L L20+84,R1      ; __D_END
    MOV.L @R1,R7        ; _D_END
    CMP/HS R7,R2
    BF L19
L18:
    ADD #8,R15
    RTS
    NOP
L20:
    .DATA.W H'5A00
    .DATA.W H'FF50
    .DATA.W H'1BF0
    .DATA.W H'516C
    .DATA.W H'D880
    .DATA.W H'E880
    .DATA.L STARTOF S+SIZEOF S
    .DATA.L H'0000A507
    .DATA.L H'0000A101
    .DATA.L H'0000F00F
    .DATA.L H'0000BFF3
    .DATA.L H'0000FFD7
    .DATA.L H'0000A51C
    .DATA.L H'0000A582
    .DATA.L H'0000A400
    .DATA.L H'0000A508
    .DATA.L H'A4000000
    .DATA.L H'A0001000
    .DATA.L H'60000000
    .DATA.L _main
    .DATA.L __B_BGN
    .DATA.L __B_END
    .DATA.L __D_BGN
    .DATA.L __D_ROM
    .DATA.L __D_END
    .SECTION S,STACK,ALIGN=4
    .RES.B 1024
    .END _startup

;-------------------------------------------------------------------------------------------------------------------------------------------------------

   確認後は、設定を元に戻しておきます。
   出力ファイル形式は、「機械語プログラム(*.obj)」、デバッグ情報出力にチェックを入れる。