AKI-H8/3048のCクロスコンパイラ環境でのはじめてのプログラミング
GCC(cygwin)対応簡単コマンド利用版

Copyright(C)16Nov2003
coskx


1.はじめに
この文書は,Windows2000パソコンにAKI-H8/3048のC言語クロスコンパイル環境での,コンパイル作業のための方法を記述しています。あらかじめ指導者あるいはパソコン管理者が構築したC言語クロスコンパイラ環境で,C言語によるH8プログラミングを学ぼうとする方がプログラミングを行ない,AKI-H8/3048でプログラムが動作するまでを解説します。C言語のプログラミングについては別の文書で学んでください。基本的にcygwinフォルダ内にh8用のGCCの環境が出来ていれば,windowsのドラッグ&ドロップで作業できます。

サンプルプログラムのダウンロード(転送ソフトは含まれていません)

DownLoad

本文書で記述してある作業の特徴
Cプログラムソースファイルが出来上がったら,windows上で「xxxx.c」を「h8gcc.cmd」にドラッグアンドドロップするだけです。

前提
(1)Sygwinのシステムがc:\sygwinに導入されているものとします。
(2)Cygwinのシステムから「cygwin1.dll」,「cygiconv-2.dll」がwindowsのフォルダsystem32にコピーされているものとします。
(3)コンパイル用コマンド「H8gcc.cmd」は「各作業ファイル」に入っているものとします。
(4)gccの環境が整い,「C:\cygwin\usr\local\h8\bin」に「h8300-hms-coff-gcc」「h8300-hms-coff-objcopy」が置かれているものとします。もし設定が異なっていたら,コンパイル用コマンド「H8gcc.cmd」をカスタマイズします。
(5)転送ソフト「n-h8w.exe」かあるいは「h8write.exe」を利用します。ご自身でダウンロードして,gccコンパイラと同じフォルダに入れてください。

転送ソフト「h8w.exe」はシェアウェアですが10kバイトまではライセンスキー不要で書き込める転送ソフトです。
h8w.exeは,ライセンス登録作業を行なうと,標準でn-h8w.exeに名前が変わり,10kバイトの制限が外れます。この文書では名前が変わった場合の記述をしておりますが,ライセンス取得前の「h8w.exe」でも作業することが出来ますその場合はh8cc.cmd中の次の個所を変更してください。

変更前 rem フラッシュメモリ書き込みに使用するプログラムを指定します。
 set downloader=n-h8w.exe
変更後 rem フラッシュメモリ書き込みに使用するプログラムを指定します。
 set downloader=h8w.exe

なお,この書き込みソフトは(本校)情報工学科の前任助教授の前田先生が作成したものです。前田先生には大変お世話になっております。前田先生は別の名前をつけて使うように勧めていますが,作者に敬意をはらいまして,あえて標準のままにしておきした。
「h8w.exe」の取得はhttp://www.vector.co.jp/soft/win95/prog/se232247.htmlになります。


転送ソフト「h8write.exe」はみついわゆきお氏のオープンツールです。次の場所から入手できます。
http://mes.sourceforge.jp/h8/writer-j.html


注意
この文書で扱っているh8gcc.cmdはWindows2000,WindowsXP,WindowsVista,Windows7で使用可能です。
残念ながらWindows95/98では動作しません。

2.プログラムの作成から実行まで
シングルボードマイコンAKI-H8/3048内で動作するプログラムはパソコン上で開発され、シングルボードマイコンAKI-H8/3048にフラッシュメモリ書き込みされます。パソコンで開発されるソースプログラムはC言語で記述され、クロスコンパイラにより、オブジェクトプログラムに変換され、最後はフラッシュメモリ書き込み形式(xxxxxx.mot)になります。
シングルボードマイコンAKI-H8/3048を動作させるまでの大きな流れは以下のようになります。
(1)パソコン上で作業用のフォルダの用意
(2)パソコン上でCソースプログラムの作成
(3) パソコン上でフラッシュメモリ書き込み形式ファイル(実行プログラム)の作成(クロスコンパイル、コード変換)
(4)パソコン上の転送ソフトによる,フラッシュメモリ書き込み形式ファイル(実行プログラム)のAKI-H8/3048への書き込み操作
これら四つの作業によりシングルボードマイコン内で動作させることが出来ます。

3.テンプレートフォルダの実行
(1)図3.1に示すテンプレートフォルダでの実行の様子を確かめてみよう。(サンプルファイルのダウンロード


図3.1 小坂のテンプレートフォルダ

ファイル 内容
3048f.h レジスタのアドレス配置ヘッダファイル
h8_3048.h 小坂の標準ヘッダ
h8gcc.cmd コンパイルコマンド(PCの環境によって多少カスタマイズして下さい。)
startup.S スタートアップルーチンアッセンブリソース
h8_3048f.x リンカスクリプト
xxxxxx.c Cプログラム
to_H8.ht ハイパーターミナルファイル(ダブルクリックで起動)

(2)テンプレートフォルダがダウンロードできたら,解凍し,「xxxxxx.c」の内容をエディタで確かめてみてください。
プログラムは,AKI-H8/3048マザーボード上のLEDを点滅させるものです。プログラムの内容には深入りしないことにしましょう。

リスト プログラムソースファイル"xxxxxx.c"

/*  マザーボード上のLEDの1秒ごとのON-OFFを行う  */

#include "3048f.h"
#include "h8_3048.h"

void msecwait(int msec)
/*msec間なにもしない時間稼ぎ関数*/
{
    int i,j;
    for (i=0;i<msec;i++) {
        for (j=0;j<1989;j++);    /*1989は実測によって求めた値*/
    }
}
main()
{
    /*P5の下位2ビットを出力に設定*/
    /* P5のDDRの下位2ビットに1を与えるとこの設定になる*/
    /*DDRとはDataDirectionRegister(データ方向設定レジスタ)*/
    P5.DDR =  0x3;     /*0x3 = 00000011(二進数)*/
    while(1) {/*これは無限ループ*/
        /*LED0をONにする  P5のDRの第0ビットを1にする*/
        /*DRとはDataRegister(データレジスタ)*/
        P5.DR.BIT.B0=1;
        /*LED1をOFFにする  P5のDRの第1ビットを0にする*/
        P5.DR.BIT.B1=0;
        msecwait(1000);/*1000msecの間なにもしない*/
        /*LED0をOFFにする  P5のDRの第0ビットを0にする*/
        P5.DR.BIT.B0=0;
        /*LED1をONにする  P5のDRの第1ビットを1にする*/
        P5.DR.BIT.B1=1;
        msecwait(1000);
    }
}


(3)この後の作業は次のようになります。
ただし,図3.1のテンプレートフォルダは「デスクトップ」あるいは「マイドキュメント」の中にあるとします。

表3.1 フラッシュメモリ書き込み形式ファイルの作成とROMライター書き込み操作から実行までの手順

 

パソコン側

マイコンH8側
注意:H8は,電源スイッチONの瞬間に,状態選択スイッチの状態を検査しますので,必ず<1><2><3>の手順が必要です

(1)  

 <1>AKI-H8/3048のマザーボード上の電源スイッチをOFFにします。
<2>AKI-H8/3048のマザーボード上の状態選択スイッチをライト(Write)モードにします。ライトモードとはマイコンH8/3048がパソコンからプログラムコードを受け取り,フラッシュメモリに書き込むモードのことです。
<3>AKI-H8/3048のマザーボード上の電源スイッチをONにします。

(2)

「h8gcc.cmd」に「xxxxxx.c」をドラッグ&ドロップします。
うまく実行できると,フラッシュメモリ書き込みまで進みます。

(3)  

<1>転送が終了したら、AKI-H8/3048のマザーボード上の電源スイッチをOFFにします。
<2>AKI-H8/3048のマザーボード上の状態選択スイッチをラン(Run)モードにします。
<3>AKI-H8/3048のマザーボード上の電源スイッチをONにします。

(4)ここまでの作業が順調に出来ていたら,AKI-H8/3048マザーボード上の2つのLEDが点滅して動作が確認できるはずです。

4.新規プログラムの開発手順

4.1 パソコン上で作業用のフォルダの用意
作業準備は作業用フォルダを適当な場所に作る作業です。
作業用のフォルダを用意します。ここではled00という名前のフォルダを使用することにします。
その中には以下のファイルを用意しておきます。

ファイル 内容
3048f.h レジスタのアドレス配置ヘッダファイル
h8_3048.h 小坂の標準ヘッダ
h8gcc.cmd コンパイルコマンド
startup.S スタートアップルーチンアッセンブリソース
h8_3048f.x リンカスクリプト
to_H8.ht ハイパーターミナルファイル(ダブルクリックで起動)


これ以降の作業はすべてこのフォルダ内で行われます。

(テンプレートフォルダの複製を作ってフォルダ名をled00としてもよいでしょう)

4.2 プログラムの作成
Windowsマシン上のエディタ上で、C言語で記述されているソースプログラムを作成します。
例えばled00.cを作るという仮定で以下の説明にはいります。リストにあるファイルを作成してください。
このリストをコピー&ペーストするとよいでしょう。

リスト プログラムソースファイル"led00.c"

/*  マザーボード上のLEDの1秒ごとのON-OFFを行う  */

#include "3048f.h"
#include "h8_3048.h"

void msecwait(int msec)
/*msec間なにもしない時間稼ぎ関数*/
{
    int i;
    long int j;
    for (i=0;i<msec;i++) {
        for (j=0;j<33300;j++);    /*33300は実測によって求めた値*/
    }
}

main()
{
    /*P5の下位2ビットを出力に設定*/
    /* P5のDDRの下位2ビットに1を与えるとこの設定になる*/
    /*DDRとはDataDirectionRegister(データ方向設定レジスタ)*/
    P5.DDR =  0x3;     /*0x3 = 00000011(二進数)*/
    while(1) {/*これは無限ループ*/
        /*LED0をONにする  P5のDRの第0ビットを1にする*/
        /*DRとはDataRegister(データレジスタ)*/
        P5.DR.BIT.B0=1;
        /*LED1をOFFにする  P5のDRの第1ビットを0にする*/
        P5.DR.BIT.B1=0;
        msecwait(1000);/*1000msecの間なにもしない*/
        /*LED0をOFFにする  P5のDRの第0ビットを0にする*/
        P5.DR.BIT.B0=0;
        /*LED1をONにする  P5のDRの第1ビットを1にする*/
        P5.DR.BIT.B1=1;
        msecwait(1000);
    }
}

ここまでの作業でフォルダled00の中には

ファイル 内容
3048f.h レジスタのアドレス配置ヘッダファイル
h8_3048.h 小坂の標準ヘッダ
h8gcc.cmd コンパイルコマンド
startup.S スタートアップルーチンアッセンブリソース
h8_3048f.x リンカスクリプト
led00.c Cプログラム
to_H8.ht ハイパーターミナルファイル(ダブルクリックで起動)

ができているはずです。

4.3 フラッシュメモリ書き込み形式ファイルの作成とROMライター書き込み操作
Cプログラムソースファイル「led00.c」が出来ましたら,次の手順で実行してください。

表4.1 フラッシュメモリ書き込み形式ファイルの作成とROMライター書き込み操作から実行までの手順

 

パソコン側

マイコンH8側

(1) もしハイパーターミナルなどCOMポートを使用しているソフトがパソコン上で動作している時はそれらのソフトを中止します。  
(2)  

 

 

<1>AKI-H8/3048のマザーボード上の電源スイッチをOFFにします。
<2>AKI-H8/3048のマザーボード上の状態選択スイッチをライト(Write)モードにします。ライトモードとはマイコンH8/3048がパソコンからプログラムコードを受け取り,フラッシュメモリに書き込むモードのことです。
<3>AKI-H8/3048のマザーボード上の電源スイッチをONにします。
(注意:H8/3048は,電源スイッチONの瞬間に,状態選択スイッチの状態を検査しますので,必ず<1><2><3>の手順が必要です)
(3)

「h8gcc.cmd」に「xxxxxx.c」をドラッグ&ドロップします。
うまく実行できると,フラッシュメモリ書き込みまで進みます。

次のようなファイルができます。
ファイル 内容
led00.mot 転送形式の実行ファイル
led00.coff 実行ファイル
led00.map mapファイル

(4)   <1>転送が終了したら、AKI-H8/3048のマザーボード上の電源スイッチをOFFにします。
<2>AKI-H8/3048のマザーボード上の状態選択スイッチをラン(Run)モードにします。
(5) 必要ならパソコン側で「to_H8.ht」をダブルクリックしてターミナルアプリケーション「ハイパーターミナル」を立ち上げます。  
(6)   AKI-H8/3048のマザーボード上の電源スイッチをONにすると転送したプログラムが作動します。

注意(1) もしマルチソースファイルでのプログラミングの時は必要なソースファイルすべてを選択状態にし,「.mot」のファイル名にしたい「.c」ファイルを「h8gcc.cmd」へドラッグ&ドロップします。

なお「コンパイル−リンク−コンバート」作業における失敗時の画面例を以下に示します。

失敗例1 Cソースプログラムで文法エラーがあった時
(led01.cの11行目に宣言されていない変数jjがある)
(エラーメッセージでファイル名の次はエラー行番号!)

led00.c: In function `msecwait':
led00.c:11: `jj' undeclared (first use in this function)
led00.c:11: (Each undeclared identifier is reported only once
led00.c:11: for each function it appears in.)

失敗例2 リンクエラーがあった時
関数名が見つからない(関数名のミスタイプのことが多い)
ここでは「msecwait」を「msecwait11」とミスタイプ

/cygdrive/c/DOCUME~1/kosaka/LOCALS~1/Temp/ccKGXQZ4.o(.text+0xb6e):led00.c: undef
ined reference to `msecwait11'
collect2: ld returned 1 exit status
h8300-hms-coff-objcopy: led00.coff: No such file or directory

失敗例3 AKI-H8/3048のフラッシュメモリ書き込み受け入れ態勢が完全でない時
(AKI-H8/3048の電源が入っていない時)
(ライタモードになっていない時)
ウインドウが一瞬で消えてしまうので実際には見えない


h8w: synchronizing.....
  no response from cpu board

失敗例4 「ハイパーターミナル」などのシリアルポートを
利用しているソフトが動いていてフラッシュメモリ書き込みソフトが
シリアルポート(COMポート)を取得できない時
ウインドウが一瞬で消えてしまうので実際には見えない


comm open failed

4.4 プログラムの実行
「led00.mot」がマイコンにフラッシュメモリ書き込みされて,実行します。正常に作業が終えていれば,マザーボード上の2つのLEDが点滅します。


参考1 コマンドスクリプトファイルh8ccの内容

h8gcc.cmdの内容を参考リスト1に示します。

参考リスト1 motファイル作成用のコマンドスクリプトファイル「h8gcc.cmd」

@echo off
echo h8/30xx GCC compile-flashwrite(GCC)
echo Copyright 6Feb2006 20Nov2003 coskx

rem *************** カスタマイズ領域 begin *******************
rem ○コンパイラが入っているディレクトリ名をパスに追加します。○
rem コンパイラをコンパイルした時の設定に依存します。
set mypath=%HOMEDRIVE%\cygwin\usr\local\h8\bin
rem set mypath=%HOMEDRIVE%\cygwin\usr\local\h8300\bin

rem ○コンパイラファイル名の設定を行います。○
rem コンパイラをコンパイルした時の設定に依存します。
set mycompiler=h8300-hms-coff-gcc
rem set mycompiler=h8300-coff-gcc
rem set mycompiler=h8300-hms-gcc

rem ○motファイルコンバータファイル名の設定を行います。○
rem コンパイラをコンパイルした時の設定に依存します。
set myconverter=h8300-hms-coff-objcopy
rem set myconverter=h8300-coff-objcopy
rem set myconverter=h8300-hms-objcopy

rem ○リンカスクリプトファイル名を指定します○
set mylinkerscript.x=h8_3048f.x
rem set mylinkerscript.x=h8_3052f.x

rem ○フラッシュメモリ書き込みに使用するプログラムを指定します。○
set myFMwriter=n-h8w.exe
rem set myFMwriter=h8write.exe -3048
rem set myFMwriter=h8write.exe -3052

rem ○正常にダウンロードが終了した場合はそのまま終了する○
rem YES:そのまま終了する NO:そのまま終了せず停止
set downloadquit=YES
rem *************** カスタマイズ領域 end *******************

%~d1
cd %~p1
if %~x1==.mot goto FMWRITE
if %~x1==.MOT goto FMWRITE
path=%path%;%mypath%;%HOMEDRIVE%\cygwin\bin
if exist %~n1.coff rm %~n1.coff
echo %mycompiler%
%mycompiler% -mh -T %mylinkerscript.x% -nostartfiles startup.S %~nx1 %~nx2 %~nx3 %~nx4 %~nx5 -o %~n1.coff -O2 -Wall -Wl,-Map,%~n1.map
if not exist %~n1.coff goto TERMINAL
if exist %~n1.mot rm %~n1.mot
echo %myconverter%
%myconverter% -O srec %~n1.coff %~n1.mot
if not exist %~n1.mot goto TERMINAL
:FMWRITE
%myFMwriter% %~n1.mot
if ERRORLEVEL==0 goto TERMINAL0
goto TERMINAL
:TERMINAL0
pause
if %downloadquit%==YES goto LEXIT
:TERMINAL
echo Pushing any key leads the exit.
pause >nul
:LEXIT
exit

参考2 スタートアップルーチン「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






割り込みベクタは
リンカスクリプト
に書く











































割り込み許可関数
E_INT()の定義


割り込み禁止関数
D_INT()の定義

参考3 リンカスクリプト「h8_3048f.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 = 0x000100
    rom(rx)   :  o = 0x000100, l = 0x007f00
    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領域の次のアドレスに定義。
  この値はスタートアップルーチン内でスタックポインタ設定の
  ため使用される。
---------------------------------------------------------------*/

参考4 「start.S」「h8_3048f.x」の利用の利点

(1)初期化されたグローバル変数,および関数内の初期化されたstatic変数はRAM領域で使えるようにします。const修飾子を持つ初期化されたグローバル変数,およびconst修飾子を持つ関数内の初期化されたstatic変数はROM領域に割り当てられるようにします。
秋月電子通商で販売しているCコンパイラに付属している環境が与えるスタートアップルーチン(resetv.obj)では,このような変数の割り当てができていません。初心者が勉強するには不都合な環境です。初心者が通常のC言語の変数感覚でなにげなく使える環境を与えます。

参考5 「h8_3048.h」の利用の利点

(1)マザーボード上のスイッチ・LEDの制御関数をインクルードファイルで提供します。

(2)プログラムをフラッシュメモリ書き込みに用いた通信回線とWindowsマシンのハイパーターミナルを用いた表示環境を提供し,printf()に似た整数変数出力ルーチン,整数入力ルーチンをインクルードファイルで提供します。

(3)タイマ割り込み設定ルーチンでサポートします。



付録1 coffファイルの逆アッセンブル

ファイルrasm.batをダウンロードして

「rasm.bat」に「xxxxxx.coff」をドラッグ&ドロップする。

付録2 motファイルの逆アッセンブル

ファイルmotrasm.batをダウンロードして

「motrasm.bat」に「xxxxxx.mot」をドラッグ&ドロップする。

付録3 Cファイルのアッセンブルファイル出力

ファイルCtoAsm.batをダウンロードして

「CtoAsm.bat」に「xxxxxx.c」をドラッグ&ドロップすればよい。
その際,インクルードファイルは,読み込めるようにしておくこと。