メモリと待機時間に関する考慮事項を管理する

このトピックでは、MT3620 チップで実行されるリアルタイム アプリケーションの基本的なメモリ使用量と待機時間に関する考慮事項について説明します。

メモ

メモリ構成または DMA の詳細については、 MediaTek から発行された MT3620 データシートを参照してください。質問が残っている場合は、電子メールで Avnet から "MT3620 M4 データシート" を Azure.Sphere@avnet.com要求できます。

リアルタイム コアのメモリ レイアウト

次の表は、リアルタイム コアで使用可能なメモリをまとめたものです。

メモリの種類 ベース アドレス
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 を別のアプリケーションと共有することはできません。

Execute-In-Place (XIP) フラッシュ メモリは、高度なアプリケーションと共有されます。 フラッシュの XIP マッピングへのウィンドウは、アドレス 0x10000000の各コアに表示されます。 アプリケーションの ELF ファイルに次のプロパティを持つセグメントが含まれている場合、OS はアプリケーションを起動する前に XIP マッピングを構成します。

  • 読み込みアドレス (プログラム ヘッダーの VirtAddr 列で指定) は、0x10000000
  • アプリケーションの ELF ファイルに収まるファイル オフセットとサイズ (プログラム ヘッダーの FileSiz フィールドと MemSiz フィールドで指定)

これらのプロパティを持つプログラム ヘッダーがアプリケーションの ELF ファイルに存在する場合、セグメントが0x10000000に表示されるように XIP ウィンドウが配置されます。 ファイルは複数の XIP セグメントを持つ必要があり、0x10000000を指す必要があります。他のアドレスを指定することはできません。

ELF デプロイ

RTApp イメージは ELF ファイルである必要があります。 ELF イメージは Azure Sphere イメージ パッケージにラップされ、アプリケーションとしてデプロイされます。 アプリケーションを読み込むため、Azure Sphere OS はリアルタイム コアで実行される ELF ローダーを起動します。 ローダーは、ELF ファイル内の各 LOAD セグメントを処理し、プログラム ヘッダーの仮想アドレスによって示されるメモリの種類に読み込みます。

アプリケーションのプログラム ヘッダーを表示するには、GNU Arm Embedded Toolchain の一部である (小文字の L) を使用 arm-none-eabi-readelf.exe -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 サンプルは、これを行う方法を示しています。 メイン.c のベクター テーブルの宣言は、その属性を section.vector_table設定します。 リンカー スクリプト エイリアスは TCM または XIP の先頭にCODE_REGIONし、ALIGN 属性は ELF ファイル内のテキスト セクションの配置を次のように設定します。

SECTIONS
{
    .text : ALIGN(32) {
        KEEP(*(.vector_table))
        *(.text)
    } >CODE_REGION
...
}

リアルタイムと待機時間に関する考慮事項

RTApps と高レベルアプリケーションは、相互に通信しない場合でも、フラッシュ メモリへのアクセスを求めて競合します。 その結果、XIP フラッシュから実行されている RTApps では、高く予測できない待機時間が発生する可能性があります。 更新中などのフラッシュへの書き込みには、最大数百ミリ秒の待機時間の急増が伴う場合があります。 アプリケーションの要件に応じて、これをいくつかの方法で管理できます。

  • すべてのコードとデータを TCM に配置します。 TCM から実行されるコードは、フラッシュの競合に対して脆弱ではありません。

  • コードをクリティカル セクションと非クリティカル セクションに分割し、フラッシュから重要でないコードを実行します。 ウォッチドッグ タイマーなどのリアルタイム要件を持つコードは、他のコードがフラッシュにアクセスするときに実行する必要はありません。 メモリ ターゲット では、TCM ではなく XIP フラッシュをターゲットにする方法について説明します。

  • キャッシュを使用します。 アプリケーションでは、XIP キャッシュとして最も低い 32 KB の TCM を使用できます。 この方法では、キャッシュ ミスが発生した場合のハード リアルタイム保証は提供されませんが、すべてのコードを RAM に移動することなく、一般的なパフォーマンスが向上します。 XIP キャッシュの構成については、「MT3620 M4 データシート」を参照してください。