Post on 10-Apr-2018
プログラムのROM化
エディタ ソース
ファイル ソース
ファイル ソース
ファイル
コンパイラ
リンカ
オブジェクト
ファイル
ライブラリ
書込用
ファイル
変換
プログラム
エラー
リスト
エラー
リスト
実行モジュール
(ロードモジュール)
インテルHex
モトローラS
など
書き込みツール ターゲットシステム
ターゲットシステムのROMへ書き込む
プログラムのROM化
• コンパイル
– ソースプログラムをCPU(MPU)の命令に翻訳して,機械語(オブジェクトプログラム)を生成する
– コンパイラはプログラムの各部分を属性により,コード部,データ部,スタック部などに分ける
– コンパイルした時,命令のアドレスは仮のアドレスが振られている
• リンカ
–複数のオブジェクトやライブラリを結合して,実行モジュールを生成する
–各モジュールにおける命令のアドレスはリンク作業によりアドレスの調整が行われ,アドレスの再配置(リロケーション)が行われる
プログラムのROM化
#include <stdio.h>
main()
{
printf("hello, world¥n");
}
CGROUP GROUP TEXT
DGROUP GROUP DATA,BSS
TEXT CSEG
0000
0000 DATA DSEG
0000
0000 BSS DSEG
0000
0000
0000 TEXT CSEG
0000 ; #include <stdio.h>
0000 ; main()
0000
0000 main_::
0000 ; {
0000 ; printf("hello, world¥n");
0000 B80000 MOV AX,Z1
0003 50 PUSH AX
0004 E80000 CALL printf_
0007 83C402 ADD SP,2
000A ; }
000A C3 RET
000B
000B
000B DATA DSEG
0000 EVEN
0000 68 Z1: DB 104 (h)
0001 65 DB 101 (e)
0002 6C DB 108 (l)
0003 6C DB 108 (l)
0004 6F DB 111 (o)
0005 2C DB 44 (,)
0006 20 DB 32 ( )
0007 77 DB 119 (w)
0008 6F DB 111 (o)
0009 72 DB 114 (r)
000A 6C DB 108 (l)
000B 64 DB 100 (d)
000C 0A DB 10 (¥n)
000D 00 DB 0
000E
000E EXTRN printf_
000E
000E
000E ;core used: 1123/35648
000E
000E END
Z1のアドレスは0000.つまりまだ確定してない
printfのアドレスは0000.つまりまだ確定してない リンクによりアドレスを再配置(確定)させる
プログラムのROM化
00000000 : 4D 5A C1 01 02 00 00 00 20 00 01 00 FF FF 00 00 : MZ...... ....... 00000010 : 00 00 65 7D 00 00 00 00 1E 00 00 00 01 00 00 00 : ..e}............ 00000020 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 000001F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 00000200 : B8 96 03 50 E8 F9 FF 83 C4 02 C3 51 52 56 8B C8 : ...P顋.ζ..QRV曲 00000210 : BA 20 00 EB 13 8B DA D1 E3 83 BF 00 00 00 74 08 : . ...芹.繝....t. 00000220 : 8B DA D1 E3 FF 97 00 00 4A 83 FA 00 7D E7 BE 00 : 芹......J・.}鄒. 00000380 : C6 8D 5E 80 8B 0E 32 00 E8 75 FE E8 7D FE 5F 5E : .洪...2.鑾.閘._^ 00000390 : 5A 59 8B E5 5D C3 68 65 6C 6C 6F 2C 20 77 6F 72 : ZY句].hello, wor 000003A0 : 6C 64 0A 00 6F 75 74 20 6F 66 20 6D 65 6D 6F 72 : ld..out of memor 000003B0 : 79 00 00 00 72 00 77 00 77 00 77 2B 62 00 77 62 : y...r.w.w.w+b.wb 000003C0 : 00 : .
printf のアドレスを呼び出し
main 関数
このデータをターゲットシステムに書き込む
どうやって書き込むのか?
アドレスがリンクにより確定している
プログラムのROM化
• ROM化とは
–一般的に組み込みシステムを動作させるプログラムはファームウェアと呼ばれる
– ファームウェアは最終的に ROM 書かれる
– ROM にデータを書く(ROM化)には 専用の装置(ROM ライタ)を用いる
– ROM ライタは指定したROMのアドレスに指定データを書き込む作業を行う
–指定データに指定アドレスを定義しているファイルは特殊な形式となっており,大体2種類に分類される • モトローラSフォーマット形式
• インテルHEXフォーマット形式
プログラムのROM化
code
data
stack
ロードモジュール
code
data
ROM
code
data
stack
stackには実体がない
ロードモジュールをROMに書き込む
命令コード
初期値のある変数
data’
copy
初期値のない変数
スタック領域
実行
高速化のためメモリにコピーして実行する場合もある
RAM
実行した段階で実体が生成される
ROMに書かれたファームウェア
プログラムのROM化
モトローラSフォーマット
– 複数のレコード形式
– ファイルはプレーンテキスト
– 1レコード 1行
S0 0E 0000 73616D706C652020202020 CF S2 14 000000 92ED73CEE943A2EFB87E3B89FEB2D26D 85 S2 14 000010 965AC3175EF077E199BBE27692E95088 6C S2 14 000020 83DD62C6B4CA5308E78180CDF48728E8 2A S2 14 000030 B16B70761456AA139CE4D64EEC32695A 0D S2 14 000040 BA394E06E75A2BEEEF39E5F384CF66EA 67 S2 14 000050 76BB9E91D6D9C7C75B16EEFC0483AFE6 87 S2 14 000060 FFA84075CA1AB10A985071E4F6B215DA BC S2 14 000070 AEF35550ECA157649FFA31682202A995 59 S2 14 000080 1CD23EFDA5336DC2AA6B2D869257BC22 AC S2 14 000090 21BA9D9B9DD5E2523038A77A8ED7DFCF 06 S2 14 0000A0 D7605385BFCCE77FEC351FC2A0E7E329 B6 S2 14 0000B0 97B97F5A339EEEF8D677581B8F2BD9FD 0B S2 14 0000C0 FAFA84F6610EA8AA2753518167891257 57 S2 14 0000D0 D8980275F42305C0595F4D316F262085 E8 S2 14 0000E0 4B47DB36D32137A92370CBA93066D214 11 S2 14 0000F0 ABFE2FD4298DAE1180998DA574EF3BD1 20 S8 04 000000 FB
レコード形式 バイト数 ロードアドレス
データ
チェックサム
S1 : 2バイトアドレス
S2 : 3バイトアドレス
S3 : 4バイトアドレス
S8 : 終了レコード
書き込み対象となる先頭アドレス
バイトカウントおよびデータの加算した結果の1の補数
スペースを入れて区切りを分かり易くしていますが,本来はスペースはありません
プログラムのROM化
インテル・HEXフォーマット
– 複数のレコード形式
– ファイルはプレーンテキスト
– 1レコード 1行
:10 0000 00 92ED73CEE943A2EFB87E3B89FEB2D26D 8A :10 0010 00 965AC3175EF077E199BBE27692E95088 71 :10 0020 00 83DD62C6B4CA5308E78180CDF48728E8 2F :10 0030 00 B16B70761456AA139CE4D64EEC32695A 12 :10 0040 00 BA394E06E75A2BEEEF39E5F384CF66EA 6C :10 0050 00 76BB9E91D6D9C7C75B16EEFC0483AFE6 8C :10 0060 00 FFA84075CA1AB10A985071E4F6B215DA C1 :10 0070 00 AEF35550ECA157649FFA31682202A995 5E :10 0080 00 1CD23EFDA5336DC2AA6B2D869257BC22 B1 :10 0090 00 21BA9D9B9DD5E2523038A77A8ED7DFCF 0B :10 00A0 00 D7605385BFCCE77FEC351FC2A0E7E329 BB :10 00B0 00 97B97F5A339EEEF8D677581B8F2BD9FD 10 :10 00C0 00 FAFA84F6610EA8AA2753518167891257 5C :10 00D0 00 D8980275F42305C0595F4D316F262085 ED :10 00E0 00 4B47DB36D32137A92370CBA93066D214 16 :10 00F0 00 ABFE2FD4298DAE1180998DA574EF3BD1 25 :00 0000 01 FF
バイト数 レコード形式 ロードアドレス
データ
チェックサム
00 : データ
01 : 終了
02 : 拡張
03 : エントリアドレス
書き込み対象となる先頭アドレス
バイトカウントからデータまでの加算した結果の2の補数
スペースを入れて区切りを分かり易くしていますが,本来はスペースはありません
レコードの開始
プログラムのROM化
• ROMデータの書き込み方法(1)
– ROMそのものにデータを書き込む
1つのROMに書き込む
(大体が実験用) 多数のROMに書き込む
(量産用途向け)
ROM
ターゲット ROMを搭載
プログラムのROM化
• ROMデータの書き込み方法(2)
–通信を通じてデータを書き込む
シリアル通信 など
CPU
ROM
RAM 周辺
内部に ROM が搭載されている
このROMにコードとデータを直接書き込む
LED と PORT の関係
7 6 5 4 3 2 1 0
PORTB
7 6 5 4 3 2 1 0
PORTD
LED #1 #2 #3 #4 #5 #6 #7
LED #8 #9 #10 #11 #12 #13
bit 7 ~ 1までが LED
で使われている
なお,SW1~7と共用
bit5 ~ 0 が LED で使われている
LED の点灯
LDE は port D に接続
port D の初期化
/* Set Port D config */
TRISD = 0xC0; // bit 0-5 OUT, bit6-7 IN
port D に出力
PORTD = <DATA> & 0x3F; // output to bit 0-5
但し port D は bit 0 ~ 5 までの 6bit が LED の出力に対応しており,bit 6,7は対応していないので注意
SW の使い方
RC5
RBx
RCx
・RB1~7 および RC0~1 を in に設定
・SWx を押すと RxDATA に SW の状況が入る
実習用ボードには SW が9個存在する
SW 1~7
SW 8,9
Pull-UP 抵抗
入力した情報が 1 の時: SW OFF
入力した情報が 0 の時: SW ON
SW の使い方
SW は port B に接続,一部 port C も使用
port B および port C の初期化
/* Set Port B*/
ANSELH = 0x00; // AN Disable (RB5-RB0)
WPUB = 0x00; // Pull-up disable
INTCON = 0x00; // Intrauppt disable
IOCB = 0x00; // Intrauppt charge disable
CCP1CON = 0x00;
CM2CON1 = 0x02;
OPTION_REG = 0xFF; // Pull-up disable
TRISB = 0xFF; // IN
/* Set Port C */
RCSTA = 0x00; // Serial disable (RC7-6)
SSPCON = 0x00; // Serial disable (RC5-4)
TRISC = 0x03; // OUT(2-7), IN(0,1)
PORTC = 0x00; // Low
port B の初期化
(入力設定)
port C の初期化
(入力および出力設定)
SW の使い方
スイッチの状態の読み込み
<data> = PORTB & 0xFE;
<data> = PORTC & 0x03;
port B は bit 1~7
が SW で使われる
port C は bit 0~1
が SW で使われる
各SWの状態を調べるには
例えば SW4 の状態を調べたい
SW4 は port B の bit 4 である
このbitが 1 のとき,SW は OFF,0 のとき,SW は ON
よって bit 4 だけが 1 か 0 かを判断すれば良い
if( (PORTB & 0x10) == 0 ) { /* SW4 is ON */
7 6 5 4 3 2 1 0
SW #7 #6 #5 #4 #3 #2 #1
bit 4 以外は 0 に固定してしまう
bit 4 が 0 のとき,SWは
ON となる
LED をビット毎に制御するには
例えば 6 つある LED の 3 つ目を光らせたい!
この LED の 3 つ目は port D の bit 2 である
よって bit 2 だけを 1 にすればよい
その他の bit はそのまま変更しないようにする
LED = PORTD | 0x04; // bit 2 is 1, other is condition of Port D
PORTD = LED ;
7 6 5 4 3 2 1 0
LED --- --- #8 #9 #10 #11 #12 #13
bit 2 は 1 にして,それ以外は前のままとする
OR 演算子
LED に対して出力する
情報工学セミナー 第4回 24
LCD ・センサー 用関数
lcd_disp.c
LCD 表示関数用ファイル
lcd_disp.h
LCD 表示関数用ヘッダファイル
sensor.c
timer,ロータリーエンコーダ関数用ファイル
sensor.h timer,ロータリーエンコーダ関数用ヘッダファイル
情報工学セミナー 第4回 25
LCD 表示用関数 (lcd_disp)
void init_lcd( void ) 液晶表示器を初期化する
void disp_number( int number, int x, int y) 液晶の指定場所に数値を1文字表示させる
void write_lcd( int code, int rs ) 液晶に rs 分の文字データを表示させる
void locate( int x, int y) 液晶のカーソル位置を指定する
void write_char( char c ) 液晶に1文字表示させる
void write_str( char *s ) 液晶に文字列を表示させる
情報工学セミナー 第4回 27
センサー用関数 (sensor)
void sensor_init( void ) 各種センサーの状態の初期化
char check_Rotary( void ) ロータリーエンコーダの回転状況を読み取る
return : 回転状態の読み取り 0 : not move
1 : 時計方向に1クリック動く
2 : 反時計方向に1クリック動く
short check_Tempture( void ) 温度センサーの状態を読み取る
return : 温度(℃)
void timer0_init( void ) timer0 の初期化
Rotary Encoder の使い方
rot_dir = check_Rotary();
switch( rot_dir ) {
case CW:
<処理>
break;
case CCW:
<処理>
break;
default:
break;
}
Rotary エンコーダの状態の読み取り
rot_dir に状態が入っている
時計回りで1つ動いたときの処理を記述
反時計回りで1つ動いたときの処理を記述
特に動きが無い時は抜ける
timer0 を使った割り込み処理
static void interrupt rtcc_isr( void ) {
T0IF = 0; /* Timer Interrupt Flag CLS */
<割り込み処理の記述>
}
void main ( void ) {
:
timer0_init(); /* Timer0 Initilize */
:
/* Timer0 Interrupt */
T0IE = 1; /* Enable Interrupt */
GIE = 1; /* Enable Global Interrupt */
}
割り込み処理の記述
タイマー0 を動作させる
timer0 による割り込み処理を許可
全体の割り込みを許可
Timer による割り込みについて
16F887 にはタイマーが全部で3つある
Timer0 , Timer1 , Timer2
割り込み用許可のレジスタ : INTCON
16F887 仕様書 p.31~p.32 参照
T0IE : Timer0 Overflow Interrupt Flag
TMR1IE : Timer1 Overflow Interrupt Enable bit
TMR2IE : Timer2 to PR2 Match Interrupt Enable bit
TME1IF : Timer1 Overflow Interrupt Flag bit
TME2IF : Timer2 to PR2 Interrupt Flag bit