AKI-H8/3048用スタートアップルーチン
アセンブリソース「startup.S」

Copyright(C) 01Feb2004
Copyright(C) 26Dec2001
coskx TNCT 

【1】スタートアップルーチンアセンブリソース「startup。S」
 このスタートアップルーチンはAKI-H8/3048をWindowsマシンでクロスコンパイルして使用している環境で使用されているものです。

 スタートアップルーチンとは,マイコンの電源ONと同時に起動し,必要な処理を行なって,Cで記述された関数main()をcallするまでの作業を行なうプログラムです。

基本的なスタートアップルーチンの役割は
(1)スタックポインタの設定              [A]
(2)必要なROM領域のRAM領域変数へのコピー       [B]
  (これはリンカスクリプトと連動しています)
(3)関数main()の呼び出し                              [C]
です。

これに次のものを付け加えます。
(1)マシン語でないと記述できないCPU割り込み許可関数  [D]
(2)マシン語でないと記述できないCPU割り込み禁止関数  [E]

【2】本スタートアップルーチンの特徴
 (1)初期化されたグローバル変数,関数内static変数を,実行時にはRAMに割り当てて
    正常に動作させるようにしました。
 (2)関数main()から戻ってきても,無限ループに入るようにしました。
 (3)CPUのコントロールレジスタのCCRでの割り込みマスクビットのセット・リセット関数をCプログラムに提供します。
   E_INT()  割り込み許可
   D_INT()  割り込み禁止

【3】本スタートアップルーチンを利用した場合のプログラム中での変数の取り扱い
(1)初期化されていないグローバル変数 RAM領域
(2)初期化されたグローバル変数    RAM領域
(3)初期化された関数内static変数   RAM領域
(4)const修飾子のある初期化されたグローバル変数    ROM領域
(5)const修飾子のある初期化された関数内static変数   ROM領域
 オート変数はconst修飾語をつけてもスタック領域にセットされ,値の変更をコンパイラがチェックするだけです。(値をプログラム中で変更するとコンパイルエラーとなる。)

大きな定数表(配列)をグローバル変数で与えるときにはconst修飾子をつけるとROM領域に割り当てられ,少ないRAMしか持たないH8のRAM節約になることを意味します。(関数内で大きな定数表(配列)を与える場合はconst staticにすればよい。)

【4】スタートアップルーチン「startup.S」のソース

/*--------------------------------------------------------
 H8-3048F 用スタートアップルーチン startup.S
 27Dec2003 coskx
 16Nov2003 coskx
--------------------------------------------------------*/
    .h8300h

    .section .text
    .global _start

_start:
    /*スタックポインタの初期化*/
    mov.l    #_initial_stack_point,sp

    /*初期値のある書き換えデータ領域のコピー。ROM->RAM。*/
    mov.l    #_dataROM_begin,er0
    mov.l    #_dataRAM_begin,er1
    mov.l    #_dataRAM_end,er2
    bra .mvdata1
.mvdata:
    mov.b    @er0,r3h
    mov.b    r3h,@er1
    adds    #1,er0
    adds    #1,er1
.mvdata1:
    cmp.l    er2,er1
    blo      .mvdata

    /*初期値のない書き換えデータ領域のクリア*/
    mov.b    #0,r0h
    mov.l    #_bss_begin,er1
    mov.l    #_bss_end,er2
    bra      .cldata1
.cldata:
    mov.b    r0h,@er1
    adds     #1,er1
.cldata1:
    cmp.l    er2,er1
    blo      .cldata

    /*main()をコール*/
    jsr      @_main

    /*終了処理は無限ループ*/
_forever:
    bra     _forever

    .global _E_INT
    .global _D_INT
    .align 2
_E_INT:
    andc.b   #0x7f,ccr    /*Clear Interrupt mask = Enable Interrupt*/
    rts
    .align 2
_D_INT:
    orc.b    #0x80,ccr    /*Set Interrupt mask = Disable Interrupt*/
    rts

    .end













[A]


[B]

























[C]









[D]



[E]

H8/3048のモード7動作(AKI-H8/3048)でのアドレス空間は1Mbyteなので,16進数で5桁である。6桁表示の部分の上位1桁は無視される。

【5】リンクオプションを記述したリンカスクリプトファイル(h8_3048f.x)


標準AKI-H8/3048向けのリンカスクリプトファイル(.xファイル)には次のようにセクションのメモリ配置を記述する。

/*-------------------------------------------------
 H8-3048F 用リンカスクリプト    h8_3048f.x
  27Dec2003 coskx
  16Oct2003 coskx
-------------------------------------------------*/
OUTPUT_FORMAT("coff-h8300")
OUTPUT_ARCH(h8300h)
ENTRY("_start")

/*----              メモリマップ              ----*/
MEMORY
{
    vectors(r) : o = 0x000000, l = 0x0000ff
    rom(rx)   :  o = 0x000100, l = 0x01ff00
    ram(rw)   :  o = 0xffef10, l = 0x000ff0
    stack(rw) :  o = 0xffff0c, l = 0x000004
}

/*----            各セクション定義            ----*/

SECTIONS
{
    /*リセットベクタと割り込みベクタ等の設定*/
    /*-------------------------------------------------
    DEFINED(SYMBOL)は,SYMBOLが定義されていたら1,そうでなかったら0の意味
    DEFINED(SYMBOL)?address1:address2;はCで言う所の3項演算子
    先頭から4byteずつ割り込みベクタを定義している。
    ベクタ0はプログラムの起動pointが指定される。
    -------------------------------------------------*/
    .vectors : {
        LONG(ABSOLUTE(_start))  /*    vector#0 Reset vector */
        LONG(ABSOLUTE(_start))  /*    Reserved */
        LONG(ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(DEFINED(_int_nmi)?ABSOLUTE(_int_nmi):ABSOLUTE(_start))
        LONG(DEFINED(_int_trap0)?ABSOLUTE(_int_trap0):ABSOLUTE(_start))
        LONG(DEFINED(_int_trap1)?ABSOLUTE(_int_trap1):ABSOLUTE(_start))
   
        LONG(DEFINED(_int_trap2)?ABSOLUTE(_int_trap2):ABSOLUTE(_start))
        LONG(DEFINED(_int_trap3)?ABSOLUTE(_int_trap3):ABSOLUTE(_start))
        LONG(DEFINED(_int_irq0)?ABSOLUTE(_int_irq0):ABSOLUTE(_start))
        LONG(DEFINED(_int_irq1)?ABSOLUTE(_int_irq1):ABSOLUTE(_start))
        LONG(DEFINED(_int_irq2)?ABSOLUTE(_int_irq2):ABSOLUTE(_start))
        LONG(DEFINED(_int_irq3)?ABSOLUTE(_int_irq3):ABSOLUTE(_start))
        LONG(DEFINED(_int_irq4)?ABSOLUTE(_int_irq4):ABSOLUTE(_start))
        LONG(DEFINED(_int_irq5)?ABSOLUTE(_int_irq5):ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
   
        LONG(DEFINED(_int_wovi)?ABSOLUTE(_int_wovi):ABSOLUTE(_start))
        LONG(DEFINED(_int_cmi)?ABSOLUTE(_int_cmi):ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(DEFINED(_int_imia0)?ABSOLUTE(_int_imia0):ABSOLUTE(_start))
        LONG(DEFINED(_int_imib0)?ABSOLUTE(_int_imib0):ABSOLUTE(_start))
        LONG(DEFINED(_int_ovi0)?ABSOLUTE(_int_ovi0):ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(DEFINED(_int_imia1)?ABSOLUTE(_int_imia1):ABSOLUTE(_start))
        LONG(DEFINED(_int_imib1)?ABSOLUTE(_int_imib1):ABSOLUTE(_start))
   
        LONG(DEFINED(_int_ovi1)?ABSOLUTE(_int_ovi1):ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(DEFINED(_int_imia2)?ABSOLUTE(_int_imia2):ABSOLUTE(_start))
        LONG(DEFINED(_int_imib2)?ABSOLUTE(_int_imib2):ABSOLUTE(_start))
        LONG(DEFINED(_int_ovi2)?ABSOLUTE(_int_ovi2):ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(DEFINED(_int_imia3)?ABSOLUTE(_int_imia3):ABSOLUTE(_start))
        LONG(DEFINED(_int_imib3)?ABSOLUTE(_int_imib3):ABSOLUTE(_start))
        LONG(DEFINED(_int_ovi3)?ABSOLUTE(_int_ovi3):ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
   
        LONG(DEFINED(_int_imia4)?ABSOLUTE(_int_imia4):ABSOLUTE(_start))
        LONG(DEFINED(_int_imib4)?ABSOLUTE(_int_imib4):ABSOLUTE(_start))
        LONG(DEFINED(_int_ovi4)?ABSOLUTE(_int_ovi4):ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(DEFINED(_int_dend0a)?ABSOLUTE(_int_dend0a):ABSOLUTE(_start))
        LONG(DEFINED(_int_dend0b)?ABSOLUTE(_int_dend0b):ABSOLUTE(_start))
        LONG(DEFINED(_int_dend1a)?ABSOLUTE(_int_dend1a):ABSOLUTE(_start))
        LONG(DEFINED(_int_dend1b)?ABSOLUTE(_int_dend1b):ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
   
        LONG(ABSOLUTE(_start))
        LONG(ABSOLUTE(_start))
        LONG(DEFINED(_int_eri0)?ABSOLUTE(_int_eri0):ABSOLUTE(_start))
        LONG(DEFINED(_int_rxi0)?ABSOLUTE(_int_rxi0):ABSOLUTE(_start))
        LONG(DEFINED(_int_txi0)?ABSOLUTE(_int_txi0):ABSOLUTE(_start))
        LONG(DEFINED(_int_tei0)?ABSOLUTE(_int_tei0):ABSOLUTE(_start))
        LONG(DEFINED(_int_eri1)?ABSOLUTE(_int_eri1):ABSOLUTE(_start))
        LONG(DEFINED(_int_rxi1)?ABSOLUTE(_int_rxi1):ABSOLUTE(_start))
        LONG(DEFINED(_int_txi1)?ABSOLUTE(_int_txi1):ABSOLUTE(_start))
        LONG(DEFINED(_int_tei1)?ABSOLUTE(_int_tei1):ABSOLUTE(_start))
   
        LONG(DEFINED(_int_adi)?ABSOLUTE(_int_adi):ABSOLUTE(_start))
    }  > vectors /*ベクタ領域(0-0xff)に配置*/
       
   
    /*プログラム領域&参照のみのデータ領域*/
    .text : {
        *(.text) /*プログラム領域*/
        *(.rodata) /*コンスタント領域(read only)*/
        _dataROM_begin = . ; /* *1 */
    }  > rom /*rom領域に配置*/
   
    /*初期値を持つグローバル変数,スタティック変数領域*/
    .data : AT (_dataROM_begin) { /* *2 */
        _dataRAM_begin = . ;      /* *3 */
        *(.data)
         _dataRAM_end = . ;       /* *4 */
    }  > ram /*ram領域に配置*/

    /*初期値を持たないグローバル変数,スタティック変数領域*/
    .bss : {
         _bss_begin = . ;         /* *5 */
        *(.bss)
        *(COMMON)
         _bss_end = . ;           /* *6 */
    }  >ram /*ram領域に配置*/

    /*スタック領域*/
    .stack : {
         _initial_stack_point = . +4 ;      /* *7 */
         _stack = . ;
        *(.stack)
    }  > stack
}

/*---------------------------------------------------------------

*1 _dataROM_beginを.textを割り付けた直後のアドレス(rom領域)に定義
  この値はスタートアップルーチン内で変数コピーのため使用される。

*2 セクション.dataの変数をram領域に割り付けるが,初期値は_dataROM_begin
  の場所に置く (ATコマンドの作用)
 スタートアップルーチンでRAM領域の_dataにコピーするための仕掛け

*3 _dataRAM_beginを割付中のアドレスに定義。この値はスタートアップルー
  チン内で変数コピーのため使用される。

*4 _dataRAM_endを割付中のアドレスに定義。この値はスタートアップルー
  チン内で変数コピーのため使用される。

*5 _bss_beginを割付中のアドレスに定義。この値はスタートアップルー
  チン内で変数コピーのため使用される。

*6 _bss_endを割付中のアドレスに定義。この値はスタートアップルー
  チン内で変数コピーのため使用される。

*7 _initial_stack_pointをstack領域の次のアドレスに定義。
  この値はスタートアップルーチン内でスタックポインタ設定の
  ため使用される。
---------------------------------------------------------------*/

各セクションの意味は次の通り

.text............................プログラム領域(Cで記述したプログラムのオブジェクトもここに入る)
.text............................コンスタント領域(Cで記述したプログラムの,constのついたグローバル変数とconstのついたstatic変数はここに入る)
.data............................データ領域(Cで記述したプログラムの,初期化されたグローバル変数のRAM割り当て領域)

           [初期値は「AT」で指定されたアドレスすなわち.textの後ろに連続して配置される]
.bss............................データ領域(Cで記述したプログラムの,初期化されていないグローバル変数のRAM割り当て領域)