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

Copyright(C) 5July2002
Copyright(C) 26Dec2001
coskx TNCT 

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

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

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

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

さらに初心者向けにタイマ割り込みをサポートするために
(1)ITU1のコンペアマッチ割り込みベクトルの設定    [G]
(2)割り込み割り込み関数のレジスタ退避部       [H]
(3)割り込み要因クリア                [I]
(4)割り込み割り込み関数のレジスタ復帰部       [J]

【2】本スタートアップルーチンの特徴
 (1)初期化されたグローバル変数,関数内static変数を,実行時にはRAMに割り当てて
    正常に動作させるようにしました。
 (2)ITU71のタイマ割り込みの利用をサポートします
 (3)関数main()から戻ってきても,無限ループに入るようにしました。
 (4)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.src」のソース

;************************************************************************
;startup routine    startup.src      Copyright (C) 2001 coskx
; 24 Dec 2003
; 14 Dec 2001
;************************************************************************
    .CPU 300HA

    .IMPORT _main, _interrupt_cfunc

    .EXPORT _E_INT,_D_INT

TIER1 .EQU H'FFFF70
TSR1 .EQU H'FFFF71
   
    .SECTION A,DATA,LOCATE=H'000000
RSTVEC: .DATA.L START       ;リセットベクトル

    .ORG H'000070  ;IMIA1
    .DATA.L ITU_I

;ITU1のIMIA割り込みを割り込みルーチンに送っておく

    .SECTION    P,CODE,ALIGN=2
START:
    MOV.L #H'FFF10,ER7 ;スタックポインタ設定

    ;move Section D to Section X
    MOV.L @_D_Head,ER0      ;source address to ER0
    MOV.L @_X_Head,ER1      ;destination address to ER1
    MOV.L @_D_Size,ER2      ;size to be copied to ER2
    OR.L ER2,ER2            ;(ER2 or ER2) to ER2
    JMP @LOOP_11
LOOP_1:
    MOV.B @ER0+,R3H         ;source byte to R3H with ER0++
    MOV.B R3H,@ER1          ;R3H to destination
    ADDS #1,ER1             ;increment destination address
    DEC.L #1,ER2            ;ER2--
LOOP_11:
    BNE LOOP_1

    ;fill 0 to Section B
    MOV.L @_B_Head,ER1      ;destination address to ER1
    MOV.L @_B_Size,ER2      ;size to be copied to ER2
    MOV.B #0,R3H            ;0 to R3H
    OR.L ER2,ER2            ;(ER2 or ER2) to ER2
    JMP @LOOP_21
LOOP_2:
    MOV.B R3H,@ER1          ;R3H to destination
    ADDS #1,ER1             ;increment destination address
    DEC.L #1,ER2            ;ER2--
LOOP_21:
    BNE LOOP_2

    JSR @_main        ; Call main()
EternalLoop: BRA EternalLoop ;万が一戻ってきてもOK

    .SECTION P,CODE,ALIGN = 2;
_E_INT: ANDC.B #B'01111111,CCR ;Clear Interrupt mask = Enable Interrupt
    RTS
    .SECTION P,CODE,ALIGN = 2;
_D_INT: ORC.B #B'10000000,CCR ;Set Interrupt mask = Disable Interrupt
    RTS

    .SECTION P,CODE,ALIGN = 2;
ITU_I: PUSH.L ER0
    PUSH.L ER1
    PUSH.L ER2
    PUSH.L ER3
    PUSH.L ER4
    PUSH.L ER5
    PUSH.L ER6

    BCLR #0,@TIER1 ;割り込み停止
    BCLR #0,@TSR1 ;Clear IMFA
   
    JSR @_interrupt_cfunc

    BSET #0,@TIER1 ;割り込み再開

    POP.L ER6
    POP.L ER5
    POP.L ER4
    POP.L ER3
    POP.L ER2
    POP.L ER1
    POP.L ER0
    RTE

; 割り込み停止,Clear IMFA,割り込み再開をここに書いておくことにより
; ユーザは割り込み処理内容だけに専念できる

    .SECTION    D,DATA,ALIGN=2
    .SECTION    X,DATA,ALIGN=2
    .SECTION    B,DATA,ALIGN=2

    .SECTION    C,DATA,ALIGN=2
_D_Head:   .DATA.L     (STARTOF D)     ; D Head Address
_X_Head:   .DATA.L     (STARTOF X)     ; X Head Address
_D_Size:   .DATA.L     (SIZEOF D)      ; D Size
_B_Head:   .DATA.L     (STARTOF B)     ; B Head Address
_B_Size:   .DATA.L     (SIZEOF B)      ; B Size
    .END
















[A]


[G]





[B]


[C]


























[D]



[E]


[F]


[H]








[I]






[J]



















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

【5】オブジェクトファイル「startup.obj」の作り方
次のコマンドで「startup.src」から「startup.obj」を作る。

>
a38h startup
H8/300H ASSEMBLER (Evaluation software) Ver.1.0
  *****TOTAL ERRORS       0
  *****TOTAL WARNINGS     0


【6】リンカオプションを記述したSUBファイルの例

小坂のコンパイルコマンドを用いると,標準AKI-H8/3052向けのSUBファイルは自動生成されるので意識して作成する必要はない。

OUTPUT xxxxxx
PRINT xxxxxx
INPUT xxxxxx
INPUT c:\Progra~1\h8\c\startup
LIB c:\Progra~1\h8\c\c38hab
ROM (D,X)
START P,C,D(100),X,B(0FDF10)
EXIT

「ROM (D,X)」の指示でSECTION DとSECTION Xが結び付けられる。

「START P,C,D(100),X,B(0FDF10)」では,セクションP,C,Dを0x100から連続して配置し,セクションX,Dを0xFDF10から連続して配置することを示している。

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

SECTION A............................アブソリュート領域(このスタートアップルーチンのみで使用)
SECTION P............................プログラム領域(Cで記述したプログラムのオブジェクトもここに入る)
SECTION C............................コンスタント領域(Cで記述したプログラムの,constのついたグローバル変数とconstのついたstatic変数はここに入る)
SECTION D............................データ領域(Cで記述したプログラムの,初期化されたグローバル変数のROM割り当て領域[初期化時にのみ使用される])
SECTION X............................データ領域(Cで記述したプログラムの,初期化されたグローバル変数のRAM割り当て領域[実行時にのみ使用される])
SECTION B............................データ領域(Cで記述したプログラムの,初期化されていないグローバル変数のRAM割り当て領域)