8.2.6 RAM領域セクションの初期化処理

初期値を持つ領域である“data属性”領域へ初期値のコピーと,初期値を持たない領域である“bss属性”領域のゼロ・クリアを行います。プログラム実行前に初期化するべき領域がない場合,本処理は必要ありません。

 

最初に,最適化リンカの-romオプションで初期値データの生成を指示し,コピー先のRAM領域セクションを定義します。詳細は「8.4 ROMイメージの作成」を参照してください。

定義したRAM領域セクションを,スタートアップ・ルーチン内に次のように記述します。

.SECTION        .dataR, DATA
.SECTION        .sdataR, DATA

 

次に,スタートアップ・ルーチン内で,bss 属性の領域を初期化するコードを記述します。

セクション.bss,.sbss を0 初期化する場合,次のように記述します。

        ; clear external variables which doesn't have initial value (near)
        MOVW    HL,#LOWW(STARTOF(.bss))
        MOVW    AX,#LOWW(STARTOF(.bss) + SIZEOF(.bss))
        BR      $.L2_BSS
.L1_BSS:
        MOV     [HL+0],#0
        INCW    HL
.L2_BSS:
        CMPW    AX,HL
        BNZ     $.L1_BSS
 
        ; clear saddr variables which doesn't have initial value
        MOVW    HL,#LOWW(STARTOF(.sbss))
        MOVW    AX,#LOWW(STARTOF(.sbss) + SIZEOF(.sbss))
        BR      $.L2_SBSS
.L1_SBSS:
        MOV     [HL+0],#0
        INCW    HL
.L2_SBSS:
        CMPW    AX,HL
        BNZ     $.L1_SBSS

 

次に,スタートアップ・ルーチン内で,data属性の領域をRAM領域セクションにコピーするコードを記述します。

セクション.data,.sdataをそれぞれ.dataR,.sdataRにコピーする場合,次のように記述します。このコピールーチンは,64Kbyte境界をまたぐセクションについては対応していないので注意してください。

        ; copy external variables having initial value (near)
        MOV     ES,#HIGHW(STARTOF(.data))
        MOVW    BC,#LOWW(SIZEOF(.data))
        BR      $.L2_DATA
.L1_DATA:
        DECW    BC
        MOV     A,ES:LOWW(STARTOF(.data))[BC]
        MOV     LOWW(STARTOF(.dataR))[BC],A
.L2_DATA:
        CLRW    AX
        CMPW    AX,BC
        BNZ     $.L1_DATA
 
        ; copy saddr variables having initial value
        MOV     ES,#HIGHW(STARTOF(.sdata))
        MOVW    BC,#LOWW(SIZEOF(.sdata))
        BR      $.L2_SDATA
.L1_SDATA:
        DECW    BC
        MOV     A,ES:LOWW(STARTOF(.sdata))[BC]
        MOV     LOWW(STARTOF(.sdataR))[BC],A
.L2_SDATA:
        CLRW    AX
        CMPW    AX,BC
        BNZ     $.L1_SDATA

 

RAM領域セクションへの0初期化,およびコピー処理は,C言語で作成しスタートアップ・ルーチンから呼ぶこともできます。

        ; initializing RAM section
        CALL    !!_INITSCT_RL

 

C言語でのRAM領域セクション初期化関数の例を以下に示します。

#define BSEC_MAX        2               /*0初期化するBSSセクションの数*/
#define DSEC_MAX        2               /*コピーするDATAセクションの数*/
 
const struct bsec_t {
        char __near *ram_sectop;        /*セクション先頭アドレス*/
        char __near *ram_secend;        /*セクション末尾アドレス+1*/
} bsec_table[BSEC_MAX] = {
        {(char __near *)__sectop(".bss"),
         (char __near *)__secend(".bss")},
        {(char __near *)__sectop(".sbss"),
         (char __near *)__secend(".sbss")}};
 
const struct dsec_t {
        char __far *rom_sectop;         /*コピー元セクション先頭アドレス*/
        char __far *rom_secend;         /*コピー元セクション末尾アドレス+1*/
        char __near *ram_sectop;        /*コピー先セクション先頭アドレス*/
} dsec_table[DSEC_MAX] = {
        {__sectop(".data"),
         __secend(".data"),
         (char __near *)__sectop(".dataR")},
        {__sectop(".sdata"),
         __secend(".sdata"),
         (char __near *)__sectop(".sdataR")}};
 
void INITSCT_RL(void)
{
        unsigned int i;
        char __far *rom_p;
        char __near *ram_p;
 
        for (i = 0; i < BSEC_MAX; i++) {
                ram_p = bsec_table[i].ram_sectop;
                for ( ; ram_p != bsec_table[i].ram_secend; ram_p++) {
                        *ram_p = 0;
                }
        }
        for (i = 0; i < DSEC_MAX; i++) {
                rom_p = dsec_table[i].rom_sectop;
                ram_p = dsec_table[i].ram_sectop;
                for ( ; rom_p != dsec_table[i].rom_secend; rom_p++, ram_p++) {
                        *ram_p = *rom_p;
                }
        }
}