8.4 コーディング例

統合開発環境で生成される実際のスタートアッププログラムの例として、CPU種別としてRX610を選択したシミュレータ用の場合の例を示します。

(1)

ソースファイル

スタートアッププログラムは、表 8.5に示すファイルから構成されます。

表 8.5

統合開発環境で生成されるプログラムの一覧

 

ファイル名

内容

(a)

resetprg.c

初期設定ルーチン (リセットベクタ関数)

(b)

intprg.c

ベクタ関数の定義

(c)

vecttbl.c

固定ベクタテーブル*1

(d)

dbsct.c

セクションの初期化処理(テーブル)

(e)

lowsrc.c

低水準インタフェースルーチン(C言語部分)

(f)

lowlvl.src

低水準インタフェースルーチン(アセンブリ言語部分)

(g)

sbrk.c

低水準インタフェースルーチン(sbrk関数)

(h)

typedefine.h

型定義ヘッダ

(i)

vect.h

ベクタ関数のヘッダ

(j)

stacksct.h

スタックサイズの設定

(k)

lowsrc.h

低水準インタフェースルーチン(C言語ヘッダ)

(l)

sbrk.h

低水準インタフェースルーチン(sbrk関数のヘッダ)

注 1.

RXv1命令セットアーキテクチャの場合です。
RXv1命令セットアーキテクチャ以外の場合は、「例外ベクタテーブル」となります。

 

ファイル内容を、以下、(a)〜(l)に示します。

(a)

resetprg.c -- 初期設定ルーチン (リセットベクタ関数)

#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  "stacksct.h"            // Stack Sizes (Interrupt and User)
 
#ifdef __cplusplus                // For Use Reset vector
extern "C" {
#endif
void PowerON_Reset_PC(void);
void main(void);
#ifdef __cplusplus
}
#endif
 
#ifdef __cplusplus                // For Use SIM I/O
extern "C" {
#endif
extern void _INIT_IOLIB(void);
extern void _CLOSEALL(void);
#ifdef __cplusplus
}
#endif
 
#define PSW_init  0x00010000      // PSW bit pattern
#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_PC to PResetPRG section
 
#pragma entry PowerON_Reset_PC
 
void PowerON_Reset_PC(void)
{
#if (__RX_ISA_VERSION__ >= 2) || defined(__RXV2)
    set_extb(__sectop("EXCEPTVECT")); // Remove the comment when you want to set an address
                                    // into the Exception Vector Table Register of RXv2 or later
#endif
     set_intb(__sectop("C$VECT"));
#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_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();
 
//   _CALL_INIT();                // Remove the comment when you use global class object
 
     set_psw(PSW_init);           // Set Ubit & Ibit for PSW
//   chg_pmusr();                 // Remove the comment when you need to change PSW PMbit (SuperVisor->User)
 
     main();
 
     _CLOSEALL();                 // Use SIM I/O
 
//   _CALL_END();                 // Remove the comment when you use global class object
 
     brk();
}

 

(b)

intprg.c -- ベクタ関数の定義

#include <machine.h>
#include "vect.h"
#pragma section IntPRG
 
// Exception(Supervisor Instruction)
void Excep_SuperVisorInst(void){/* brk(); */}
 
// Exception(Undefined Instruction)
void Excep_UndefinedInst(void){/* brk(); */}
 
// Exception(Floating Point)
void Excep_FloatingPoint(void){/* brk(); */}
 
// NMI
void NonMaskableInterrupt(void){/* brk(); */}
 
// Dummy
void Dummy(void){/* brk(); */}
 
// BRK
void Excep_BRK(void){ wait(); }

(c)

vecttbl.c -- 固定ベクタテーブル

#include "vect.h"
 
#pragma section C FIXEDVECT
 
void (*const Fixed_Vectors[])(void) = {
//;0xffffffd0  Exception(Supervisor Instruction)
    Excep_SuperVisorInst,
//;0xffffffd4  Reserved
    Dummy,
//;0xffffffd8  Reserved
    Dummy,
//;0xffffffdc  Exception(Undefined Instruction)
    Excep_UndefinedInst,
//;0xffffffe0  Reserved
    Dummy,
//;0xffffffe4  Exception(Floating Point)
    Excep_FloatingPoint,
//;0xffffffe8  Reserved
    Dummy,
//;0xffffffec  Reserved
    Dummy,
//;0xfffffff0  Reserved
    Dummy,
//;0xfffffff4  Reserved
    Dummy,
//;0xfffffff8  NMI
    NonMaskableInterrupt,
//;0xfffffffc  RESET
//;<<VECTOR DATA START (POWER ON RESET)>>
//;Power On Reset PC
PowerON_Reset_PC
//;<<VECTOR DATA END (POWER ON RESET)>>
};

【ご参考】
RXv1命令セットアーキテクチャ以外を選択した場合 (例外ベクタテーブル)

#include "vect.h"
 
#pragma section C EXCEPTVECT
 
void (*const Excep_Vectors[])(void) = {
//;0xffffff80  Reserved
    Dummy,
//;0xffffff84  Reserved
    Dummy,
//;0xffffff88  Reserved
    Dummy,
//;0xffffff8c  Reserved
    Dummy,
//;0xffffff90  Reserved
    Dummy,
//;0xffffff94  Reserved
    Dummy,
//;0xffffff98  Reserved
    Dummy,
//;0xffffff9c  Reserved
    Dummy,
//;0xffffffa0  Reserved
    Dummy,
//;0xffffffa4  Reserved
    Dummy,
//;0xffffffa8  Reserved
    Dummy,
//;0xffffffac  Reserved
    Dummy,
//;0xffffffb0  Reserved
    Dummy,
//;0xffffffb4  Reserved
    Dummy,
//;0xffffffb8  Reserved
    Dummy,
//;0xffffffbc  Reserved
    Dummy,
//;0xffffffc0  Reserved
    Dummy,
//;0xffffffc4  Reserved
    Dummy,
//;0xffffffc8  Reserved
    Dummy,
//;0xffffffcc  Reserved
    Dummy,
//;0xffffffd0  Exception(Supervisor Instruction)
    Excep_SuperVisorInst,
//;0xffffffd4  Exception(Access Instruction)
    Excep_AccessInst,
//;0xffffffd8  Reserved
    Dummy,
//;0xffffffdc  Exception(Undefined Instruction)
    Excep_UndefinedInst,
//;0xffffffe0  Reserved
    Dummy,
//;0xffffffe4  Exception(Floating Point)
    Excep_FloatingPoint,

 

//;0xffffffe8  Reserved
    Dummy,
//;0xffffffec  Reserved
    Dummy,
//;0xfffffff0  Reserved
    Dummy,
//;0xfffffff4  Reserved
    Dummy,
//;0xfffffff8  NMI
    NonMaskableInterrupt,
};
 
#pragma section C RESETVECT
 
void (*const Reset_Vectors[])(void) = {
//;0xfffffffc  RESET
    PowerON_Reset_PC
};

 

(d)

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") }
};
#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 W0561100 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

(e)

lowsrc.c -- 低水準インタフェースルーチン(C言語部分)

#include <string.h>
#include <stdio.h>
#include <stddef.h>
#include "lowsrc.h"
 
#define STDIN  0
#define STDOUT 1
#define STDERR 2
 
#define FLMIN  0
#define _MOPENR   0x1
#define _MOPENW   0x2
#define _MOPENA   0x4
#define _MTRUNC   0x8
#define _MCREAT   0x10
#define _MBIN     0x20
#define _MEXCL    0x40
#define _MALBUF   0x40
#define _MALFIL   0x80
#define _MEOF     0x100
#define _MERR     0x200
#define _MLBF     0x400
#define _MNBF     0x800
#define _MREAD    0x1000
#define _MWRITE   0x2000
#define _MBYTE    0x4000
#define _MWIDE    0x8000
 
#define O_RDONLY  0x0001
#define O_WRONLY  0x0002
#define O_RDWR    0x0004
#define O_CREAT   0x0008
#define O_TRUNC   0x0010
#define O_APPEND  0x0020
 
#define CR 0x0d
#define LF 0x0a
 
extern const long _nfiles;
char flmod[IOSTREAM];
 
unsigned char sml_buf[IOSTREAM];
 
#define FPATH_STDIN     "C:\\stdin"
#define FPATH_STDOUT    "C:\\stdout"
#define FPATH_STDERR    "C:\\stderr"
 
extern void charput(unsigned char);
extern unsigned char charget(void);
 
#include <stdio.h>
FILE *_Files[IOSTREAM];
char *env_list[] = {
    "ENV1=temp01",
    "ENV2=temp02",
    "ENV9=end",
    '\0'
};
char **environ = env_list;
 
void _INIT_IOLIB( void )
{
    _Files[0] = stdin;
    _Files[1] = stdout;
    _Files[2] = stderr;
 
    if( freopen( FPATH_STDIN, "r", stdin ) == NULL )
        stdin->_Mode = 0xffff;
    stdin->_Mode  = _MOPENR;
    stdin->_Mode |= _MNBF;
    stdin->_Bend = stdin->_Buf + 1;
 
    if( freopen( FPATH_STDOUT, "w", stdout ) == NULL )
        stdout->_Mode = 0xffff;
    stdout->_Mode |= _MNBF;
    stdout->_Bend = stdout->_Buf + 1;
 
    if( freopen( FPATH_STDERR, "w", stderr ) == NULL )
        stderr->_Mode = 0xffff;
    stderr->_Mode |= _MNBF;
    stderr->_Bend = stderr->_Buf + 1;
}
 
void _CLOSEALL( void )
{
    long i;
    for( i=0; i < _nfiles; i++ )
    {
        if( _Files[i]->_Mode & (_MOPENR | _MOPENW | _MOPENA ) )
        fclose( _Files[i] );
    }
}
 
long open(const char *name,
     long  mode,
     long  flg)
{
 
    if( strcmp( name, FPATH_STDIN ) == 0 )
    {
        if( ( mode & O_RDONLY ) == 0 ) return -1;
        flmod[STDIN] = mode;
        return STDIN;
    }
    else if( strcmp( name, FPATH_STDOUT ) == 0 )
    {
        if( ( mode & O_WRONLY ) == 0 ) return -1;
        flmod[STDOUT] = mode;
        return STDOUT;
    }
    else if(strcmp(name, FPATH_STDERR ) == 0 )
    {
        if( ( mode & O_WRONLY ) == 0 ) return -1;
        flmod[STDERR] = mode;
        return STDERR;
    }
    else return -1;
 
long close( long fileno )
{
    return 1;
}
 
long write(long  fileno,
      const unsigned char *buf,
      long  count)
{
    long    i;
    unsigned char    c;
 
    if(flmod[fileno]&O_WRONLY || flmod[fileno]&O_RDWR)
    {
        if( fileno == STDIN ) return -1;
        else if( (fileno == STDOUT) || (fileno == STDERR) )
        {
            for( i = count; i > 0; --i )
            {
                c = *buf++;
                charput(c);
            }
            return count;
        }
        else return -1;
    }
    else return -1;
}
 
long read( long fileno, unsigned char *buf, long count )
{
	   long i;
       if((flmod[fileno]&_MOPENR) || (flmod[fileno]&O_RDWR)){
             for(i = count; i > 0; i--){
                   *buf = charget();
                   if(*buf==CR){
                         *buf = LF;
                   }
                   buf++;
             }
             return count;
       }
       else {
             return -1;
       }
}
 
long lseek( long fileno, long offset, long base )
{
    return -1L;
}

 

(f)

lowlvl.src -- 低水準インタフェースルーチン(アセンブリ言語部分)

         .GLB    _charput
         .GLB    _charget
 
SIM_IO   .EQU 0h
 
         .SECTION   P,CODE
;-----------------------------------------------------------------------
;  _charput:
;-----------------------------------------------------------------------
_charput:
         MOV.L      #IO_BUF,R2
         MOV.B      R1,[R2]
         MOV.L      #1220000h,R1
         MOV.L      #PARM,R3
         MOV.L      R2,[R3]
         MOV.L      R3,R2
         MOV.L      #SIM_IO,R3
         JSR        R3
         RTS
 
;-----------------------------------------------------------------------
;  _charget:
;-----------------------------------------------------------------------
_charget:
        MOV.L       #1210000h,R1
        MOV.L       #IO_BUF,R2
        MOV.L       #PARM,R3
        MOV.L       R2,[R3]
        MOV.L       R3,R2
        MOV.L       #SIM_IO,R3
        JSR         R3
        MOV.L       #IO_BUF,R2
        MOVU.B      [R2],R1
        RTS
 
;-----------------------------------------------------------------------
;  I/O Buffer
;-----------------------------------------------------------------------
         .SECTION  B,DATA,ALIGN=4
PARM:    .BLKL     1
         .SECTION  B_1,DATA
IO_BUF:  .BLKB     1
         .END

(g)

sbrk.c -- 低水準インタフェースルーチン(sbrk関数)

#include <stddef.h>
#include <stdio.h>
#include "typedefine.h"
#include "sbrk.h"
 
_SBYTE  *sbrk(size_t size);
 
//const size_t _sbrk_size=                /* Specifies the minimum unit of*/
                                          /* the defined heap area*/
 
extern _SBYTE *_s1ptr;
 
union HEAP_TYPE {
    _SDWORD  dummy ;                      /* Dummy for 4-byte boundary*/
    _SBYTE heap[HEAPSIZE];                /* Declaration of the area managed by sbrk*/
};
 
static union HEAP_TYPE heap_area ;
 
/* End address allocated by sbrk*/
static _SBYTE *brk=(_SBYTE *)&heap_area;
 
/**************************************************************************/
/*     sbrk:Memory area allocation                                        */
/*          Return value:Start address of allocated area (Pass)           */
/*                       -1                              (Failure)        */
/**************************************************************************/
_SBYTE  *sbrk(size_t size)                      /* Assigned area size   */
{
    _SBYTE  *p;
 
    if(brk+size > heap_area.heap+HEAPSIZE){     /* Empty area size      */
        p = (_SBYTE *)-1;
    }
    else {
        p = brk;                                /* Area assignment      */
        brk += size;                            /* End address update   */
    }
    return p;
}

(h)

typedefine.h -- 型定義ヘッダ

typedef signed char _SBYTE;
typedef unsigned char _UBYTE;
typedef signed short _SWORD;
typedef unsigned short _UWORD;
typedef signed int _SINT;
typedef unsigned int _UINT;
typedef signed long _SDWORD;
typedef unsigned long _UDWORD;
typedef signed long long _SQWORD;
typedef unsigned long long _UQWORD;

(i)

vect.h -- ベクタ関数のヘッダ

// Exception(Supervisor Instruction)
#pragma interrupt (Excep_SuperVisorInst)
void Excep_SuperVisorInst(void);
 
// Exception(Undefined Instruction)
#pragma interrupt (Excep_UndefinedInst)
void Excep_UndefinedInst(void);
 
// Exception(Floating Point)
#pragma interrupt (Excep_FloatingPoint)
void Excep_FloatingPoint(void);
 
// NMI
#pragma interrupt (NonMaskableInterrupt)
void NonMaskableInterrupt(void);
 
// Dummy
#pragma interrupt (Dummy)
void Dummy(void);
 
// BRK
#pragma interrupt (Excep_BRK(vect=0))
void Excep_BRK(void);
 
//;<<VECTOR DATA START (POWER ON RESET)>>
//;Power On Reset PC
extern void PowerON_Reset_PC(void);
//;<<VECTOR DATA END (POWER ON RESET)>>

(j)

stacksct.h -- スタックサイズの設定

// #pragma stacksize su=0x100        // Remove the comment when you use user stack
#pragma stacksize si=0x300

(k)

lowsrc.h -- 低水準インタフェースルーチン(C言語ヘッダ)

/*Number of I/O Stream*/
#define IOSTREAM 20

(l)

sbrk.h -- 低水準インタフェースルーチン(sbrk関数のヘッダ)

/* size of area managed by sbrk */
#define HEAPSIZE 0x400

(2)

実行コマンド

これらのファイルをビルドするのに必要なコマンド列の例を示します。

この例では、ユーザプログラム(main関数を含む)はUserProgram.c、生成するロードモジュールやライブラリなどのファイル名をLoadModule(拡張子を除いた部分)とします。

lbgrx -isa=rxv1 -output=LoadModule.lib
ccrx -isa=rxv1 -output=obj UserProgram.c
ccrx -isa=rxv1 -output=obj resetprg.c
ccrx -isa=rxv1 -output=obj intprg.c
ccrx -isa=rxv1 -output=obj vecttbl.c
ccrx -isa=rxv1 -output=obj dbsct.c
ccrx -isa=rxv1 -output=obj lowsrc.c
asrx -isa=rxv1 lowlvl.src
ccrx -isa=rxv1 -output=obj sbrk.c
rlink -rom=D=R,D_1=R_1,D_2=R_2 -list=LoadModule.map 
-start=B_1,R_1,B_2,R_2,B,R,SI/01000,PResetPRG/0FFFF8000,C_1,C_2,C,C$*,D_1,D_2,D,P,PIntPRG,
W*,L/0FFFF8100,FIXEDVECT/0FFFFFFD0 -=LoadModule.lib -output=LoadModule.abs
UserProgram.obj resetprg.obj intprg.obj vecttbl.obj dbsct.obj lowsrc.obj lowlvl.obj sbrk.obj
rlink -output=LoadModule.sty -form=stype -output=LoadModule.mot LoadModule.abs

【ご参考】
RXv2命令アーキテクチャを選択した場合のコマンド列の例を示します。

lbgrx -isa=rxv2 -output=LoadModule.lib
ccrx -isa=rxv2 -output=obj UserProgram.c
ccrx -isa=rxv2 -output=obj resetprg.c
ccrx -isa=rxv2 -output=obj intprg.c
ccrx -isa=rxv2 -output=obj vecttbl.c
ccrx -isa=rxv2 -output=obj dbsct.c
ccrx -isa=rxv2 -output=obj lowsrc.c
asrx -isa=rxv2 lowlvl.src
ccrx -isa=rxv2 -output=obj sbrk.c
rlink -rom=D=R,D_1=R_1,D_2=R_2 -list=LoadModule.map -start=B_1,R_1,B_2,R_2,B,R,SU,SI/04,PResetPRG/0FFFF8000,C_1,C_2,C,C$DSEC,C$BSEC,C$INIT,C$VTBL,C$VECT,D_1,D_2,D,P,PIntPRG,W_1,W_2,W,L/0FFFF8100,EXCEPTVECT/0FFFFFF80,RESETVECT/0FFFFFFFC -=LoadModule.lib -output=LoadModule.abs UserProgram.obj resetprg.obj intprg.obj vecttbl.obj dbsct.obj lowsrc.obj lowlvl.obj sbrk.obj
rlink -output=LoadModule.sty -form=stype -output=LoadModule.mot LoadModule.abs