H8プログラミングメモ
by K.I
date 2006/02/14
Index
- 開発に必要な、H8のハードウェア、ソフトウェアについてのメモ
- H8独自の仕様や記述に関して、自分なりに推察したものを纏めたものなので、全て正しいかどうかは保障出来ない。
[top]
- H8はいろんなバリエーションがあるが、それぞれのコンパイラでの対応は不明
- しかし、H8をコアにして周辺を追加しただけの様なので、互換性はあるのではないかと思われる。
- 分割コンパイルに対応しているのは、HEWのみ
- このメモは特に断りのない限り、HEWのC/C++コンパイラでの記述方法の説明だが、H8で共通な部分もあると思われる。
- 日立(Renesas)標準の開発環境H8S,H8/300シリーズ C/C++ コンパイラパッケージ。
- GNUのgccをベースに作られたフリーの統合環境
- H8/3664F,H8/3687F,H8/3694F対応、H8/3048F,H8/3664Fフラッシュライタを含む
- しかし試したところでは、分割コンパイルは出来ない仕様のようだ。
- #includeでソースを分割出来ると思うが、簡単には移行出来ない。
- Cygwinとgccで、クロスコンパイラを構築して、
- Eclipse/CDTで、開発環境を作ることが出来るらしい。
http://hp.vector.co.jp/authors/VA022386/
- 秋月電子で販売している、H8/3048F,H8/3052F用のコンパイラ
[top]
- 1命令の実行には、2〜12ステート程度、最大24ステート1
- /RES端子が、lowになるとCPUの状態と、内蔵周辺モジュールのレジスタがクリアされる。
- 入出力状態の初期値は要注意!
- 動作中は、最低20ステートの間、lowにする必要がある。
- 24.4.6のパワーオンリセット回路特性で、リセット時間が明確に記述されていない.
- 動作中のリセットの規定から、電源が立ち上がってから20ステート以上必要ではないかと思われる。
- リセット端子は約100kでプルアップされており、Cの値を調節してリセット時間を決めるらしいが、リセット時間が明確には規定されていないので、適当に決めるしかなさそう。
- 起動時には、発振安定時間(trc)+待機時間
- 待機時間の設定は、SYSCR1 のSTS2〜STS0 ビットの設定値により選択
- スリープモード
- CPUが止まるだけ。システムクロック、周辺モジュールは動作している。
- スタンバイモード、ウォッチモード2
- システムクロック、周辺モジュールも停止。データは保持される。
- サブアクティブモード、サブスリープモード
- システムクロックが停止し、サブクロックで動作している状態?
#include <machine.h>
sleep();
- IRQ0〜5端子の入力信号で起動される。
- ISCRで、立上り/立下りのどちらのエッジで起動するか設定
- IERで、割込みの許可/不許可の設定
- IPRA7〜4ビットで、プライオリティの設定
- ISRに、割込みステータスが入る。プログラムでクリア可能
- 優先順位は、NMIの次に高い
- 16bitのインテグレーテッドタイマを5ch使用可能。
- 内部クロック、φ,φ/2,φ/4,φ/8
- 外部クロック、TCLKA、TCLKB、TCLKC、TCLKD
- コンペアマッチ、オーバーフローでの割込み
- TIERで割込みの許可/不許可の設定
- TSRに、割込みステータスが入る
- STR0〜4ビットで、タイマスタート/停止を設定
- TSNC0〜4ビットで、タイマの同期動作/独立動作を設定
1乗除演算が一番時間が掛かるようだ。
2ほぼ同等と思われ
[top]
型 | byte | 値の範囲 |
char | 1 | -128〜127 |
signed char | 1 | -128〜127 |
unsigned char | 1 | 0〜255 |
short | 2 | -32768〜32767 |
unsigned short | 2 | 0〜65535 |
int | 2 | -32768〜32767 |
unsigned int | 2 | 0〜65535 |
long | 4 | -2147483648〜2147483647 |
unsigned long | 4 | 0〜4294967295 |
- byteは unsigned char, wordは unsigned shortと同じ。
- H8に関しては、セクションの概念を理解しないとプログラム構造が理解出来ないようだ。
- セクションに関しては、実際のプログラムから推察した部分が多いので、記述内容は正しくない可能性があります。
- PCプログラムは、基本的にプログラムやデータは全てRAM上に置かれる。
- しかしH8のようなマイコンは、プログラムや定数はROM上に配置する。
- H8コンパイラは、メモリの用途別にセクションという単位に分けて、実メモリ上に配置するらしい。
- H8の場合、セクションに以下のような名前(デフォルト)を付けて、メモリ領域の種類を区別している。
セクション名 | 内容 | メモリ種別 | 備考 |
P | プログラム(Program) | ROM | |
C | 定数(Const) | ROM | |
D,R | 初期値を持つデータ(Data) | ROM,RAM | 初期値をROM(D)に格納、初期化でRAM(R)に転送 |
B | 初期値を持たないデータ | RAM | |
C$DSEC | Dsectionのアドレス | ROM | Dstart,Dend,Rstartのアドレス |
C$BSEC | Bsectionのアドレス | ROM | Bstart,Bendのアドレス |
S | スタック | RAM | |
- D→Rの転送は、標準ライブラリ'_INITSCT()'を呼出せば良いようだ。
- セクションの構成の変更は、ビルドメニュー→H8S,H8/300 Standard Toolchainを選び、
- 最適化リンカ-タブ→セクション-カテゴリ で、編集可能。
- 3048Fの場合、デフォルトは以下のようになっている。
アドレス | セクションのカテゴリ |
0x00000400 | PResetPRG |
| PIntPRG |
| |
0x00000800 | P |
| C |
| C$DSEC |
| C$BSEC |
| D |
| |
0x000FEF10 | B |
| R |
| |
0x000FFD00 | S |
- スタックサイズを指定すると、スタックエリアの最後がスタックポインタとして設定される。
#pragma stacksize 0X200 →スタックサイズを指定する。
- HEWの、プロジェクトメニュー→構成の編集でも、スタックの設定が可能。
種別 | 用途 |
ROM | 割込みベクタ |
| プログラム領域(P) |
| 定数領域(C) |
| Dsecのアドレス(C$DSEC) |
| Bsecのアドレス(C$BSEC) |
| 初期化データ領域(D) |
| |
RAM | 未初期化データ領域(B) |
| 初期化データ領域(R) |
| スタック領域(S) |
- ヒープ領域が何処になるのか不明→おそらくはRの領域の最後の方か?と思われる
- 3048Fのモード7の場合のメモリマップ割当ては以下のようになる。
フラッシュROM: 00000〜1FFFF(割込みベクタ:00000〜000FF)
内蔵RAM: FEF10〜FFF0F
I/Oポート: FFF1C〜FFFFF
[top]
- H8の動作モードは、MD2..MD0端子の状態で決まる。
モード設定 | MD2 | MD1 | MD0 | 内蔵ROM | 動作 |
モード1 | 0 | 0 | 1 | 無効 | ポート1,2,5がアドレスバス(最大1Mbyte)、8bitバス |
モード2 | 0 | 0 | 1 | 無効 | ポート1,2,5がアドレスバス(最大1Mbyte)、16bitバス |
モード3 | 0 | 0 | 1 | 無効 | ポート1,2,5,Aがアドレスバス(最大16Mbyte)、8bitバス |
モード4 | 0 | 0 | 1 | 無効 | ポート1,2,5,Aがアドレスバス(最大16Mbyte)、16bitバス |
モード5 | 0 | 0 | 1 | 有効 | ポート1,2,5がアドレスバス(最大1Mbyte)、8bitバス |
モード6 | 0 | 0 | 1 | 有効 | ポート1,2,5,Aがアドレスバス(最大16Mbyte)、8bitバス |
モード7 | 0 | 0 | 1 | 有効 | 内蔵メモリのみ使用(最大1Mbyte)、全てのポート使用可 |
- とりあえず、3048F-ONEの仕様
- FWE端子を 1に設定することで、オンボードプログラミングモードとなる。
- 当然、内蔵ROMが有効なモード5〜7で可能。
- フラッシュROMの書換え回数は100回までなので、注意が必要。
- ブートモード
- FWEを1,MD2を0に設定する。
- シリアルインターフェース SCI1からRAMへデータを書き込む
- フラッシュROMをクリアする
- FF300〜のプログラムを実行する。
- ユーザプログラムモード
- FWEを1、MD2を1に設定する。
- プログラムから、フラッシュROMを書換える
ROM D=R →ROM領域Dと同じ大きさで、Rを確保する
START P,C,D/400,R,B/20000 →P,C,Dを400から、R,Bを20000からメモリ上に割付
- 複数のRAMセクションを同一アドレスに割り当てたい時
- PAとPBを100番地から割当てる。PBはPAの後に続けて割当てられる。
START PA,PB:PC/100
- セクションの初期化
- 未初期化データ領域(B)をゼロに初期化
- RAM上の初期化データ領域(R)を、ROM上の初期化データ領域(D)の値で初期化する
_INITSCT();
- 未初期化データ領域も、ゼロに初期化されるので注意。
- gcc等では初期化された変数は、ROM領域に置かれてしまうらしい。
- そのため、RAMに置きたい変数は初期化してはいけない。
- Cで直接記述出来ないことについては、組込み関数になっている。
組込み関数 | 機能 | パラメータ |
set_imask_ccr | ccrの割込みマスクの設定 | 0: 割込み可とする |
| | 1: 割込み不可とする |
| | |
sleep | sleep状態に移行 | なし |
| | |
- volatile宣言した変数については、コンパイラの最適化が行われない。
- 割込み処理で、変更される可能性のある変数は、volatile宣言すべき。
- メインプログラム中で変更されていない場合、コンパイラの最適化で思ったような動作をしない可能性がある。
- まず個別の割込み要因毎に、割込みフラグを許可する。
- HEWの場合は、全体の割込み許可を、set_imask_ccr()で行う。
- gccの場合は、以下のようなマクロをインラインアセンブラで作ると良い。
#define STI() asm volatile ("andc.b #0x7f,ccr") //割込み許可
#define CLI() asm volatile ("orc.b #0x80,ccr") //割込み禁止
[top]
- HEWのC/C++コンパイラの独自の記述方法については、多くの場合、#pragmaを使って指定する。
- 最初に実行される関数。実質的なメインルーチンの指定。
#pragma section PowerON_Reset
#pragma entry PowerON_Reset(vect=0)
void PowerON_Reset(void) {
:
main();
:
}
- 関数名は、PowerON_Resetにする必要はないと思う。
- vectは常にゼロである必要があると思うので、指定出来るようになっている理由は不明。
#pragma interrupt (int_func(vect=25))
int_func(void) {
:
}
- ほとんどエントリ関数の指定と同様。
- というよりエントリ関数も実質上は割込みベクタなので、その後に続けて定義する。
- スタックサイズを指定すると、スタックエリアの最後がスタックポインタとして設定される。
#pragma stacksize 0X200 →スタックサイズを指定する。
- スタックサイズしか指定しないが、スタートはBセクションの最後になるのか?
- spの初期値とスタックサイズから、逆算することは出来る。
- HEWの、プロジェクトメニュー→構成の編集でも、スタックの設定が可能。
- 構造体のメンパにポインタで直接アクセスしたい場合は、ワード境界にあわせる必要がある。
[top]
[top]
[電子工作関連に戻る]