AKI-SH2/7045プログラミング
Renesas HEW SuperH 9.4.0
 利用版
High-performance Embedded Workshop

Copyright(C)23Sep2011
coskx

1.はじめに

この文書は,Windows7パソコンにAKI-SH2/7045のC言語クロスコンパイル環境での,コンパイル作業のための方法を記述している。
コンパイラシステムは,RenesasHEW(High-performance Embedded Workshop)SuperH9.4.0を使う。あらかじめ指導者あるいはパソコン管理者が標準構築したHEWがインストールされている環境で,AKI-SH2/7045でプログラムが動作するまでを解説する。C言語のプログラミングについては別の文書で学んでほしい。

図1.1 AKI-SH2/7045とマザーボード(山下)

本解説中で使用しているファイルのダウンロード

FilesForHewPrg.zip

本解説中で使用している作業フォルダのダウンロード
適当な場所に解凍し,中のSH7045.hwsをダブルクリックすると,HEWが起動し,ワークスペースが現れる。
ただし,解凍されて出てくるフォルダ名は「SH7045」なので,衝突させないこと。

SH7045.zip

2.本文書で記述してある作業の特徴

HEWは大きな規模の組み込みシステムを作成することを前提にして作られているようである。学習する為の小さなプログラムを作ろうとするとかなり大げさな作業となる。できるだけデフォルトの設定でコンパクトな作業ができるようにしている。
なお,途中でPCからマイコンにファイル転送するが,これには転送ソフト「h8w.exe」を使う。

「h8w.exe」はyamasan氏のオープンツールです。次の場所から入手できます。
http://ym3.plala.jp/yamasan/

適当な場所にインストールし,h8w.exeと同じフォルダ内にフォルダ「CTRL_MOT」があることを確認しておく。
次のようなCMDファイルを作成しておく。

goH8W7045.cmd (FilesForHewPrg.zipに収録)

rem カレントドライブ・カレントディレクトリへ移動
%~d1
cd %~p1

rem ★フラッシュメモリ書き込みに使用するプログラム
set downloader="C:\Program Files\h8v2\WRITER\H8W\h8w.exe"
rem ★フラッシュメモリ書き込みのためのCOMポート番号を設定します
set ComPortNumber=1

echo [AutoPgm] >myAutoPgm.ini
echo AutoStart=1 >>myAutoPgm.ini
echo AutoExit=1 >>myAutoPgm.ini
echo CtrlProgam=7045_F286_P384.MOT >>myAutoPgm.ini
echo ComPortNo=%ComPortNumber% >>myAutoPgm.ini
echo UserMotPath=%1 >>myAutoPgm.ini
echo on
%downloader% -GO .\myAutoPgm.ini
@echo off
del myAutoPgm.ini

ここで,★のついたところを,自分の環境に合わせる必要がある。
「h8w.exe」をフルパスで定義すること。


3.プログラムの作成から実行まで

シングルボードマイコンAKI-SH2/7045内で動作するプログラムはパソコン上で開発され、シングルボードマイコンAKI-SH2/7045のフラッシュメモリに書き込まれます。パソコンで開発されるソースプログラムはC言語で記述され、クロスコンパイラにより、オブジェクトプログラムに変換され、最後はフラッシュメモリ書き込み形式(XXXX.MOT)になる。
シングルボードマイコンAKI-SH2/7045を動作させるまでの大きな流れは以下のようになる。

(1)パソコン上でHEW作業用のワークスペースとプロジェクトを作る *1,*2
(2)パソコン上でHEWプロジェクト内のCソースプログラムの作成
(3) パソコン上でHEWのビルドコマンドでダウンロード形式ファイル(実行プログラム)の作成(クロスコンパイル、コード変換)
(4)パソコン上の転送ソフトによる,ダウンロード形式ファイル(実行プログラム)のAKI-SH2/7045への書き込み操作
これら四つの作業によりシングルボードマイコン内で動作させることが出来る。

*1 ワークスペース 作業用のフォルダのこと
*2 プロジェクト 1つのプログラムを作成するファイル群 ワークスペース内に作られる
   ワークスペース内に複数のプロジェクトを作ることもできるし,1ワークスペースに1プロジェクトという構成でもよい。

4.ワークスペース・プロジェクトの作成

HEWを起動すると,ワークスペースとプロジェクトの設定画面が次々と現れてくる。

(1)ワークスペースとプロジェクトの設定

SH7045というワークスペース内にLed1stというプロジェクトを設定したところ
フォルダの実体は,デフォルトでC:\WorkSpaceに作られるようになっている。
この場所にWorkSpaceというフォルダがなかったら,自分で作っておく必要がある。
ワークスペース名のフォルダC:\WorkSpace\SH7045が作られる。
ワークスペースはほかの場所に作ってもよい。

(2)CPUの設定

CPUシリーズは「SH2」,CPUタイプは「SH7045f」を設定する

(3)動作モード,アドレス空間の設定

Endian選択は「Big」を設定する

(4)自動生成ルーチンの選択

標準入出力ライブラリは使わないので,「I/Oライブラリ使用」チェックを外す
動的メモリ確保(malloc,callocなど)は当面しないが,ヒープメモリは64kbytesほど一応設定しておく。
(RAMは1Mbytesあるので,ぜいたくに使う。)
Cプログラムソースを作るのでmain関数を呼び出してもらう設定にしておく。
I/Oレジスタ定義(これは)は使用するのでチェックを付ける。
ハードウェアのセットアップでは,外部メモリを使う設定を行うので,Cプログラムソースを作ることにする。
そのほかのハードウェア設定は学習用のため,あとで自分で明示的にプログラムする。

ハードウェアのセットアップは,main関数呼び出し前に行うか,main関数内で行うか,2通りの考え方がある。
ここでは,外部メモリ設定はmain呼び出し前に行い,他の設定はmain関数内で行うことにする。

(5)ライブラリの使用

当面は使わないライブラリは消しておこう。

(6)これ以降は変更しないので,この段階で「完了」ボタンを押してよい。

「完了」ボタンを押すと,「概要」が表示されるので,そのまま「OK」を押す。

 

5.Workshopでの作業

ここでWorkshopが自動的に開く。
左側の「プロジェクトペイン」のところに,最初に命名したワークペース名「SH7045」とその中のプロジェクト「Led1st」が見える。

(1) debugはしないので,下図の右赤丸のところをdebugからreleaseに変更して,debug構成からrelease構成に変更する。

 

参考

この段階でプロジェクト「Led1st」内に自動で作られたファイルは,次の通り。

dbsct.c

各セクションのアドレスなどの変数定義。このファイルには手を付けない。

hwsetup.c ハードウェア設定。あとで外部メモリのための設定を記述する。

intprg.c

割り込み関数の定義をするファイル,割り込みの記述をこのファイルに書いてもよいが,
ユーザ用のCファイルに割り込み関数を書いて,このファイル内の対応する関数をコメントアウトしてもよい。

Led1st.c

ここにmain関数をはじめ,必要なプログラムを書く。

resetprg.c

マイコンに電源が投入されてから,mainを呼び出すまでのスタートアップルーチン。
mainから制御が戻ってきてもsleep関数を使って暴走しないようになっている。
このファイルには手を付けない。

sbrk.c メモリ割り当ての関数定義。このファイルには手を付けない。
vecttble.c ベクタテーブル。
iodefine.h I/Oの定義。
sbrk.h メモリ割り当ての関数定義のヘッダ。このファイルには手を付けない。

stacksct.h

スタックサイズの定義。このファイルには手を付けない。

typedefine.h

標準Cから拡張した型の定義。この定義を使った方が型宣言のあいまいさがなくなる。
このファイルには手を付けない。

vect.h ベクタテーブル。

(2) 外部メモリのための設定

AKI-SH2/7045は外部メモリ1Mbytesがついているが,これを使うための設定を行う。

左側のプロジェクトペインのところで,「hwsetup.c」をダブルクリックして開いて,次のように関数を書き換える。

リスト プログラムソースファイル"hwsetup.c"(FilesForHewPrg.zipに収録)

#include "iodefine.h"           //IOポートの定義ファイル HEWが自動生成

void HardwareSetup(void)
{

    #define D_BCR1    0x202f // CS0/CS2/CS3 are 16bit-bus,CS is 32 bit
    #define D_BCR2    0x5510 // wait 1 idle
    #define D_WCR1    0x0002 // CS0 is 2 wait, CS1-3 are 0 wait
    #define D_PACRH   0x5020 // WRHH WRHL DRAK0 are enable
    #define D_PACRL1  0x5550 // CK -RD -WRH -WRL -CS[1..0] are enable
    #define D_PBCR1   0x000a // A21/A20 are enable
    #define D_PBCR2   0xa005 // A19/A18/A17/16 are enable
    #define D_PCCR    0xffff // A15-0 are enable
    #define D_PDCRH1  0x5555 // D31-24 are enable
    #define D_PDCRH2  0x5555 // D23-16 are enable
    #define D_PDCRL   0xffff // D15-0 are enable
   
    P_BSC.BCR1.WORD=D_BCR1;
    P_BSC.BCR2.WORD=D_BCR2;
    P_BSC.WCR1.WORD=D_WCR1;
   
    P_PFC.PACRH.WORD = D_PACRH;
    P_PFC.PACRL1.WORD= D_PACRL1;
    P_PFC.PBCR1.WORD = D_PBCR1;
    P_PFC.PBCR2.WORD = D_PBCR2;
    P_PFC.PCCR.WORD  = D_PCCR;
    P_PFC.PDCRH1.WORD= D_PDCRH1;
    P_PFC.PDCRH2.WORD= D_PDCRH2;
    P_PFC.PDCRL.WORD = D_PDCRL;
}

(3) セグメントのアドレス割り付け

AKI-SH2/7045は外部メモリを持つため,変数領域をRAMに割り付ける。

ワークスペースの「ビルド」メニューの一番上の「SuperH RISC engine Standard Toolchain」を選ぶと,ダイアログが現れるので,「最適化リンカ」タブで,カテゴリを「セクション」,設定項目も「セクション」にして,アドレスの「編集」を行う。

次のダイアログで,0xFFFFF000を0x00400000に変更

次のようになればよい。なお,この段階でイクスポートすると,この設定がファイルになるので,別のプロジェクトで,この場面まで来たらインポートして,保存したファイルを読み出せば,この設定が簡単になる。

 

6.Cプログラミング

左側の「プロジェクトペイン」のところの「Led1st.c」をダブルクリックして開いて,中身をすべて消去して,下記のプログラムを書き込む。
(コピー&ペーストしてよい。)

リスト プログラムソースファイル"Led1st.c"(FilesForHewPrg.zipに収録)

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

#include "iodefine.h"           //IOポートの定義ファイル HEWが自動生成

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

int main(void)
{
    P_PFC.PEIOR.WORD |= 0x0a00; /* PEのHのbit8,bit10を出力に設定 */
    while(1){
        P_PE.DR.WORD |= 0x200; /*LED0の点灯*/
        P_PE.DR.WORD &= 0xf7ff; /*LED1の消灯*/
        msecwait(500);
        P_PE.DR.WORD &= 0xfdff; /*LED0の消灯*/
        P_PE.DR.WORD = 0x800; /*LED1の点灯*/
        msecwait(500);
    }
}

 

7.実行形式プログラムの転送形式ファイルのビルド

Cプログラムから実行形式プログラムを作り,さらに転送形式ファイルを作る。
Workshopのビルドメニューからビルドコマンドを選択すればよい。

左下に「Build Finished」が出てくる。
このとき「L1100 (W) Cannot find "C" specified in option "start"」のような警告が出てくるが,
使用していないセクションが見つからないと言っているだけなので,無視してよい。

 

8.転送形式ファイルの転送

転送形式ファイル「Led1st.mot」が,ワークスペースフォルダ「SH7045」内のプロジェクトフォルダ「Led1st」内のフォルダreleaseにある。
これを転送プログラムでマイコンのフラシュメモリに書き込み,実行する。

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

 

パソコン側

マイコンSH2/7045側

(1)  

SH2/7045のマザーボード上のモードスイッチを「Prog」側に倒してから電源スイッチをONにします。
電源LEDが点灯します。

重要 電源をONしてからモードスイッチを切り替えるという逆手順では動作しません。

(2)

転送形式ファイル「Led1st.mot」を最初に作成しておいたgoH8W7045.cmdにドラッグ&ドロップする。
h8w.exeの画面が開いて転送される。

 
(3)  

<1>転送が終了したら、マザーボード上の電源スイッチをOFFにします。
<2>モードスイッチをラン(Run)にしてから電源スイッチをONにします。
電源LEDが点灯します。

重要 電源をONしてからモードスイッチを切り替えるという逆手順では動作しません。

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

 

9.Workshopの終了と,再起動

Workshopを終了する。
終了した状態で,ワークスペースフォルダ「SH7045」を見ると。そのなかにプロジェクトフォルダ「Led1st」がある。
ワークスペースフォルダ「SH7045」内のファイル「SH7045.hws」をダブルクリックすると,Workshopが再起動する。
このときワークスペース「SH7045」がWorkshop上に開いている。
Led1st.cがエディタ上で開いているので,左下のLed1st.cのタグ上を右クリックして閉じておく。
「プロジェクトペイン」でLed1st.cをダブルクリックすると再びエディタで編集することができる。
最後に,ここではLed1st.cは閉じておこう。

 

10.新規プロジェクトの追加,サービス関数(sh_7045.h)の利用

ここでは,次の2つのことを行う。
A.新規プロジェクトLed2ndをワークスペースSH7045に追加すること
B.サービス関数定義が記述されたsh_7045.hの利用
  これを利用するとSH7045のポートに対する記述が隠ぺいされ,移植性の良いプログラミングができる。

注 新規プロジェクトは,別な新規ワークスペース上に作ることもできるが,それは「4.ワークスペース・プロジェクトの作成」ですでに述べた方法で作成できる。

(1)プロジェクトの構築

「8」で述べたように,ワークスペースフォルダ「SH7045」内のファイル「SH7045.hws」をダブルクリックすると,Workshopが再起動すると,ワークスペース「SH7045」がWorkshop上に開いている。
Led1st.cがエディタ上で開いている場合は,エディタ左下のLed1st.cのタグ上を右クリックして閉じておく。

「プロジェクトペイン」の一番上の「SH7045」はワークスペースを表している。
SH7045のところで,右クリックして「プロジェクトの挿入...」で,新規プロジェクトをワークスペース「SH7045」に追加することができる。
「4.ワークスペース・プロジェクトの作成」とおなじように,プロジェクトの設定画面が次々と現れてくる。

「4.(1)」のところで,ワークスペース名は「SH7045」そのままにし,プロジェクト名のみ「Led2nd」に設定し,ディレクトリ名はHEWが自動でつくるのに任せる。
「4.(2)」〜「4.(5)」までは全く同じ設定でよい。
設定が終わると,プロジェクト「Led2nd」が見えてくる。

「プロジェクトペイン」で,Led2ndの文字が強調されているが,ビルドを行うと,Led2ndがビルドされることを示している。
別な表現をすれば,Led2ndが作業対象になっているという意味だが,このことをアクティブプロジェクトと呼んでいる。
もし,Led1stをアクティブプロジェクトにしたければ,Led1stのところで右クリックし,「アクティブプロジェクトに設定」でよい。
元に戻すには,Led2ndのところで右クリックし,「アクティブプロジェクトに設定」でよい。

プロジェクトLed2ndがアクティブになっていることを確認して,
「5.(1)」〜「5.(3)」とおなじように,設定する。

(2) 「sh_7045.h」(小坂のサービス関数群)の利用

FilesForHewPrg.zipに収録されている「sh_7045.h」をWindows上で,プロジェクトフォルダ「Led2nd」にコピーする。
コピーしただけでは,Workshop上に反映されてこない。
「プロジェクトペイン」の「Led2nd」を右クリックして,「ファイルの追加...」でプロジェクトフォルダ「Led2nd」内の「sh_7045.h」を追加する。
「プロジェクトペイン」のLed2nd配下に「sh_7045.h」が見えてくる。

(3)Cプログラミング

「6」と同じように操作して,「Led2nd.c」を次の内容にする。

リスト プログラムソースファイル"Led2nd.c" (FilesForHewPrg.zipに収録)

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

#include "iodefine.h" //IOポートの定義ファイル HEWが自動生成
#include "sh_7045.h"  //サービス関数群の定義ファイル 小坂が作成したもの

void msecwait(int msec)
{
    int i,j;
    for (i=0;i<msec;i++) {
        for (j=0;j<7250;j++); /*7250は実測によって求めた値*/
    }
}

main()
{
    initLed();  /*LED初期化*/
    while(1) {
        turnOnLed(0); /*LED0のON*/
        turnOffLed(1); /*LED1のOFF*/
        msecwait(500);
        turnOnLed(1); /*LED1のON*/
        turnOffLed(0); /*LED0のOFF*/
        msecwait(500);
    }
}

 

「7.」と同じように,ビルドする。

「8.」と同じように,マイコンに転送し,LEDが点滅すれば成功。

 

11.割り込み処理(例外処理)の記述

ここでは,割り込み処理の記述についてのべる。

「10.」を参考に,新規プロジェクトint1stを作成する。

プロジェクトint1stがアクティブになっていることを確認して,「10(1)」〜「10(2)」まで作業を行う。


「6」と同じように操作して,「int1st.c」を次の内容にする。

リスト プログラムソースファイル"int1st.c" (FilesForHewPrg.zipに収録)

/**********************************************************
時間割り込みによってLEDのON-OFFを行う
**********************************************************/
#include "machine.h"  //低レベル関数ヘッダ   Renesasが提供 imask関連で使用
#include "vect.h"     //割り込み関数ヘッダ   INT_CMT1_CMI1が割り込み関数であることが定義
#include "iodefine.h" //IOポートの定義ファイル HEWが自動生成
#include "sh_7045.h"  //サービス関数群の定義ファイル 小坂が作成したもの

main()
{
    initLed();
    set_imask(14);                  //レベル15は割り込み許可
    initCMTInt(500000,1,15); /*500000μsec,CMT.ch1使用,割り込みレベル15*/
    startCMT1(); /* コンペアマッチタイマ1スタート */
    while(1);       /*なにもしないループ*/
}

/******************************************************
コンペアマッチタイマ割り込み関数
関数名はvecttbl.c,vect.h中で決められている
INT_CMT0_CMI0はコンペアマッチタイマch0の割り込み
INT_CMT1_CMI1はコンペアマッチタイマch1の割り込み
コンペアマッチフラッグのクリアを割り込み関数中で行なうこと
******************************************************/
void INT_CMT1_CMI1(void)
{
    static int tick=0;
    if (tick==1) {
        turnOnLed(0);
        turnOffLed(1);
    } else {
        turnOffLed(0);
        turnOnLed(1);
    }
    tick=1-tick;
    clearCMFlag1(); /* コンペアマッチフラッグのクリア */
}

説明

割り込み関数名はHEWが決めている。この関数名が割り込み関数であることは,
vect.h中に次のように記述されている。これは変更してはいけない。
148はCPUの割り込みベクタ番号である。

// 148 CMT1 CMI1
#pragma interrupt INT_CMT1_CMI1
extern void INT_CMT1_CMI1(void);

INT_CMT1_CMI1の割り込み関数は,HEWも自動で「intprg.c」に生成している(何もしない関数が書かれている)ため,
それを消さなければ,二重定義になってしまう。
そこで,プロジェクトペインのプロジェクトintist配下に「intprg.c」を修正する。
以下のようにvoid INT_CMT1_CMI1の定義をコメントアウトする。

変更前 // 148 CMT1 CMI1
void INT_CMT1_CMI1(void){/* sleep(); */}
変更後 // 148 CMT1 CMI1
//void INT_CMT1_CMI1(void){/* sleep(); */}

「7.」と同じように,ビルドする。

「8.」と同じように,マイコンに転送し,LEDが点滅すれば成功。