H8/SH

Linux上でH8/36064の開発をする

準備

これひとつでビルドできます.(というかできるようにしました)
tokoro10g/h8300-toolchain-builder - GitHub

ただし,ビルド時間を少しでも短縮するために,h8300s,h8300sx向けのgcc,newlibは向こうにしてあります.詳しくは,patchesフォルダ内のgcc-4.4.6.patchをご覧ください.

シリアル経由の書き込みには,Open SH/H8 writerが便利です.
Open SH/H8 writer
が,サポートされているデバイスのリストの中に36064がないので,3664に書き込むモードで動作させます.したがって,何かしらおかしくなっても保証はできません.(問題なく動作することは確認できています.)

Open SH/H8 writerは,ソースコードを適当な作業フォルダにダウンロードして,

 gcc -O h8write h8write.c
 sudo cp ./h8write /usr/local/bin

のように,出てきたバイナリを/usr/local/binの中に突っ込んでおくと,どのディレクトリからも呼び出せるので便利です.(汚したくないという方は適当に/opt/toolsとかそのあたりにディレクトリを掘ってパスを通してください.)

Ubuntuの場合

ターミナルを開いて,

 sudo apt-get install git g++ autoconf texinfo=4.13a* gcc-multilib g++-multilib libncurses5-dev

で,必要なパッケージ類をインストールします.
次に,適当な作業フォルダに移動し,Githubからh8300-toolchain-builderをcloneします.

 mkdir -p ~/tmp
 cd ~/tmp
 git clone https://github.com/tokoro10g/h8300-toolchain-builder.git
 cd h8300-toolchain-builder

makeします.

 make
 sudo make install

ビルドには2時間ほどかかります.installまで終わったら準備完了です. ビルドしたツールチェインは,/opt/cross/h8300-elf-x-tools/ 以下のディレクトリに配置されます.

H8/36064向け開発の手引き

H8/36064は,H8/300HTinyシリーズのマイコンです. 適切なコンフィギュレーションでもってビルドしないとバグります.

h8300-toolchain-builderでは,h8300,h8300h向けのgcc(コンパイラ群)とnewlib(標準Cライブラリ)をビルドしています. また,h8300,h8300hそれぞれに対して,デフォルトモード,int32モード(intを16bitではなく32bitとして処理するモード),normalモード(後述),normalモードでのint32モードの4種類のコンフィギュレーションが用意されています.

H8/36064では,h8300hのnormalモードを使用します. このコンフィギュレーションは,

 -mh -mn

をフラグとしてgccに与えることで指定できます. その他細かい部分の設定は必要ですが,最も重要なのはこの項目です. 特に-mnを忘れると,マイコンとして動作はするものの一部機能だけがバグるといった厄介な現象が発生するため,忘れないようにしましょう.

その他の項目については,サンプルのMakefileを用意したので,こちらをご覧ください.
Makefile

リンカスクリプト

OUTPUT_FORMAT("elf32-h8300")
OUTPUT_ARCH(h8300hn)
ENTRY("_start")
MEMORY
{
        vectors : o = 0x0000, l = 0x0042
        rom     : o = 0x0042, l = 0x7fbe
        ram     : o = 0xf780, l = 0x0400
        stack   : o = 0xff80, l = 0x0000
}

SECTIONS
{
.vectors : {
    /* 0x0000 */
        SHORT(ABSOLUTE(_start))     /* 0(0x0000): _startの絶対アドレスをShortにして渡す*/
        SHORT(ABSOLUTE(_INT_Dummy)) /* 1(0x0002): システム予約*/
        SHORT(ABSOLUTE(_INT_Dummy)) /* 2(0x0004): システム予約*/
        SHORT(ABSOLUTE(_INT_Dummy)) /* 3(0x0006): システム予約*/
        SHORT(ABSOLUTE(_INT_Dummy)) /* 4(0x0008): システム予約*/
        SHORT(ABSOLUTE(_INT_Dummy)) /* 5(0x000A): システム予約*/
        SHORT(ABSOLUTE(_INT_Dummy)) /* 6(0x000C): システム予約*/
        SHORT(ABSOLUTE(_INT_NMI)) /* 7(0x000E): NMI*/
    /* 0x0010 */
        SHORT(ABSOLUTE(_INT_TRAP0)) /* 8(0x0010): CPU トラップ命令 #0*/
        SHORT(ABSOLUTE(_INT_TRAP1)) /* 9(0x0012): CPU トラップ命令 #1*/
        SHORT(ABSOLUTE(_INT_TRAP2)) /*10(0x0014): CPU トラップ命令 #2*/
        SHORT(ABSOLUTE(_INT_TRAP3)) /*11(0x0016): CPU トラップ命令 #3*/
        SHORT(ABSOLUTE(_INT_ABRK)) /*12(0x0018): アドレスブレーク ブレーク条件成立 */
        SHORT(ABSOLUTE(_INT_SLEEP)) /*13(0x001A): CPU スリープ命令の実行による直接遷移*/
        SHORT(ABSOLUTE(_INT_IRQ0)) /*14(0x001C): 外部割り込み端子 IRQ0 低電圧検出割り込み*/
        SHORT(ABSOLUTE(_INT_IRQ1)) /*15(0x001E): 外部割り込み端子 IRQ1*/
    /* 0x0020 */
        SHORT(ABSOLUTE(_INT_IRQ2)) /*16(0x0020): 外部割り込み端子 IRQ2*/
        SHORT(ABSOLUTE(_INT_IRQ3)) /*17(0x0022): 外部割り込み端子 IRQ3*/
        SHORT(ABSOLUTE(_INT_WKP)) /*18(0x0024): 外部割り込み端子 WKP*/
        SHORT(ABSOLUTE(_INT_Dummy)) /*19(0x0026): システム予約*/
        SHORT(ABSOLUTE(_INT_Dummy)) /*20(0x0028): 予約*/
        SHORT(ABSOLUTE(_INT_Dummy)) /*21(0x002A):*/
        SHORT(ABSOLUTE(_INT_TimerV)) /*22(0x002C): タイマV*/
        SHORT(ABSOLUTE(_INT_SCI3))   /*23(0x002E): SCI3*/
    /* 0x0030 */
        SHORT(ABSOLUTE(_INT_IIC2)) /*24(0x0030): IIC2*/
        SHORT(ABSOLUTE(_INT_ADI)) /*25(0x0032): A/D変換終了*/
        SHORT(ABSOLUTE(_INT_TimerZ0))   /*26(0x0034): タイマZ*/
        SHORT(ABSOLUTE(_INT_TimerZ1))    /*27(0x0036): Z*/
        SHORT(ABSOLUTE(_INT_Dummy)) /*28(0x0038):*/
        SHORT(ABSOLUTE(_INT_TimerB1)) /*29(0x003A): タイマB*/
        SHORT(ABSOLUTE(_INT_Dummy)) /*30(0x003C):*/
        SHORT(ABSOLUTE(_INT_Dummy)) /*31(0x003E):*/
    /* 0x0040 */
        SHORT(ABSOLUTE(_INT_SCI3_2)) /*32(0x0040): SCI3_2*/
        }  > vectors

.text 0x0042 : {
	___text = . ;
        *(.text)
         _etext = . ;
        } > rom

.rodata : {
	___rodata = . ;
        *(.strings)
        *(.rodata)
	*(.rodata.*)
	_erodata = . ;
	} > rom

.data : AT ( _erodata ){
        ___data = . ;
        *(.data)
        *(.tiny)
         _edata = .;
        } > ram

.bss : AT ( LOADADDR(.data) + SIZEOF(.data) ) {
         _bss_start = . ;
        *(.bss)
        *(COMMON)
         _end = . ;  
        }  >ram

.stack : {
         _stack = . ; 
        *(.stack)
        }  > stack

.stab 0 (NOLOAD) : {
        [ .stab ]
        }

.stabstr 0 (NOLOAD) : {
        [ .stabstr ]
        }
}

スタートアップファイル

 	.h8300hn
 	.section .text
 	.global	_start
 _start:
 	mov.w	#_stack,sp
 	mov.l	#_erodata,er0
 	mov.l	#___data,er1
 	mov.l	#_edata,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_start,er1
 	mov.l	#_end,er2
 	bra	.cldata1
 .cldata:
 	mov.b	r0h,@er1
 	adds	#1,er1
 .cldata1:
 	cmp.l	er2,er1
 	blo	.cldata
 ;
 	andc.b  #0x3f,ccr
 	jsr	@_PowerON_Reset
 
 ;	Endless
 _endless:
 	bra	_endless
 
 	.section .stack
 _stack:

Renesasの開発環境からのコードの移植

Renesasが用意しているHEWなどの開発環境からコードを移植する際は,組み込み関数に注意する必要があります.

組み込み関数とは,マイコンの低レベルなレイヤー(よりダイレクトにいじるレイヤー)に対して提供される関数群のことを指します. 例えば,H8の開発でよく用いるset_imask_ccr(int)関数がこれに該当します. Renesasのツールチェインでは,これらの関数はすでに定義されているのですが,gccを自分でビルドした場合は定義されていないため,そのまま使用することはできません. したがって,自分で定義する必要があります.

Renesasのツールチェインでは,組み込み関数はmachine.hに定義されています. このmachine.hをそのまま再利用できる形で進めて行きましょう.

HEWデフォルトで生成するコードから呼ばれるのは,set_imask_ccr(int)関数と,_builtin_sleep()関数のみですので,この2つについて処理を記述することとします. machine.hに以下の関数の定義をコメントアウトし,次の記述を追加すればよいでしょう.

 #define _builtin_set_imask_ccr(c) if(c){asm volatile ("orc.b #0x80,ccr");} else {asm volatile ("andc.b #0x7f,ccr");}
 #define _builtin_sleep() while(1)

あまりdefineマクロは使いたくないのですが・・・


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-09-29 (木) 23:42:30 (549d)