SylixOS ARM BSP第2編【startup.S】
6027 ワード
このブログはSylixOS ARM BSPの連載第2編で、主にstartupを紹介している.Sファイルは具体的に実装される.
startup.SはBSP起動コードのエントリであり、通常bootloaderによりSylixOSミラーをマウント後に呼び出されるが、以下、S 3 C 2440 Aプロセッサを例に、ブロック毎にstartupを紹介する.Sコード.
このコードは、アセンブリプログラムである後に参照されるヘッダファイルを通知します.
オペレーティングシステムのアセンブリヘッダファイルを参照します.このヘッダファイルは、コンパイラとプラットフォームのタイプに基づいて、多くのコンパイラとプラットフォームに関連する処理マクロを定義し、異なるプラットフォーム、異なるコンパイラ間のアセンブリ言語のキーワードの違いを統一することができます.例えばFILE_BEGIN()マクロは、アセンブリ言語ファイルの開始を表すこのファイルに定義されます.
このコードは、ARMの各モードにおけるプリセットスタックのサイズを定義し、一般的には調整する必要はありません.
IMPORT_LABEL()は、このファイルが参照する必要がある外部記号を表し、Cプログラムのexternキーワードに相当します.
以下に示すすべてのコードまたは文字プールは、コンパイル後に名前で格納.vertorのセクションでは、リンクスクリプトに基づいて、リンクをシステムエントリに設定します.
FUNC_DEF()は定義関数を表し、ここでvectorという関数を定義し、順序によってこの関数は.vectorセクションのエントリ関数.
FUNC_END()は関数の終わりを表します.
このコードはARMベクトル仕様に従って作成されたジャンプテーブルであり、異なる異常に入って異なるアドレスにジャンプし、ここではARM FIQの高速割り込みは処理されていない.SylixOSのデフォルトではFIQ異常を引き継ぐことはなく、ユーザーが必要であれば自分で関連処理関数を作成することができることを示している.
以上のコードから,システムリセットベクトルは最終的にreset関数(またはラベル)にジャンプし,次にreset関数実装を見ることができる.
SECTION(.vector)の意味と同様に、以下のコードまたは文字プールが存在することを示す.textセクションにあります.ここで説明する必要があるのは、一般的に1つのプログラムが少なくとも3つのセグメント(セグメント)に分けられ、それぞれコードセグメント(.text)、データセグメント(.data)、クリアセグメント(.bss)である.ここで、コードセグメントに格納されるのは、一般的にプログラムコードと実行時に変更されないテーブル構造である.データ・セグメントには、主に初期値のグローバル変数が格納されます.クリアセグメントには、プライマリ・プログラムを実行する前にクリア操作が必要なグローバル変数が格納されます.リンクは、リンクスクリプトに基づいて、リンクtargetの各セクション(セグメント)のメモリレイアウトを決定します.具体的なリンクスクリプトの作成は、後述する章で説明します.
reset関数は、まず2440プロセッサの内部ウォッチドッグを閉じて、起動中にウォッチドッグにリセットされないようにします.ここでは、ターゲットマシンがSMP(対称マルチプロセッサ)プロセッサ、例えばARM Cortex-A 9マルチコアであれば、すべてのコアプログラムエントリがresetであるため、reset関数が最初からこのコアをプライマリコア(primary)またはセカンダリコア(secondary)と判断する必要があり、システム起動時に異なるコア初期化順序が異なるが、マルチタスク状態に入った後、各コア間に明確な違いはない.
このセグメントコードは、ARMプロセッサの様々なモードでのスタックを初期化し、ARMプロセッサは、スタックが高アドレスから低アドレスに増加することをサポートするとともに、スタックが低アドレスから高アドレスに増加することをサポートするが、一般的には、高アドレスから低アドレスに増加するモードを使用する.したがって、スタックの実点は、bspMapによるカーネルの高アドレス位置に定義される.h設定メモリレイアウトは、後でbspMap.hで詳しく紹介します.
ARMスタックの初期化が完了すると、2440のSDRAMインタフェースとPPLロックリングを初期化するために2つのサブ関数を呼び出します.もちろん、異なるプロセッサに対しても、ここのコードは異なります.bootloaderによって起動されると、実際にはこの部分のコードは必要ありません.bootloaderは関連するパラメータを初期化しました.
このコードは領域コピー関数です.このコードがデータ・セグメント(.data)に初期値を付与していることを知るだけでいいです.ここでは、ロード・セグメントと実行セグメントが異なる場合の処理サポートについて、リンク・スクリプトの内容に基づいて読者自身が関連知識を調べる必要があります.もちろんRealCoderは、ユーザーBSPウィザードでユーザーが設定した関連パラメータに基づいて、リンクスクリプトの生成を自動的に完了します.
以上のコードは、データ・セグメント(.data)の初期値と類似しており、このコードは、ゼロ・セグメント(.bss)のゼロ・オペレーション・ループである.
以上のコードは、コードセグメント(.text)がbootloaderによって初期化され、データセグメント(.data)とクリアセグメント(.bss)がBSPエントリ関数によって初期化され、この3つのセグメントが初期化されると、bspInit()関数に入ってオペレーティングシステムを正式に初期化し、bspInit()関数コードを呼び出すことができると結論した.
startup.Sファイルの最後にFILEがあります.END()は、FILEとBEGIN()文は対称的に使用され、アセンブリが終了したことを示します.
(この編完)
startup.SはBSP起動コードのエントリであり、通常bootloaderによりSylixOSミラーをマウント後に呼び出されるが、以下、S 3 C 2440 Aプロセッサを例に、ブロック毎にstartupを紹介する.Sコード.
#ifndef ASSEMBLY
#define ASSEMBLY 1
#endif
このコードは、アセンブリプログラムである後に参照されるヘッダファイルを通知します.
#include <arch/assembler.h>
オペレーティングシステムのアセンブリヘッダファイルを参照します.このヘッダファイルは、コンパイラとプラットフォームのタイプに基づいて、多くのコンパイラとプラットフォームに関連する処理マクロを定義し、異なるプラットフォーム、異なるコンパイラ間のアセンブリ言語のキーワードの違いを統一することができます.例えばFILE_BEGIN()マクロは、アセンブリ言語ファイルの開始を表すこのファイルに定義されます.
#define UND_STACK_SIZE 0x00001000
#define ABT_STACK_SIZE 0x00001000
#define FIQ_STACK_SIZE 0x00001000
#define IRQ_STACK_SIZE 0x00001000
#define SVC_STACK_SIZE 0x00001000
#define SYS_STACK_SIZE 0x00001000
このコードは、ARMの各モードにおけるプリセットスタックのサイズを定義し、一般的には調整する必要はありません.
IMPORT_LABEL(archIntEntry)
IMPORT_LABEL(archAbtEntry)
IMPORT_LABEL(archPreEntry)
IMPORT_LABEL(archUndEntry)
IMPORT_LABEL(archSwiEntry)
IMPORT_LABEL(sdramInit)
IMPORT_LABEL(targetInit)
IMPORT_LABEL(bspInit)
IMPORT_LABEL()は、このファイルが参照する必要がある外部記号を表し、Cプログラムのexternキーワードに相当します.
SECTION(.vector)
以下に示すすべてのコードまたは文字プールは、コンパイル後に名前で格納.vertorのセクションでは、リンクスクリプトに基づいて、リンクをシステムエントリに設定します.
FUNC_DEF(vector)
LDR PC, resetEntry
LDR PC, undefineEntry
LDR PC, swiEntry
LDR PC, prefetchEntry
LDR PC, abortEntry
LDR PC, reserveEntry
LDR PC, irqEntry
LDR PC, fiqEntry
FUNC_END()
FUNC_LABEL(resetEntry)
.word reset
FUNC_LABEL(undefineEntry)
.word archUndEntry
FUNC_LABEL(swiEntry)
.word archSwiEntry
FUNC_LABEL(prefetchEntry)
.word archPreEntry
FUNC_LABEL(abortEntry)
.word archAbtEntry
FUNC_LABEL(reserveEntry)
.word 0
FUNC_LABEL(irqEntry)
.word archIntEntry
FUNC_LABEL(fiqEntry)
.word 0
FUNC_DEF()は定義関数を表し、ここでvectorという関数を定義し、順序によってこの関数は.vectorセクションのエントリ関数.
FUNC_END()は関数の終わりを表します.
このコードはARMベクトル仕様に従って作成されたジャンプテーブルであり、異なる異常に入って異なるアドレスにジャンプし、ここではARM FIQの高速割り込みは処理されていない.SylixOSのデフォルトではFIQ異常を引き継ぐことはなく、ユーザーが必要であれば自分で関連処理関数を作成することができることを示している.
以上のコードから,システムリセットベクトルは最終的にreset関数(またはラベル)にジャンプし,次にreset関数実装を見ることができる.
SECTION(.text)
SECTION(.vector)の意味と同様に、以下のコードまたは文字プールが存在することを示す.textセクションにあります.ここで説明する必要があるのは、一般的に1つのプログラムが少なくとも3つのセグメント(セグメント)に分けられ、それぞれコードセグメント(.text)、データセグメント(.data)、クリアセグメント(.bss)である.ここで、コードセグメントに格納されるのは、一般的にプログラムコードと実行時に変更されないテーブル構造である.データ・セグメントには、主に初期値のグローバル変数が格納されます.クリアセグメントには、プライマリ・プログラムを実行する前にクリア操作が必要なグローバル変数が格納されます.リンクは、リンクスクリプトに基づいて、リンクtargetの各セクション(セグメント)のメモリレイアウトを決定します.具体的なリンクスクリプトの作成は、後述する章で説明します.
FUNC_DEF(reset)
LDR R0 , =WTCON
LDR R1 , =0x0
STR R1 , [R0]
reset関数は、まず2440プロセッサの内部ウォッチドッグを閉じて、起動中にウォッチドッグにリセットされないようにします.ここでは、ターゲットマシンがSMP(対称マルチプロセッサ)プロセッサ、例えばARM Cortex-A 9マルチコアであれば、すべてのコアプログラムエントリがresetであるため、reset関数が最初からこのコアをプライマリコア(primary)またはセカンダリコア(secondary)と判断する必要があり、システム起動時に異なるコア初期化順序が異なるが、マルチタスク状態に入った後、各コア間に明確な違いはない.
LDR R0 , =0x31800000 /* */
MSR CPSR_c, #(UND32_MODE | DIS_INT)
MOV SP , R0
SUB R0 , R0, #UND_STACK_SIZE
MSR CPSR_c, #(ABT32_MODE | DIS_INT)
MOV SP , R0
SUB R0 , R0, #ABT_STACK_SIZE
MSR CPSR_c, #(IRQ32_MODE | DIS_INT)
MOV SP , R0
SUB R0 , R0, #IRQ_STACK_SIZE
MSR CPSR_c, #(FIQ32_MODE | DIS_INT)
MOV SP , R0
SUB R0 , R0, #FIQ_STACK_SIZE
MSR CPSR_c, #(SVC32_MODE | DIS_INT)
MOV SP , R0
SUB R0 , R0, #SVC_STACK_SIZE
MSR CPSR_c, #(SYS32_MODE | DIS_INT)
MOV SP , R0
SUB R0 , R0, #SYS_STACK_SIZE
MSR CPSR_c, #(SVC32_MODE | DIS_INT)
このセグメントコードは、ARMプロセッサの様々なモードでのスタックを初期化し、ARMプロセッサは、スタックが高アドレスから低アドレスに増加することをサポートするとともに、スタックが低アドレスから高アドレスに増加することをサポートするが、一般的には、高アドレスから低アドレスに増加するモードを使用する.したがって、スタックの実点は、bspMapによるカーネルの高アドレス位置に定義される.h設定メモリレイアウトは、後でbspMap.hで詳しく紹介します.
BL sdramInit
BL targetInit
ARMスタックの初期化が完了すると、2440のSDRAMインタフェースとPPLロックリングを初期化するために2つのサブ関数を呼び出します.もちろん、異なるプロセッサに対しても、ここのコードは異なります.bootloaderによって起動されると、実際にはこの部分のコードは必要ありません.bootloaderは関連するパラメータを初期化しました.
LDR R1 , =_etext /* -> ROM data end */
LDR R2 , =_data /* -> data start */
LDR R3 , =_edata /* -> end of data */
1:
CMP R2 , R3 /* check if data to move */
LDRLO R0 , [R1] , #4 /* copy it */
STRLO R0 , [R2] , #4
BLO 1b /* loop until done */
このコードは領域コピー関数です.このコードがデータ・セグメント(.data)に初期値を付与していることを知るだけでいいです.ここでは、ロード・セグメントと実行セグメントが異なる場合の処理サポートについて、リンク・スクリプトの内容に基づいて読者自身が関連知識を調べる必要があります.もちろんRealCoderは、ユーザーBSPウィザードでユーザーが設定した関連パラメータに基づいて、リンクスクリプトの生成を自動的に完了します.
MOV R0 , #0 /* get a zero */
LDR R1 , =__bss_start /* -> bss start */
LDR R2 , =__bss_end /* -> bss end */
2:
CMP R1 , R2 /* check if data to clear */
STRLO R0 , [R1], #4 /* clear 4 bytes */
BLO 2b /* loop until done */
以上のコードは、データ・セグメント(.data)の初期値と類似しており、このコードは、ゼロ・セグメント(.bss)のゼロ・オペレーション・ループである.
以上のコードは、コードセグメント(.text)がbootloaderによって初期化され、データセグメント(.data)とクリアセグメント(.bss)がBSPエントリ関数によって初期化され、この3つのセグメントが初期化されると、bspInit()関数に入ってオペレーティングシステムを正式に初期化し、bspInit()関数コードを呼び出すことができると結論した.
LDR R10, =bspInit
MOV LR , PC
BX R10
startup.Sファイルの最後にFILEがあります.END()は、FILEとBEGIN()文は対称的に使用され、アセンブリが終了したことを示します.
(この編完)