Mini210S 開発キット詳細URL
第VIII章 DRAMにコードをリロケーション
第二節 プログラム説明
完全なコードは、ディレクトリ6.sdramをご参照ください。本章ではコードが大幅に変更があります。まず、プロジェクト全体はBL1とBL2 、2つのディレクトリに分割されます、ディレクトリBL1下のコードはBL1.binという名前のファイルにコンパイル・リンクされ、ディレクトリBL2下のコードはBL2.binという名前のファイルにコンパイル・リンクされます。BL1.binファイルのリンクアドレスは0である(位置独立コードで、プログラムが任意の可用メモリで実行できます)、BL2.binファイルのリンクアドレス0x23E00000(位置に依存するコードで、すべてのプログラムは当アドレスで実行します)BL1.binは、SDカードのセクタ1にプログラミングする必要があり、BL2.binはSDカードのセクタ49にプログラミングします。理由は後ほど説明します。プログラミング・プロセスは本章の第四節をご参照ください。プログラミング・プロセス:システム通電後、SDカードのセクタ1のBL1.bin を IRAM の 0xD0020000までにコピーし、実行します;本コードは先にDRAMを初期化し、続いてSDカードのセクタ49のBL2.binをDRAM の 0x23E00000までにコピーし、最後にプログラムが当アドレスにジャンプし、実行します。
1. BL1/start.S
前章と比べったら、本章の start.S に2つの手順を追加しました:
ステップ1 mem_init関数を呼び出し、メモリを初期化ます、機能の実現はmemory.Sにおけます、このファイルは、ubootから調達されます;
ステップ2 copy_code_to_dram()を呼び出し、SDカードからBL2.binファイルをDRAM 0x23E00000にコピーします。copy_code_to_dram()はmmc_relocate.cファイルにおけます;
2. BL1/memory.S
S5PV210は既にDDR2 DRAM初期化の仕方を解説しました、主に3つの主要手順にあります:PHY DLL初始化、DMC初始化、DDR2 DRAM初期化です。更に詳しいなら27のステップがあります、多くのレジスタを使用しますので、説明には時間が掛かり過ぎますので、本文ではレジスタ•セットには要点のみを説明します。DDR2 DRAM完全初期化手順下記図をご参照ください:
DRAMの完全初期化手順
memory.Sは上記の知識を参照して、メモリを初期化しました。主要手順は次の4つのステップです。
ステップ1 DRAMのドライバ強度(メモリアクセス信号強度)を設定
DRAM Driver Strength の値は大きほど、メモリアクセス信号強度が大きい。メモリは動作周波数には敏感で、動作周波数はメモリの公称周波数より高い場合、当オプションの値を大きくすると、コンピュータがオーバークロック状態での安定性を向上させることができます。ここではデフォルト値を使用します。
ステップ2 DDR型DRAMは、DLL(Delay Locked Loop 遅延ロックループがデータ•ストローブ信号を提供する)技術を使用します、データがオンな場合、メモリコントローラはこのデータ•ストローブ信号で、正確にデータを検索できます。ここでは、あまりにも深く掘る必要はありません、く27ステップの2~4の手順に従い、PHYのDLLを初期化するだけで十分です。関連するコードは、既に解説を持って、ここにコードを貼り付けていません。
ステップ3 DMC0を初期化
27ステップの 5~9と対応し、初期化します、詳しいレジスタ・セットはコードに参照ください。
ステップ4 DDR2 DRAMを初期化
DRAMの初期化はレジスタに DIRECTCMDコマンドを入れるだけで、7ステップの 16~23をご参照ください。
3. BL1/mmc_relocate.c
mem_init関数でDRAMを初期化後、DRAMへのコードをコピーし、実行できます。この機能はBL1ディレクトリ下のmmc_relocate.cで実現します。mmc_relocate.cコードは、下記のとおりです。
void copy_code_to_dram(void)
{
unsigned long ch;
void (*BL2)(void);
ch = *(volatile unsigned int *)(0xD0037488);
copy_sd_sd_to_mem copy_bl2 = (copy_sd_sd_to_mem) (*(unsigned int *) (0xD0037F98));
unsigned int ret;
// チャンネル 0
if (ch == 0xEB000000)
{
// 0:channel 0
// 49:ソース、コードはセクタ49にあり、1 sector = 512 bytes
// 32:長さ、こぴー 32 sector、 16K
// 0x23E00000:目的地、リンクアドレス 0x23E00000
ret = copy_bl2(0、 49、 32、(unsigned int *)0x23E00000、 0);
}
// チャンネル 2
else if (ch == 0xEB200000)
{
ret = copy_bl2(2、 49、 32、(unsigned int *)0x23E00000、 0);
}
else
return;
// DRAM にジャンプ
BL2 = (void *)0x23E00000;
(*BL2)();
}
まず、関数ポインタcopy_blを定義して、値を0xD0037F98に与えます。IROM内部硬化のコードは既に、クラスのコピー機能があります、 SDカードからデータをDRAMコピーするのも含めます。関数のアドレス配置は下記図をご参照ください。
上記図により、External Copy Function の位置は0xD0037F80~0xD0038000です、其SDカードからDRAMへデータをコピする機能の関数はアドレス0xD0037F98におけます、コードのプロトタイプは下記の通りです:
StartBlkAddress:コピー開始のセクタナンバー、1セクタの単位は512バイト
blockSize:セクタのコピー数
memoryPtr:DRAMのどのアドレスにコピーする
with_init:SDカードの初期化必要の判別
上記の知識があれば、copy_code_to_dram機能を理解することは簡単です。アドレス0xD0037488値を読み出しことによってチャネル0または1を使用するかどうかを判断できます、チップマニュアルで“sd/MMC/eMMC boot – MMC Channel0 is used for first boot. And Channel 2 is used for Second boot゛、BL1.bin はfirst boot、チャネル0を使用します、 CopysdMMCtoMem 関数を呼び出し、 BL2.bin は sd カードのセクタ49からDRAMの0x23E00000アドレスにコピします、コピの長さは16K。最後に、BL2関数ポインタに0x23E0000の値を与え、BL2関数を呼び出しで、関数は0x23E0000にジャンプして、BL2.binのコードを実行できます。
4. BL2/start.S
BL1.binは 0x23E00000にジャンプした後、実行するのは start.S のコードです、BL2.binリンカスクリプトsdram.ldsがコードセグメントの初期でをstart.oを置くことを指定された。BL2/start.Sで実行するのは、位置指令を使用することです:ldr PC、 =main は main 関数を呼び出し、main関数の機能は前章のコードと同じ、LEDを点滅することです。
---続く