このトピックでは、MT3620 チップで実行されるリアルタイム アプリケーションの基本的なメモリ使用量と待機時間に関する考慮事項について説明します。
Note
メモリ構成または DMA の詳細については、MediaTek から発行された MT3620 データシートを参照してください。質問が残っている場合は、Azure.Sphere@avnet.comに電子メールで Avnet から "MT3620 M4 データシート" を要求できます。
リアルタイム コアのメモリ レイアウト
次の表は、リアルタイム コアで使用可能なメモリをまとめたものです。
| メモリの種類 | ベース アドレス |
|---|---|
| TCM | 0x00100000 |
| XIP フラッシュ | 0x10000000 |
| SYSRAM | 0x22000000 |
各リアルタイム コアには 192 KB の密結合メモリ (TCM) があり、0x00100000から 64 KB の 3 つのバンクにマップされます。 TCM アクセスは高速ですが、リアルタイム コアのみがメモリにアクセスできます。 TCM は、高レベルのアプリケーションや、別のコアで実行されるリアルタイム対応アプリケーション (RTApp) と共有することはできません。
また、各リアルタイム コアには 64 KB の SYSRAM があり、0x22000000からマップされます。 DMA コントローラーは SYSRAM をターゲットにして、周辺機器が SYSRAM にアクセスできるようにすることもできます。 リアルタイム コアからの SYSRAM へのアクセスは、TCM へのアクセスよりも低速です。 TCM と同様に、SYSRAM を別のアプリケーションと共有することはできません。
インプレース実行 (XIP) フラッシュメモリは、上位アプリケーションと共有されます。 フラッシュの XIP マッピングへのウィンドウは、アドレス 0x10000000の各コアに表示されます。 OS は、アプリケーションの ELF ファイルに次のプロパティを持つセグメントが含まれている場合、アプリケーションを起動する前に XIP マッピングを構成します。
- ロードアドレス (Program Header の VirtAddr 列で指定) は 0x10000000 に等しい
- (プログラム ヘッダーの FileSiz フィールドと MemSiz フィールドで指定されている) ファイル オフセットとサイズは、アプリケーションの ELF ファイルに収まります
これらのプロパティを持つプログラム ヘッダーがアプリケーションの ELF ファイルに存在する場合、セグメントが0x10000000に表示されるように XIP ウィンドウが配置されます。 ファイルは複数の XIP セグメントを持つ必要があり、0x10000000を指す必要があります。他のアドレスを指定することはできません。
ELF の展開
RTApp イメージは ELF ファイルである必要があります。 ELF イメージは、Azure Sphere イメージ パッケージにラップされ、アプリケーションとしてデプロイされます。 アプリケーションを読み込むには、Azure Sphere OS によって、リアルタイム コアで実行される ELF ローダーが起動されます。 ローダーは、ELF ファイル内の各 LOAD セグメントを処理し、プログラム ヘッダー内の仮想アドレスによって示されるメモリの種類に読み込みます。
GNU Arm Embedded Toolchain の一部である arm-none-eabi-readelf.exe -l (小文字 L) を使用して、アプリケーションのプログラム ヘッダーを表示します。 ヘッダーに表示される仮想アドレス列 (VirtAddr) は、読み込みセグメントの宛先アドレスを示します。 プロセッサ自体が追加の変換を実行することを意味するものではありません。 Azure Sphere ELF ローダーは物理アドレス (PhysAddr) を使用しません。
以下に例を示します。
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000098 0x00100000 0x00100000 0x00000 0x00e78 RW 0x8
LOAD 0x0000a0 0x10000000 0x10000000 0x03078 0x03078 RWE 0x10
LOAD 0x003118 0x00100e78 0x10003078 0x000f0 0x000f0 RW 0x4
0x00100000のセグメントは、密結合メモリ (TCM) を対象としています。 ローダーは、イメージ パッケージから RAM にデータをコピーするか、必要に応じて TCM をゼロ初期化します。
0x10000000のセグメントは、コアの XIP ウィンドウにマップされます。 実行時に、
0x10000000 + offsetへのアクセスは、リアルタイム コアから離れると<address-of-XIP-segment-in-flash> + offsetに変換されます。仮想アドレス 0x00100e78のデータ セグメントは TCM にマップされます。
ELF ランタイムに関する考慮事項
ELF ローダーは、生のバイナリ (またはチェーンされたブートローダー) が起動時に実行するタスクの一部を実行します。 具体的には、プログラム ヘッダーに従って、ブロック開始バイシンボル (BSS) データをゼロ初期化し、初期化されたが変更可能なデータを読み取り専用フラッシュから RAM にコピーします。 その後、アプリケーションが起動し、独自の初期化関数を実行します。 ほとんどの場合、既存のアプリケーションへの変更は必要ありません。 ローダーが既にメモリをゼロにしているため、アプリケーションで BSS データをゼロにすることは不要ですが無害です。
フラッシュから RAM に変更可能なデータをコピーすると、ELF ファイルのレイアウト方法によっては問題が発生する場合があります。ELF ローダーは、ファイル内のセグメントの全体的なレイアウトを変更せずに、プログラム ヘッダーを順番に処理します。 次に、XIP セグメント自体を0x10000000だけでなく、後続のセグメントも順番にマップします。 ELF ファイル内のセグメントがアラインメントやギャップなしで順番に並んでいる場合、OS スタートアップ コードはポインター演算を使用してデータ セグメントの開始を見つけることができます。 ただし、ELF ファイルのレイアウトが異なる場合、ポインターの算術演算では正しいアドレスが得られないため、アプリケーションのスタートアップ コードでデータ セクションのコピーを試みてはなりません。 これにより、アプリケーションまたは RTOS でチェーンされたブートローダーが使用されている場合や、BSS をゼロにする前にスタック カナリアを設定する必要がある場合、または変更可能なデータを初期化する前に問題が発生する可能性があります。
メモリ対象
アプリケーションの linker.ld スクリプトを編集することで、TCM、XIP フラッシュ、または SYSRAM でコードをターゲットにすることができます。 Azure Sphereサンプル アプリケーションは TCM から実行されますが、各アプリケーションの linker.ld スクリプト ファイルでは、代わりに XIP フラッシュをターゲットにする方法が説明されています。 次の例に示すように、既定の TCM ではなく、CODE_REGIONとRODATA_REGIONを FLASH にエイリアシングすることで、XIP で実行するサンプルを変更できます。
REGION_ALIAS("CODE_REGION", FLASH);
REGION_ALIAS("RODATA_REGION", FLASH);
コンパイル済みアプリケーションが TCM または XIP フラッシュから実行されるかどうかを判断するには、GNU Arm Embedded Toolchain の一部である arm-none-eabi-readelf.exe を使用します。 イメージ パッケージと同じディレクトリにある .out ファイルで実行し、 -l (小文字の L) フラグを指定して、コードと読み取り専用データが配置されている場所を確認します。 フラッシュ メモリ内のコードと読み取り専用データは、アドレス 0x10000000に読み込まれます。コードと TCM のデータは TCM リージョンに読み込まれます。
次の例は、フラッシュ メモリから実行されるアプリケーションを示しています。
arm-none-eabi-readelf.exe -l UART_RTApp_MT3620_BareMetal.out
Elf file type is EXEC (Executable file)
Entry point 0x10000000
There are 2 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000074 0x00100000 0x00100000 0x00284 0x003c0 RW 0x4
LOAD 0x000300 0x10000000 0x10000000 0x013b9 0x013b9 R E 0x10
Section to Segment mapping:
Segment Sections...
00 .data .bss
01 .text .rodata
ベクター テーブルの場所
ARMv7-M デバイスでは、「ARMv7-M アーキテクチャ リファレンス マニュアル」で説明されているように、ベクター テーブルは、少なくとも 128 バイトで、テーブルのサイズ以下の 2 乗境界に配置する必要があります。 MT3620 の各 I/O RT コアでは、100 個の外部割り込みがサポートされます。 そのため、スタック ポインターと 15 個の標準例外を含め、テーブルには 116 個の 4 バイト エントリがあり、合計サイズは 464 バイトで、512 バイトまで切り上げます。
XIP フラッシュからコードを実行する場合は、ベクター テーブルを 0x10000000 に配置し、ELF ファイル内の 32 バイト境界に配置する必要があります。 コードが XIP フラッシュから実行されない場合、通常、テーブルは TCM0 の先頭 (0x100000) に配置されます。 どちらの場合も、テーブルの仮想アドレスが正しく配置されるようにするには、ベクター テーブルを専用セクションに配置し、CODE_REGION適切なアドレスに設定します。
Azure Sphere Samples リポジトリの MT3620 BareMetal サンプルは、これを行う方法を示しています。 main.c のベクター テーブルの宣言により、 section 属性が .vector_tableに設定されます。 リンカスクリプトは、CODE_REGION を TCM または XIP のいずれかの先頭に割り当て、ALIGN 属性は ELF ファイル内の text セクションのアラインメントを次のように設定します。
SECTIONS
{
.text : ALIGN(32) {
KEEP(*(.vector_table))
*(.text)
} >CODE_REGION
...
}
リアルタイムと待機時間に関する考慮事項
RTApps と高度なアプリケーションは、相互に通信しない場合でも、フラッシュ メモリにアクセスするために競合します。 その結果、XIP フラッシュから実行されている RTApp では、長く予測できない待機時間が発生する可能性があります。 更新中などのフラッシュへの書き込みには、最大で数百ミリ秒の待機時間の急増が伴う場合があります。 アプリケーションの要件に応じて、いくつかの方法でこれを管理できます。
すべてのコードとデータを TCM に配置します。 TCM から実行されるコードは、フラッシュの競合に対して脆弱ではありません。
コードをクリティカルセクションとクリティカルでないセクションに分割し、クリティカルでないコードをフラッシュから実行します。 ウォッチドッグ タイマーなどのリアルタイム要件を持つコードは、他のコードがフラッシュにアクセスするときに実行する必要はありません。 メモリ ターゲット では、TCM ではなく XIP フラッシュをターゲットにする方法について説明します。
キャッシュを使用します。 アプリケーションでは、XIP キャッシュとして最も低い 32 KB の TCM を使用できます。 この方法では、キャッシュ ミスが発生した場合のハード リアルタイムの保証は提供されませんが、すべてのコードを RAM に移動しなくても、一般的なパフォーマンスが向上します。 XIP キャッシュの構成については、"MT3620 M4 データシート" を参照してください。