続き。
■仮想メモリ割り当て
設計したメモリマップにしたがって固定のページテーブルを作成する
■割り込み初期化手順
(1)CPUのIRQ割り込みハンドラを登録
(2)CPUの割り込み有効化
asm ("cpsie i"); でIRQ有効化
(3)UARTにクロック供給
(4)UARTのIRQハンドラを登録
(5)UARTのIRQ出力有効化
受信割り込みのみ有効化する。
OMAP3530仕様書の2693ページ 17.6.1 UART/IrDA/CIRレジスタ IER_REGを参照
IER_REGに1(RHR_ITビット)を書き込み
■割り込みハンドラ
IRQハンドラだけ作成
IRQ以外の割り込みは使用しないのでnop
ハンドラではレジスタをスタックに保存してIRQ処理に飛ぶ
.extern interruptHandler
.global interruptVector
_irq_entry:
stmfd sp!, {r0 - r12, lr};
mov r0, #6;
bl interruptHandler;
ldmfd sp!, {r0 - r12, lr};
subs pc, lr, #4;
interruptVector:
nop; // Reset
nop; // Invalid code
nop; // Software Service.
nop; // Prefetch Abort
nop; // Data Abort
nop;
ldr pc, =_irq_entry;
nop; // Fast IRQ
■UART割り込みハンドラ
UARTドライバの割り込みハンドラでは割り込み時にRHRから1文字読み取ってバッファに記録
■サンプル
ソースコード
2012年8月10日金曜日
2012年6月4日月曜日
ターミナル入力・・・・UART+MMU+割り込み
UARTの制御と割り込みを使ってターミナルから文字列を入力してそれを表示してみる。
■実装方針
1、メモリマップ
2、割り込み駆動
UARTへの入力はポーリングによってバッファの状態を確認するのではなく、割り込みで入力を検知する。
BeagleBoardの端子はUART3に接続なのでIRQ74に対応するハンドラを登録する。
OMAP35x Technical Reference Manual 10.3.2 Interrupt Request Linesを参照
■メイン処理
(1)UART入力バッファが空か確認
(2)読み込み可能フラグが立つまで無限ループ
→IRQ74が発生したらフラグを立てる
(3)バッファから1文字読み込み
(4)読み込んだ文字をUART出力
(5)(1)に戻る
■実装方針
1、メモリマップ
物理メモリのアドレス=仮想アドレスを基本とする。
BeagleBoardは物理メモリが0x8000 0000~0x8FFF FFFF の256Mbyte
割り込みベクタは上位ベクタ0xFFFF 0000が使えるように割り当てる。
ハードウェアレジスタは256M分のメモリの上位、すなわち0x90000000~に割り当て
コードとデータはオフセット0x400000~に配置。その下をスタックとする
ハードウェアレジスタは256M分のメモリの上位、すなわち0x90000000~に割り当て
コードとデータはオフセット0x400000~に配置。その下をスタックとする
以上の方針によりメモリマップは以下のように設定
2、割り込み駆動
UARTへの入力はポーリングによってバッファの状態を確認するのではなく、割り込みで入力を検知する。
BeagleBoardの端子はUART3に接続なのでIRQ74に対応するハンドラを登録する。
OMAP35x Technical Reference Manual 10.3.2 Interrupt Request Linesを参照
■メイン処理
(1)UART入力バッファが空か確認
(2)読み込み可能フラグが立つまで無限ループ
→IRQ74が発生したらフラグを立てる
(3)バッファから1文字読み込み
(4)読み込んだ文字をUART出力
(5)(1)に戻る
2012年5月13日日曜日
割り込み
次はCPU割り込み処理を実装する。
ARMには7種類の割り込みがある。
リセット、未定義命令、ソフトウェア割り込み、プリフェッチアボート、データアボート、IRQ、FastIRQ
割り込みハンドラは割り込みベクタにアドレスを設定する。
割り込みベクタは通常は0x00000000に、上位ベクタ機能を有効にした場合は0xFFFF0000にある
ARM v7 Architecture Reference Manualの54ページA2.6 例外
割り込みからの復帰はlrレジスタを使う。しかし割り込みの種類によって復帰命令が異なる
以下の表に割り込みの一覧と復帰命令を記載する
■割り込みベクタ
■割り込みベクタ設定例
アセンブラ命令で割り込みベクタの各エントリに割り込みハンドラへのジャンプ命令を設定する。
割り込みベクタ先頭をinterrupt_vector_startとすると以下のように記述する
interrupt_vector_start:
ldr pc, =_reset;
ldr pc, =_invalid_opcode;
ldr pc, =_service;
ldr pc, =_prefetch_abort;
ldr pc, =_data_abort;
nop;
ldr pc, =_irq;
ldr pc, =_fast_irq;
■上位ベクタ
通常の割り込みベクタアドレスは0x00000000だが、これを上位アドレス0xFFFF0000に移すことができる。上位ベクタ機能はCP15 C1 Control RegisterのVビットを1にセットすることで有効化できる
当然のことながらMMUを有効化して0xFFFF0000の仮想アドレスに対するメモリを設定しておく必要がある。
31 30 29 28 27 26 25 24 13 12 11 10 2 1 0
+---------------------------------------------------------------------+
| 0 | TE | AFE | TRE | NMFI | 0 | EE | 0 | V | I | Z | 0 | C | A | M |
+---------------------------------------------------------------------+
■上位ベクタ有効化
unsigned long value;
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(value));
value |= (1 << 13);
asm("mcr p15, 0, %0, c1, c0, 0;" : : "r"(value));
ARMには7種類の割り込みがある。
リセット、未定義命令、ソフトウェア割り込み、プリフェッチアボート、データアボート、IRQ、FastIRQ
割り込みハンドラは割り込みベクタにアドレスを設定する。
割り込みベクタは通常は0x00000000に、上位ベクタ機能を有効にした場合は0xFFFF0000にある
ARM v7 Architecture Reference Manualの54ページA2.6 例外
割り込みからの復帰はlrレジスタを使う。しかし割り込みの種類によって復帰命令が異なる
以下の表に割り込みの一覧と復帰命令を記載する
■割り込みベクタ
| 割り込み | オフセット | 復帰命令 | 説明 |
|---|---|---|---|
| リセット | 0 | なし | CPUリセット時に実行される |
| 未定義命令 | 4 | movs pc, lr | CPUがサポートしていない不正な命令を実行しようとした場合に呼び出される |
| ソフトウェア割り込み | 8 | movs pc, lr | ソフトウェア割り込み命令SWIを実行した場合に呼び出される。大方の場合カーネルサービス呼び出しに使用する |
| プリフェッチアボート | 12 | subs pc, lr, #4 | 命令コードをフェッチしようとしたときにコードを読み出そうとしたアドレスからメモリ読み出しが出来なかったときに呼び出される。MMUが有効化していて仮想アドレスのエントリが不在となっている場合に発生する |
| データアボート | 16 | subs pc, lr, #8 | 読み出そうとしたアドレスからメモリ読み出しが出来なかったときに呼び出される。MMUが有効化していて仮想アドレスのエントリが不在となっている場合に発生する |
| 未使用 | 20 | 未使用の割り込みエントリ | |
| IRQ | 24 | subs pc, lr, #4 | ハードウェアからIRQが発生したときに呼び出される。 |
| FastIRQ | 28 | subs pc, lr, #4 | ハードウェアからIRQが発生したときに呼び出される。 |
■割り込みベクタ設定例
アセンブラ命令で割り込みベクタの各エントリに割り込みハンドラへのジャンプ命令を設定する。
割り込みベクタ先頭をinterrupt_vector_startとすると以下のように記述する
interrupt_vector_start:
ldr pc, =_reset;
ldr pc, =_invalid_opcode;
ldr pc, =_service;
ldr pc, =_prefetch_abort;
ldr pc, =_data_abort;
nop;
ldr pc, =_irq;
ldr pc, =_fast_irq;
■上位ベクタ
通常の割り込みベクタアドレスは0x00000000だが、これを上位アドレス0xFFFF0000に移すことができる。上位ベクタ機能はCP15 C1 Control RegisterのVビットを1にセットすることで有効化できる
当然のことながらMMUを有効化して0xFFFF0000の仮想アドレスに対するメモリを設定しておく必要がある。
31 30 29 28 27 26 25 24 13 12 11 10 2 1 0
+---------------------------------------------------------------------+
| 0 | TE | AFE | TRE | NMFI | 0 | EE | 0 | V | I | Z | 0 | C | A | M |
+---------------------------------------------------------------------+
■上位ベクタ有効化
unsigned long value;
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(value));
value |= (1 << 13);
asm("mcr p15, 0, %0, c1, c0, 0;" : : "r"(value));
2012年5月7日月曜日
MMU有効化
ページテーブルのフォーマットがわかったのでMMUを有効化してみる
有効化はコプロセッサ操作で行う。
MMUを有効化するコプロセッサレジスタはCP15レジスタC1 Control Register
Cortex-A8 Technical Reference Manualの122ページ 3.2.25 c1, Control Register参照
■CP15 C1 Control Registerフォーマット
31 30 29 28 27 26 25 24 13 12 11 10 2 1 0
+---------------------------------------------------------------------+
| 0 | TE | AFE | TRE | NMFI | 0 | EE | 0 | V | I | Z | 0 | C | A | M |
+---------------------------------------------------------------------+
MMUを有効化する場合はTTBRレジスタにページテーブルの物理アドレスを指定した状態でCP15 C1レジスタのMビットを1にする。
コプロセッサの値変更はアセンブラコプロセッサ命令を使用する
■コプロセッサレジスタ値取得
unsigned long value;
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(value));
■コプロセッサレジスタ値設定
unsigned long value = 設定値;
asm("mcr p15, 0, %0, c1, c0, 0;" : : "r"(value));
■MMU有効化
unsigned long value;
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(value));
value |= 1;
asm("mcr p15, 0, %0, c1, c0, 0;" : : "r"(value));
有効化はコプロセッサ操作で行う。
MMUを有効化するコプロセッサレジスタはCP15レジスタC1 Control Register
Cortex-A8 Technical Reference Manualの122ページ 3.2.25 c1, Control Register参照
■CP15 C1 Control Registerフォーマット
31 30 29 28 27 26 25 24 13 12 11 10 2 1 0
+---------------------------------------------------------------------+
| 0 | TE | AFE | TRE | NMFI | 0 | EE | 0 | V | I | Z | 0 | C | A | M |
+---------------------------------------------------------------------+
MMUを有効化する場合はTTBRレジスタにページテーブルの物理アドレスを指定した状態でCP15 C1レジスタのMビットを1にする。
コプロセッサの値変更はアセンブラコプロセッサ命令を使用する
■コプロセッサレジスタ値取得
unsigned long value;
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(value));
■コプロセッサレジスタ値設定
unsigned long value = 設定値;
asm("mcr p15, 0, %0, c1, c0, 0;" : : "r"(value));
■MMU有効化
unsigned long value;
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(value));
value |= 1;
asm("mcr p15, 0, %0, c1, c0, 0;" : : "r"(value));
登録:
投稿 (Atom)
