続き。
■仮想メモリ割り当て
設計したメモリマップにしたがって固定のページテーブルを作成する
■割り込み初期化手順
(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年4月13日金曜日
仮想メモリ・・・その準備
仮想メモリの実現を2方法検討
(1)タスク毎に独立した4Gbyteのメモリ空間
この場合はタスクスイッチ時にページテーブルを切り替える
全てのタスクが広大なメモリ空間を扱えるが、タスクスイッチコストが重い
(2)カーネルとユーザータスクが4Gbyteのメモリ空間を共有
カーネルAPI呼び出し時にページテーブルを切り替える必要がない
ただし、カーネルとユーザーでメモリ空間を折半することになる
まずはいずれの場合でも必要となるページ機能有効化とページテーブルの設定方法を確認
例によって仕様書
■Cortex-A8仕様書
Cortex-A8 Technical Reference Manual
ページテーブルの物理アドレスはARMコプロセッサで設定する
設定するコプロセッサレジスタはTranslation Table Base Register(略してTTBR)
136ページ 3.2.31 c2, Translation Table Base Register 0
137ページ 3.2.32 c2, Translation Table Base Register 1
TTBR0がユーザープロセス用、TTBR1がOS用ということらしい。
TTBR0とTTBR1のどっちを使うか、または両方使うかはTranslation Table Base Control Register(略してTTBCR)で設定する
138ページ 3.2.33 c2, Translation Table Base Control Register
OS用であるTTBR1は固定で16kbyteのサイズを持つテーブルへのアドレスを保持する。
それに対してTTBR0が指すテーブルはTTBRC.Nビットで指定されるサイズになる。このサイズは128byte~16kbyteである。
N=0の時に最大サイズ16kbyteになる。この時はTTBR0で指定されるページテーブルのみでアドレス変換が行われる。これはARMv6仕様の仮想メモリ機構と同一動作となる。
■TTBRフォーマット
31 14 13 5 4 3 2 1 0
+------------------------------------------------+
| Base Address | 0 | RGN | P | 0 | C |
+------------------------------------------------+
ページテーブルは16kbyteのサイズ(TTBCRで変えられる)
RGN、P、Cはページテーブルのキャッシュに関する設定
面倒だからオール0(キャッシュしない)でまずは試す
ページテーブル内のフォーマットについてはARM v7 Architecture Reference Manualを参照する
■TTBCRフォーマット
31 6 5 4 3 0
+------------------------------------------------+
| 0 |PD1|PD0| 0 | N |
+------------------------------------------------+
セキュリティ拡張機能が実装されている場合の話だが、PD0, PD1はTTBR0,1それぞれを使ってアドレス変換をするかどうかを指定する。
1だと変換しない。例えばPD0=1とするとTTBR0によるページ変換をしなくなる。
もしTTBR0で指定されるページテーブルでアドレス変換しなければならない場合はページフォールトが発生する。
セキュリティ拡張機能が実装されていない場合はPD0、PD1は存在しない。NビットのみがTTBCRに存在することになる。
NはTTBR0のサイズを指定、すなわちTTBR0でアドレス変換をするメモリ範囲を指定する。
12-NがTTBR0を使ってアドレス変換する第1レベル記述子のインデックス範囲になる。
N=0なら12ビット範囲(0~0xFFF)、すなわち全第1レベル記述子範囲がTTBR0になる。
N=7なら5ビット範囲(0~32)、すなわち第1レベル記述子の最初の方、メモリアドレスで言うと0~0x2000000(2^5*256*4096)がTTBR0になる。
Linuxカーネルみたいに0xC0000000~0xFFFFFFFFをカーネル領域としてTTBR1に変換させたい場合は・・・、残念ながらN=1で0~0x80000000がTTBR0範囲となるためこの仕組みでは実現できない。
■ページテーブルフォーマット
ARM v7 Architecture Reference Manualの729ページ B4.7.4 第1 レベル記述子
第1レベル記述子はコアースページテーブル、セクションテーブル、スーパーセクションテーブルの3種類がある
とりあえずコアースページテーブルで実装する。
(コアースページテーブル)
31 10 9 8 5 4 2 1 0
+------------------------------------------------------+
| 第2レベル記述子 Base Address | IMP | Domain | 0 | 01 |
+------------------------------------------------------+
IMPの部分が何を意味するか良くわからない。
どうもユーザーが勝手に使って良いビットのようだが・・・。とりあえず0にしておく。
Domainはアクセス権に関係する設定。
別途ドメインアクセス制御レジスタ(DACR)を使ってあるメモリ領域ごとにアクセス権を設定できる。まずは0を指定して全領域ドメイン0で動かす。
■第2レベル記述子
ARM v7 Architecture Reference Manualの733ページB4.7.7 第2 レベル記述子 - コアースページテーブルのフォーマット
1ページメモリを4kbyteで扱う場合はスモールページを使う
(スモールページ)
31 12 11 10 9 8 7 6 5 4 3 2 1 0
+---------------------------------------------------------------+
| 物理メモリページ Base Address | AP3 | AP2 | AP1 | AP0 | C | B | 10 |
+---------------------------------------------------------------+
APはアクセス権設定に関係する。詳細は 710ページ B4.3 メモリアクセスの制御を参照
Cはキャッシュ可能か否か。1で可能
Bはバッファ可能か否か。1で可能
上記は古いARMのフォーマット。Cortex-A8はVMSAv7なので以下のフォーマット
31 12 11 10 9 8 6 5 4 3 2 1 0
+----------------------------------------------------------------+
| 物理メモリページ Base Address | nG | S | APX | TEX | AP | C | B | 10 |
+----------------------------------------------------------------+
C,Bの詳細は713ページ B4.4.1 C、B、TEX のエンコードを参照
(1)タスク毎に独立した4Gbyteのメモリ空間
この場合はタスクスイッチ時にページテーブルを切り替える
全てのタスクが広大なメモリ空間を扱えるが、タスクスイッチコストが重い
(2)カーネルとユーザータスクが4Gbyteのメモリ空間を共有
カーネルAPI呼び出し時にページテーブルを切り替える必要がない
ただし、カーネルとユーザーでメモリ空間を折半することになる
まずはいずれの場合でも必要となるページ機能有効化とページテーブルの設定方法を確認
例によって仕様書
■Cortex-A8仕様書
Cortex-A8 Technical Reference Manual
ページテーブルの物理アドレスはARMコプロセッサで設定する
設定するコプロセッサレジスタはTranslation Table Base Register(略してTTBR)
136ページ 3.2.31 c2, Translation Table Base Register 0
137ページ 3.2.32 c2, Translation Table Base Register 1
TTBR0がユーザープロセス用、TTBR1がOS用ということらしい。
TTBR0とTTBR1のどっちを使うか、または両方使うかはTranslation Table Base Control Register(略してTTBCR)で設定する
138ページ 3.2.33 c2, Translation Table Base Control Register
OS用であるTTBR1は固定で16kbyteのサイズを持つテーブルへのアドレスを保持する。
それに対してTTBR0が指すテーブルはTTBRC.Nビットで指定されるサイズになる。このサイズは128byte~16kbyteである。
N=0の時に最大サイズ16kbyteになる。この時はTTBR0で指定されるページテーブルのみでアドレス変換が行われる。これはARMv6仕様の仮想メモリ機構と同一動作となる。
■TTBRフォーマット
31 14 13 5 4 3 2 1 0
+------------------------------------------------+
| Base Address | 0 | RGN | P | 0 | C |
+------------------------------------------------+
ページテーブルは16kbyteのサイズ(TTBCRで変えられる)
RGN、P、Cはページテーブルのキャッシュに関する設定
面倒だからオール0(キャッシュしない)でまずは試す
ページテーブル内のフォーマットについてはARM v7 Architecture Reference Manualを参照する
■TTBCRフォーマット
31 6 5 4 3 0
+------------------------------------------------+
| 0 |PD1|PD0| 0 | N |
+------------------------------------------------+
セキュリティ拡張機能が実装されている場合の話だが、PD0, PD1はTTBR0,1それぞれを使ってアドレス変換をするかどうかを指定する。
1だと変換しない。例えばPD0=1とするとTTBR0によるページ変換をしなくなる。
もしTTBR0で指定されるページテーブルでアドレス変換しなければならない場合はページフォールトが発生する。
セキュリティ拡張機能が実装されていない場合はPD0、PD1は存在しない。NビットのみがTTBCRに存在することになる。
NはTTBR0のサイズを指定、すなわちTTBR0でアドレス変換をするメモリ範囲を指定する。
12-NがTTBR0を使ってアドレス変換する第1レベル記述子のインデックス範囲になる。
N=0なら12ビット範囲(0~0xFFF)、すなわち全第1レベル記述子範囲がTTBR0になる。
N=7なら5ビット範囲(0~32)、すなわち第1レベル記述子の最初の方、メモリアドレスで言うと0~0x2000000(2^5*256*4096)がTTBR0になる。
Linuxカーネルみたいに0xC0000000~0xFFFFFFFFをカーネル領域としてTTBR1に変換させたい場合は・・・、残念ながらN=1で0~0x80000000がTTBR0範囲となるためこの仕組みでは実現できない。
■ページテーブルフォーマット
ARM v7 Architecture Reference Manualの729ページ B4.7.4 第1 レベル記述子
第1レベル記述子はコアースページテーブル、セクションテーブル、スーパーセクションテーブルの3種類がある
とりあえずコアースページテーブルで実装する。
(コアースページテーブル)
31 10 9 8 5 4 2 1 0
+------------------------------------------------------+
| 第2レベル記述子 Base Address | IMP | Domain | 0 | 01 |
+------------------------------------------------------+
IMPの部分が何を意味するか良くわからない。
どうもユーザーが勝手に使って良いビットのようだが・・・。とりあえず0にしておく。
Domainはアクセス権に関係する設定。
別途ドメインアクセス制御レジスタ(DACR)を使ってあるメモリ領域ごとにアクセス権を設定できる。まずは0を指定して全領域ドメイン0で動かす。
■第2レベル記述子
ARM v7 Architecture Reference Manualの733ページB4.7.7 第2 レベル記述子 - コアースページテーブルのフォーマット
1ページメモリを4kbyteで扱う場合はスモールページを使う
(スモールページ)
上記は古いARMのフォーマット。Cortex-A8はVMSAv7なので以下のフォーマット
31 12 11 10 9 8 6 5 4 3 2 1 0
+----------------------------------------------------------------+
| 物理メモリページ Base Address | nG | S | APX | TEX | AP | C | B | 10 |
+----------------------------------------------------------------+
C,Bの詳細は713ページ B4.4.1 C、B、TEX のエンコードを参照
2012年4月10日火曜日
UARTからHello World
次はUART出力からターミナルにHello Worldと表示することを目指す
まずは仕様書の確認
■BeagleBoard仕様書
BeagleBoard SRM
■OMAP3530仕様書
OMAP3530はBeagleBoardに搭載されているCortex-A8のマイコン
OMAP35x Technical Reference Manual
OMAP3530仕様書のを見ると2638ページ「UART/IrDA/CIR Overview」からUARTデバイスは3つ存在することがわかる
また、BeagleBoard仕様書の23ページ「5.18 RS232 Header」からBeagleBoardのシリアル端子はUART3に繋がっているとわかる
したがってUARTからPCのシリアルポートにHello Worldを出力するにはUART3を制御することになる
UART3を制御する手順は以下の通り
■制御手順
(1)OMAP3530 Perブロックの電源をON
OMAP3530仕様書の582ページを参照
PM_PWSTCTRL_PERレジスタのPOWERSTATEに0x3を設定
(2)OMAP3530 Perブロック内UART3にクロック供給
供給するクロックはFunctionクロックとInterfaceクロックの2つ
OMAP3530仕様書の492ページを参照
CM_FCLKEN_PERレジスタとCM_ICLKEN_PERレジスタのUART3ビットを立てる
(3)UART3初期化
OMAP3530仕様書の2697ページを参照
[1]MDR1_REGレジスタに0x7を書き込んでUART無効化(2716ページ)
[2]LCR_REGレジスタに0x83を書き込んでConfigモードAに移行(2707ページ)
[3]DLL_REGレジスタ、DLH_REGレジスタの2つでボーレート設定(2697ページ、2701ページ)
DLL, DLHに設定する値の計算は2672ページ 17.4.4.1.1 UART Clock Generation: Baud Rate Generationを参照
(*)x16モードで動作させた場合にボーレートを115200にするのはDLL=0x1A, DLH=0x00
[4]LCR_REGレジスタに0x3を書き込んで通常モードに戻る
[5]MDR1_REGレジスタに0を書き込んでx16モードで動作開始
(4)出力バッファの空き確認
LSR_REGレジスタのTX_FIFO_Eビットがクリアされるまでループする(2710ページ)
(5)文字を出力バッファに書き込む
THR_REGレジスタに文字コードを書き込む(2698ページ)
(4)(5)を繰り返すことで文字列を出力
注意点はUARTレジスタは全て8ビットでアクセスすること
■サンプル
ソースコード
まずは仕様書の確認
■BeagleBoard仕様書
BeagleBoard SRM
■OMAP3530仕様書
OMAP3530はBeagleBoardに搭載されているCortex-A8のマイコン
OMAP35x Technical Reference Manual
OMAP3530仕様書のを見ると2638ページ「UART/IrDA/CIR Overview」からUARTデバイスは3つ存在することがわかる
また、BeagleBoard仕様書の23ページ「5.18 RS232 Header」からBeagleBoardのシリアル端子はUART3に繋がっているとわかる
したがってUARTからPCのシリアルポートにHello Worldを出力するにはUART3を制御することになる
UART3を制御する手順は以下の通り
■制御手順
(1)OMAP3530 Perブロックの電源をON
OMAP3530仕様書の582ページを参照
PM_PWSTCTRL_PERレジスタのPOWERSTATEに0x3を設定
(2)OMAP3530 Perブロック内UART3にクロック供給
供給するクロックはFunctionクロックとInterfaceクロックの2つ
OMAP3530仕様書の492ページを参照
CM_FCLKEN_PERレジスタとCM_ICLKEN_PERレジスタのUART3ビットを立てる
(3)UART3初期化
OMAP3530仕様書の2697ページを参照
[1]MDR1_REGレジスタに0x7を書き込んでUART無効化(2716ページ)
[2]LCR_REGレジスタに0x83を書き込んでConfigモードAに移行(2707ページ)
[3]DLL_REGレジスタ、DLH_REGレジスタの2つでボーレート設定(2697ページ、2701ページ)
DLL, DLHに設定する値の計算は2672ページ 17.4.4.1.1 UART Clock Generation: Baud Rate Generationを参照
(*)x16モードで動作させた場合にボーレートを115200にするのはDLL=0x1A, DLH=0x00
[4]LCR_REGレジスタに0x3を書き込んで通常モードに戻る
[5]MDR1_REGレジスタに0を書き込んでx16モードで動作開始
(4)出力バッファの空き確認
LSR_REGレジスタのTX_FIFO_Eビットがクリアされるまでループする(2710ページ)
(5)文字を出力バッファに書き込む
THR_REGレジスタに文字コードを書き込む(2698ページ)
(4)(5)を繰り返すことで文字列を出力
注意点はUARTレジスタは全て8ビットでアクセスすること
■サンプル
ソースコード
登録:
投稿 (Atom)
