2.11.4. __user_initial_stackheap()

__user_initial_stackheap() は、初期スタックおよびヒープの位置を返します。

RVCT v2.x 以前のバージョンでは、__user_initial_stackheap() のデフォルトの実装では、シンボル Image$$ZI$$Limit の値を使用していました。 リンカによって分散ロード記述ファイルが使用される場合(--scatter コマンドラインオプションが指定されている場合)には、このシンボルは定義されません。このため、分散ロード記述ファイルを使用する場合は __user_initial_stackheap() を再実装する必要があります。再実装しないと、リンク手順が正常に実行されません。

RVCT v3.x では、ライブラリに __user_initial_stackheap() が追加実装されており、分散ロード記述ファイルの情報から最適な実装を自動的に選択できます。 つまり、分散ロードファイルを使用する場合、この関数を再実装する必要はありません。 分散ロード記述ファイルの使用を参照して下さい。

Note

__user_initial_stackheap() を再実装すると、すべてのライブラリ実装がオーバーライドされます。 そのため、既存のアプリケーションは何も変更せずに機能します。

構文

__value_in_regs  struct __initial_stackheap __user_initial_stackheap(unsigned R0, unsigned SP, unsigned R2);

使用法

__user_initial_stackheap() は、以下を返します。

  • r0 のヒープベース

  • r1、つまりスタック領域の最上位アドレスのスタックベース

  • r2 のヒープリミット

  • r3、つまりスタック領域の最下位アドレスのスタックリミット

この関数を再実装する場合には、以下のガイドラインに従う必要があります。

  • 88 バイトを超えるスタックは使用しない

  • r12ip)以外のレジスタは更新しない

  • ヒープ内は常に 8 バイト境界の整列を守る

デフォルトの単一領域によるモデルでは、r2r3 の値が無視され、 r0r1 のすべてのメモリをヒープに使用できます。 2 つの領域によるモデルでは、ヒープリミットは r2 によって設定され、スタックリミットは r3 によって設定されます。

__main() が呼び出されたときの spr13)の値は、r1 に引数として渡されます。 セミホスティング SYS_HEAPINFO を使用する __user_initial_stackheap() のデフォルトの実装は、モジュール sys_stackheap.o 内のライブラリによって提供されます。

sp を実行環境から引き継ぎ、ヒープをもたない __user_initial_stackheap() のバージョンを作成するには、r0r2r3 の値を設定して戻ります。 詳細については、__user_setup_stackheap()を参照して下さい。

rt_misc.h 内の __initial_stackheap の定義は以下のとおりです。

struct __initial_stackheap
{
    unsigned heap_base, stack_base, heap_limit, stack_limit;
}; 

Note

stack_base の値は 0x1 で、フル下降スタックを使用しているため、スタックで使用される最上位アドレスよりも大きくなります。

この関数の再実装の例については、サンプルディレクトリを参照して下さい。

戻り値

r0r3 に返される値は、単一領域によるメモリモデルと 2 つの領域によるメモリモデルのいずれを使用しているかで異なります。

単一領域による場合

r0,r1)は 1 つのスタックおよびヒープ領域となります。r1r0 よりも大きな値を保持します。 r2r3 は無視されます。

2 つの領域による場合

r0, r2)は初期ヒープ、(r3, r1)は初期スタックとなります。r2r0 以上の値を保持し、r3r1 よりも小さい値を保持します。

分散ロード記述ファイルの使用

__user_initial_stackheap() のデフォルトの実装では、シンボル Image$$ZI$$Limit の値が使用されます。 このシンボルは、リンカで分散ロード記述ファイルが使用される場合は、定義されません。 ただし、C ライブラリには、分散ロード記述ファイル内の情報を使用して利用できる別の実装があります。

Note

__user_initial_stackheap() を再実装すると、すべてのライブラリ実装がオーバーライドされます。

単一領域によるモデルの自動選択

分散ロード記述ファイルに特別な実行領域 ARM_LIB_STACKHEAP を定義します。 この領域には EMPTY 属性があります。

そのため、ライブラリでは __user_initial_stackheap() の実装が選択され、この領域がヒープとスタックの結合領域として使用されます。 その結果、シンボル Image$$ARM_LIB_STACKHEAP$$Base および Image$$ARM_LIB_STACKHEAP$$ZI$$Limit の値が使用されます。

2 つの領域によるモデルの自動選択

分散ロード記述ファイルに 2 つの特別な実行領域 ARM_LIB_HEAPARM_LIB_STACK を定義します。 これらの領域には EMPTY 属性があります。

この定義によって、ライブラリでは、Image$$ARM_LIB_HEAP$$BaseImage$$ARM_LIB_HEAP$$ZI$$LimitImage$$ARM_LIB_STACK$$BaseImage$$ARM_LIB_STACK$$ZI$$Limit のシンボルの値を使用する、__user_initial_stackheap() の実装が選択されます。

Example 2.23 は、 ARM_LIB_HEAPARM_LIB_STACK の両方を定義する分散ロード記述ファイルの例を示しています (この例は、メインサンプルディレクトリ install_directory\RVDS\ExamplesCortex-M3.scat という名前で収録されています)。

Example 2.23. ARM_LIB_HEAP と ARM_LIB_STACK の分散ロード記述

FLASH_LOAD 0x0000 0x00200000
{
  VECTORS +0 0x400
  {
    * (:gdef:__vectab_stack_and_reset, +FIRST)
    ; Additional region for other vectors would be added here
  }

  ;; Maximum of 256 exceptions (256*4bytes == 1024 == 0x400)
  CODE 0x400 FIXED
  {
    * (+RO)
  }

  DATA 0x20000000 0x00200000
  { 
    * (+RW, +ZI)
  }

  ;; Heap starts at 1MB and grows upwards
  ARM_LIB_HEAP 0x20100000 EMPTY 0x100000-0x8000
  {
  }

  ;; Stack space starts at the end of the 2MB of RAM
  ;; And grows downwards for 32KB
  ARM_LIB_STACK 0x20200000 EMPTY -0x8000
  {
  }
}

Example 2.23__vectab_stack_and_reset は、特別なライブラリセクションで、Cortex-M3 が組み込まれたアプリケーション用に、アドレス 0 から始まるベクタテーブルに sppc の初期値を配置する便利な方法が収録されています。sp は、ARM_LIB_STACKHEAP(単一領域によるモデル用)または ARM_LIB_STACK(2 つの領域によるモデル用)のいずれか該当する方から適切に初期化されます。

エラーメッセージ

分散ファイルを使用する場合に、特別な領域名の指定も __user_initial_stackheap() の再実装もされない場合には、ライブラリで以下のエラーメッセージが生成されます。

Copyright © 2007 ARM Limited. All rights reserved.ARM DUI 0349AJ
Non-Confidential