また,H8マイコンへのバイナリーデータ転送の面倒な処理もmakeでできる.このよ うにすることにより,諸君の作業は格段に楽になる.
この実験で使うMakefileには,次の機能がある.
1 TARGET = h8exp.mot 2 3 CFLAGS = -O -mh -g -mrelax -mint32 -DH8_3664 4 TOOL_PREFIX = h8300-hms- 5 CC = $(TOOL_PREFIX)gcc 6 7 LDSCRIPT = h8_link.x 8 CRT0 = h8_start.s 9 SRCS = experiment.c 10 FUNC = h8c.c 11 12 all : $(TARGET) 13 14 $(TARGET): $(TARGET:.mot=.exe) 15 $(TOOL_PREFIX)objcopy -O srec $(TARGET:.mot=.exe) $@ 16 17 $(TARGET:.mot=.exe): Makefile $(LDSCRIPT) $(SRCS:.c=.o) $(FUNC:.c=.o) \ 18 $(CRT0) $(LIBS) 19 $(CC) $(CFLAGS) -T $(LDSCRIPT) -nostdlib $(CRT0) \ 20 $(SRCS:.c=.o) $(FUNC:.c=.o) -o $@ $(LIBS) -lc -lgcc 21 22 write: 23 h8write -3664 $(TARGET) /dev/ttyS0 24 25 clean : 26 rm -f $(TARGET) 27 rm -f $(TARGET:.mot=.exe) 28 rm -f $(SRCS:.c=.o) 29 rm -f $(FUNC:.c=.o)
1 #ifndef H8C_H 2 #define H8C_H 3 4 #define _nop() asm volatile ("nop"); 5 6 void init_led(void); 7 void init_pwm(void); 8 void start_pwm(void); 9 void duty_pwm(unsigned int b, unsigned int d); 10 void ADC_init(void); 11 void ADC(void); 12 13 typedef union{ 14 unsigned char BYTE; 15 struct{ 16 unsigned char ADF:1; 17 unsigned char ADIE:1; 18 unsigned char ADST:1; 19 unsigned char SCAN:1; 20 unsigned char CKS:1; 21 unsigned char CH2:1; 22 unsigned char CH1:1; 23 unsigned char CH0:1; 24 }BIT; 25 }set_ADC; 26 27 int ch1, ch2, ch3, ch4; 28 29 #endif
1 #include "h8_3664.h" 2 #include "h8c.h" 3 4 5 //============================================================ 6 // LED点灯のための初期化関数 7 // Port5を使うときに最初,1回だけに呼び出す 8 // PDR5のビットの設定で,点灯するLEDを決める 9 //============================================================ 10 void init_led(void){ 11 PMR5 &= 0xc0; // Port Mode Register 5 の設定 12 // 0:汎用入出力 1:マニュアルを見よ 13 PCR5 |= 0x3f; // Port Control Register 5の設定 14 // 0:入力 1:出力 */ 15 PDR5 &= 0xc0; // Port Data Register 16 } 17 18 19 //============================================================ 20 // PWMを使うための初期化関数 21 // PWMを使うときに,最初1回呼び出す 22 //============================================================ 23 void init_pwm(void){ 24 TMRW |= 0x05; /* FTIOBとFTIOD端子をPWM出力に */ 25 26 TCRW |= 0x80; /* コンペアマッチAによりカウンタクリアー */ 27 TCRW |= 0x30; /* クロックセレクト 内部クロック phi/8 (=2MHz)*/ 28 TCRW |= 0x0a; /* タイマ出力セットレベル コンペアマッチまで1 */ 29 30 TCNT = 0x0000; /* カウンタ16ビットの初期値 */ 31 32 GRA = 0xffff; 33 34 } 35 36 37 //============================================================ 38 // PWMのDutyを決める 39 // 第一引数:FTIOB 第二引数:FTIOD 40 //============================================================ 41 void duty_pwm(unsigned int b, unsigned int d){ // pwm デューティ [%] 42 43 GRB = (unsigned int)655*b; 44 GRD = (unsigned int)655*d; 45 46 } 47 48 49 //============================================================ 50 // PWMのスタート時に呼び出す 51 //============================================================ 52 void start_pwm(void){ 53 TMRW |= 0x80; /* カウンタースタート */ 54 } 55 56 57 //============================================================ 58 // AD変換器の初期化関数 59 //============================================================ 60 void init_ADC(void) 61 { 62 63 set_ADC *set; 64 65 set=(set_ADC *)&ADCSR; 66 67 set->BIT.ADF=0; 68 set->BIT.ADIE=0; 69 set->BIT.ADST=0; 70 set->BIT.SCAN=1; 71 set->BIT.CKS=0; 72 set->BIT.CH2=0; 73 set->BIT.CH1=1; 74 set->BIT.CH0=1; 75 76 } 77 78 //============================================================ 79 // AD変換器を行い結果を設定 80 // ch1:AN0の結果 0:白 1:黒 81 // ch2:AN1の結果 0:白 1:黒 82 // ch3:AN2の結果 0:白 1:黒 83 // ch4:AN3の結果 0:白 1:黒 84 //============================================================ 85 void ADC(void) 86 { 87 88 ADCSR &=0x7f; // ADF=0 AD完了フラグをゼロに 89 ADCSR |= 0x20; // ADST=1 ADCスタート 90 91 while(!(ADCSR & 0x80)); // AD変換完了まで待つ 92 ADCSR &= 0xdf; // ADST=0 ADC stop 93 94 ch1=(unsigned int)(ADDRA >> 6)<200 ? 1:0; 95 ch2=(unsigned int)(ADDRB >> 6)<200 ? 1:0; 96 ch3=(unsigned int)(ADDRC >> 6)<200 ? 1:0; 97 ch4=(unsigned int)(ADDRD >> 6)<200 ? 1:0; 98 99 }
3-5行目がアセンブラで命令を記述している.マクロ名を指定することにで,アセンブラ の命令が実行される.簡単なアセンブラの命令を実行するときに便利である.
14-96行目でレジスターのアドレスを定義している.レジスター名--ここではマクロ名 になるが--とそれに対応するアドレスは,H8のマニュアルに書いてある.このようにす ると,無味乾燥な16進数のアドレスが意味のある名前に置き換えることができる.プログ ラムが書きやすくなる.コンパイル時にgccのプリプロセッサーがこのマクロ名を対応す る16進数に変換する.
レジスターとアドレスの関係は,ルネサステクノロジー社の「H8/3664グループハードウェ
アーマニュアル」 [3]に詳しく書かれている.
1 #ifndef H8_3664_H 2 #define H8_3664_H 3 #define STI() asm volatile ("andc.b #0x7f,ccr") 4 #define CLI() asm volatile ("orc.b #0x80,ccr") 5 #define SLEEP() asm volatile ("sleep") 6 7 #define VOLATILE_BYTE(addr) (*(volatile unsigned char*)(addr)) 8 #define VOLATILE_WORD(addr) (*(volatile unsigned short*)(addr)) 9 10 //====================================================================== 11 // Definitions of H8/3664 Internal Registers 12 // DO NOT EDIT! 13 //====================================================================== 14 #define TMRW VOLATILE_BYTE(0xff80) 15 #define TCRW VOLATILE_BYTE(0xff81) 16 #define TIERW VOLATILE_BYTE(0xff82) 17 #define TSRW VOLATILE_BYTE(0xff83) 18 #define TIOR0 VOLATILE_BYTE(0xff84) 19 #define TIOR1 VOLATILE_BYTE(0xff85) 20 21 #define TCNT VOLATILE_WORD(0xff86) 22 #define GRA VOLATILE_WORD(0xff88) 23 #define GRB VOLATILE_WORD(0xff8a) 24 #define GRC VOLATILE_WORD(0xff8c) 25 #define GRD VOLATILE_WORD(0xff8e) 26 27 #define FLMCR1 VOLATILE_BYTE(0xff90) 28 #define FLMCR2 VOLATILE_BYTE(0xff91) 29 #define FLPWCR VOLATILE_BYTE(0xff92) 30 #define EBR1 VOLATILE_BYTE(0xff93) 31 #define FENR VOLATILE_BYTE(0xff9b) 32 #define TCRV0 VOLATILE_BYTE(0xffa0) 33 #define TCSRV VOLATILE_BYTE(0xffa1) 34 #define TCORA VOLATILE_BYTE(0xffa2) 35 #define TCORB VOLATILE_BYTE(0xffa3) 36 #define TCNTV VOLATILE_BYTE(0xffa4) 37 #define TCRV1 VOLATILE_BYTE(0xffa5) 38 #define TMA VOLATILE_BYTE(0xffa6) 39 #define TCA VOLATILE_BYTE(0xffa7) 40 #define SMR VOLATILE_BYTE(0xffa8) 41 #define BRR VOLATILE_BYTE(0xffa9) 42 #define SCR3 VOLATILE_BYTE(0xffaa) 43 #define TDR VOLATILE_BYTE(0xffab) 44 45 #define SSR VOLATILE_BYTE(0xffac) 46 #define RDR VOLATILE_BYTE(0xffad) 47 48 #define ADDRA VOLATILE_WORD(0xffb0) 49 #define ADDRB VOLATILE_WORD(0xffb2) 50 #define ADDRC VOLATILE_WORD(0xffb4) 51 #define ADDRD VOLATILE_WORD(0xffb6) 52 #define ADCSR VOLATILE_BYTE(0xffb8) 53 #define ADCR VOLATILE_BYTE(0xffb9) 54 55 #define TCSRWD VOLATILE_BYTE(0xffc0) 56 #define TCWD VOLATILE_BYTE(0xffc1) 57 #define TMWD VOLATILE_BYTE(0xffc2) 58 #define ICCR VOLATILE_BYTE(0xffc4) 59 #define ICSR VOLATILE_BYTE(0xffc5) 60 #define ICDR VOLATILE_BYTE(0xffc6) 61 #define SARX VOLATILE_BYTE(0xffc6) 62 #define ICMR VOLATILE_BYTE(0xffc7) 63 #define SAR VOLATILE_BYTE(0xffc7) 64 #define ABRKCR VOLATILE_BYTE(0xffc8) 65 #define ABRKSR VOLATILE_BYTE(0xffc9) 66 #define BARH VOLATILE_BYTE(0xffca) 67 #define BARL VOLATILE_BYTE(0xffcb) 68 #define BDRH VOLATILE_BYTE(0xffcc) 69 #define BDRL VOLATILE_BYTE(0xffcd) 70 #define PUCR1 VOLATILE_BYTE(0xffd0) 71 #define PUCR5 VOLATILE_BYTE(0xffd1) 72 #define PDR1 VOLATILE_BYTE(0xffd4) 73 #define PDR2 VOLATILE_BYTE(0xffd5) 74 #define PDR5 VOLATILE_BYTE(0xffd8) 75 #define PDR7 VOLATILE_BYTE(0xffda) 76 #define PDR8 VOLATILE_BYTE(0xffdb) 77 #define PDRB VOLATILE_BYTE(0xffdd) 78 79 #define PMR1 VOLATILE_BYTE(0xffe0) 80 #define PMR5 VOLATILE_BYTE(0xffe1) 81 #define PCR1 VOLATILE_BYTE(0xffe4) 82 #define PCR2 VOLATILE_BYTE(0xffe5) 83 #define PCR5 VOLATILE_BYTE(0xffe8) 84 #define PCR7 VOLATILE_BYTE(0xffea) 85 #define PCR8 VOLATILE_BYTE(0xffeb) 86 #define SYSCR1 VOLATILE_BYTE(0xfff0) 87 #define SYSCR2 VOLATILE_BYTE(0xfff1) 88 #define IEGR1 VOLATILE_BYTE(0xfff2) 89 #define IEGR2 VOLATILE_BYTE(0xfff3) 90 #define IENR1 VOLATILE_BYTE(0xfff4) 91 #define IRR1 VOLATILE_BYTE(0xfff6) 92 #define IWPR VOLATILE_BYTE(0xfff8) 93 #define MSTCR1 VOLATILE_BYTE(0xfff9) 94 #define TSCR VOLATILE_BYTE(0xfffc) 95 96 #define EKR VOLATILE_BYTE(0xff10) 97 98 #endif
このスタートアップルーチンでは,まずはスタックポインターを設定している.リンカー スクリプトで設定されたスタック領域の先頭アドレス(_stack)をスタックポインター (sp)に設定している.次にROM 領域のデータをRAM領域に転送している.このように することにより,初期値がある変数に対応している.その後,リスト 1をmain関数に実行を移している.実際にはこのメイン関数 は機械語に翻訳され,ラベルは_mainとなる.ここでは,jsrでジャンプして いる.この_mainから戻るようなことがあると,無限ループに入るようにしている.
1 ;; H8/3664 Startup routine 2 3 .h8300h 4 .section .text 5 .global _start 6 _start: 7 mov.l #_stack,sp ;; スタックポインターの設定 8 9 ;; ROM領域のデータをRAMへ転送 10 11 mov.l #___dtors_end,er0 ;; .dtorsの終わりのアドレス 12 mov.l #___data,er1 ;; .dataの開始アドレス 13 mov.l #_edata,er2 ;; .dataの終わりのアドレス 14 ram_data: 15 mov.w @er0,r3 16 mov.w r3,@er1 17 adds #2,er0 18 adds #2,er1 19 cmp.l er2,er1 20 blo ram_data 21 22 ;; main関数の実行 23 24 jsr @_main 25 sleep: 26 sleep 27 bra sleep 28 29 .end
1 OUTPUT_FORMAT("coff-h8300") 2 OUTPUT_ARCH(h8300h) 3 ENTRY("_start") 4 MEMORY 5 { 6 vectors : o = 0x0000, l = 0x0034 7 rom : o = 0x0034, l = 0x7fcc 8 ram : o = 0xf780, l = 0x0400 9 stack : o = 0xff80, l = 0x0000 10 } 11 12 SECTIONS 13 { 14 .vectors : { 15 SHORT(ABSOLUTE(_start)) 16 SHORT(ABSOLUTE(_start)) 17 SHORT(ABSOLUTE(_start)) 18 SHORT(ABSOLUTE(_start)) 19 SHORT(ABSOLUTE(_start)) 20 SHORT(ABSOLUTE(_start)) 21 SHORT(ABSOLUTE(_start)) 22 SHORT(DEFINED(_int_nmi)?ABSOLUTE(_int_nmi):ABSOLUTE(_start)) 23 SHORT(DEFINED(_int_trap0)?ABSOLUTE(_int_trap0):ABSOLUTE(_start)) 24 SHORT(DEFINED(_int_trap1)?ABSOLUTE(_int_trap1):ABSOLUTE(_start)) 25 SHORT(DEFINED(_int_trap2)?ABSOLUTE(_int_trap2):ABSOLUTE(_start)) 26 SHORT(DEFINED(_int_trap3)?ABSOLUTE(_int_trap3):ABSOLUTE(_start)) 27 SHORT(DEFINED(_int_break)?ABSOLUTE(_int_break):ABSOLUTE(_start)) 28 SHORT(DEFINED(_int_sleep)?ABSOLUTE(_int_sleep):ABSOLUTE(_start)) 29 SHORT(DEFINED(_int_irq0)?ABSOLUTE(_int_irq0):ABSOLUTE(_start)) 30 SHORT(DEFINED(_int_irq1)?ABSOLUTE(_int_irq1):ABSOLUTE(_start)) 31 SHORT(DEFINED(_int_irq2)?ABSOLUTE(_int_irq2):ABSOLUTE(_start)) 32 SHORT(DEFINED(_int_irq3)?ABSOLUTE(_int_irq3):ABSOLUTE(_start)) 33 SHORT(DEFINED(_int_wkp)?ABSOLUTE(_int_wkp):ABSOLUTE(_start)) 34 SHORT(DEFINED(_int_timera)?ABSOLUTE(_int_timera):ABSOLUTE(_start)) 35 SHORT(ABSOLUTE(_start)) 36 SHORT(DEFINED(_int_timerw)?ABSOLUTE(_int_timerw):ABSOLUTE(_start)) 37 SHORT(DEFINED(_int_timerv)?ABSOLUTE(_int_timerv):ABSOLUTE(_start)) 38 SHORT(DEFINED(_int_sci3)?ABSOLUTE(_int_sci3):ABSOLUTE(_start)) 39 SHORT(DEFINED(_int_iic)?ABSOLUTE(_int_iic):ABSOLUTE(_start)) 40 SHORT(DEFINED(_int_adi)?ABSOLUTE(_int_adi):ABSOLUTE(_start)) 41 } > vectors 42 43 .text 0x0034 : { 44 *(.text) 45 *(.strings) 46 *(.rodata) 47 _etext = . ; 48 } > rom 49 50 .tors : { 51 ___ctors = . ; 52 *(.ctors) 53 ___ctors_end = . ; 54 ___dtors = . ; 55 *(.dtors) 56 ___dtors_end = . ; 57 } > rom 58 59 .data : AT ( ADDR(.tors) + SIZEOF(.tors) ){ 60 ___data = . ; 61 *(.data) 62 *(.tiny) 63 _edata = .; 64 } > rom 65 66 .bss : AT ( LOADADDR(.data) + SIZEOF(.data) ) { 67 _bss_start = . ; 68 *(.bss) 69 *(COMMON) 70 _end = . ; 71 } >ram 72 73 .stack : { 74 _stack = . ; 75 *(.stack) 76 } > stack 77 78 .stab 0 (NOLOAD) : { 79 [ .stab ] 80 } 81 82 .stabstr 0 (NOLOAD) : { 83 [ .stabstr ] 84 } 85 }