2016-03-30 18 views
0

STM32F417 MCUで動作するように外付けRAMを取得しようとしていて、私たちは仕事で論文作成プロジェクトを行っています。 このプロジェクトでは、本当にリソースが不足していて、内部RAMだけでは十分ではないものを試しています。外部RAMにFreeRTOSを実行しているSTM32F4

この問題を解決するにはどうすればよいですか。

現在のアプローチは、リンクスクリプト(gnu ld)のRAMアドレスを外部RAMのアドレスに置き換えることです。

このアプローチの問題点は、初期化中に、FSMCが初期化されていないために内部RAM上でチップを実行する必要があることです。

pvPortMallocが実行されるとただちにハードフォールトが発生し、おそらく偽のアドレスを参照していないため、変数がシステム初期化時に正しく初期化されていないことがわかります。内部RAMはまったく使用されていません)。

これはあいまいな質問ですが、Cortex M4 MCUの外付けRAM、具体的にはSTM32F4でコードを実行する際の一般的なアプローチは何ですか?

おかげ

+0

外付けSRAMに正確に配置する必要はありますか?大きなデータ構造ですか?すべての読み書き可能なデータ? SRAMから実行するにはコードが必要ですか?それともフラッシュに常駐できますか? –

+0

当初の考えは、すべてを外部のラムに置くのが最も簡単なことでした。実際にMCUにとって大きすぎる暗号鍵と計算があります。しかし、何らかの理由で、とにかくそれを行う必要があります。コードはフラッシュからちょうど良いので、私はスタックとヒープを意味するすべてのものから実行できます。 – evading

+0

どのバージョンのFreeRTOSヒープ管理ソースファイル(heap_1.c、heap_2.cなど)を使用していますか?私はFreeRTOSが(pvPortMallocを使って)ヒープにタスクスタックを割り当てていると思うので、SRAMに移動する必要があるのは唯一のことかもしれませんが、使用しているヒープ_ *。cのバージョンによって大きく変わります –

答えて

2

FreeRTOSは、スタックとヒープの管理に単一の大きなメモリ領域を定義して使用します。これは単純にバイト配列であり、そのサイズはconfigTOTAL_HEAP_SIZEシンボルで指定され、FreeRTOSConfig.hになります。 FreeRTOSは、pvPortMalloc関数を使用してこのメ​​モリ領域にタスクスタックを割り当てます。したがって、ここでの主な目標は、FreeRTOSヒープ領域を外部SRAMに配置することです。

FreeRTOSヒープメモリ領域は、変数がucHeapと呼ばれ、(標準ライブラリのmallocを使用していますheap_3.cを除いて、それが任意のカスタムヒープ領域を定義していません)heap_*.cで定義されています。コンパイラ拡張を使用してセクションを設定することができます。 GCCの場合、それは次のようになります:

static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ((section (".sram_data"))); 

このカスタムセクションを外部SRAMに配置するようにリンカスクリプトを設定する必要があります。これを行うにはいくつかの方法があり、使用しているツールチェーンに依存します。これを行うにはGCC一つの方法は、SRAMとSRAM領域に追加する".sram_data"ためのセクションのためのメモリ領域を定義するだろうと、のようなもの:

MEMORY 
{ 
    ... 
    /* Define SRAM region */ 
    sram : ORIGIN = <SRAM_START_ADDR>, LENGTH = <SRAM_SIZE> 
} 

SECTIONS 
{ 
    ... 
    /* Define .sram_data section and place it in sram region */ 
    .sram_data : 
    { 
     *(.sram_data) 
    } >sram 
    ... 
} 

は、これは一方で、外部SRAMにucHeapエリアを配置します他のすべてのテキストセクションとデータセクションは、デフォルトのメモリ領域(内蔵フラッシュとラム)に配置されます。

いくつかの注意事項:

  • あなたが前に任意のFreeRTOS機能(のようなxTaskCreate)を呼び出すにSRAMコントローラ/ FSMCを初期化してください
  • あなたが作業を開始すると、すべてのスタックに割り当てられた変数はに配置されますucHeap(つまりext RAM)ですが、グローバル変数は引き続き内部RAMに割り当てられます。それでも内部RAMサイズの問題がある場合は、コンパイラの拡張機能(ucHeapの場合)を使用して".sram_section"に配置する他のグローバル変数を設定できます。
  • コードで動的メモリ割り当てを使用する場合は、pvPortMalloc/vPortFree stdlib malloc/free。これは、異なるメモリを使用してpvPortMalloc/vPortFreeでダイナミックタスクの作成/削除とメモリ割り当てをたくさん行っている場合、pvPortMalloc/vPortFreeのみがext RAMのucHeap領域を使用します(そして、スレッドセーフです。プラスです)
  • ブロックサイズは、heap_2.cの代わりにheap_4.cを使用することを検討してください。いくつかの異なるブロックサイズを使用する場合heap_4.c

別の(そしておそらくより簡単な)単一の大きなブロックに隣接する空きメモリブロックを結合することが可能である一方heap_2.c溶液がポインタとしてucHeap変数を定義することで、メモリの断片化の問題があります

static uint8_t * const ucHeap = <SRAM_START_ADDR>; 

これは特別なリンカースクリプト編集を必要とせず、すべてをデフォルトセクションに配置することができます。このソリューションでは、リンカはヒープ用のメモリを明示的に予約しないので、(ヒープ領域がext RAMに適合しないなどの)潜在的に有用な情報/エラーが緩和されることに注意してください。しかし、外付けRAMにucHeapしかなく、外付けRAMサイズよりも小さいconfigTOTAL_HEAP_SIZEがあればうまくいくかもしれません。

1

アプリケーションがいずれかの変数が中に配置される部分に応じて、ゼロにクリア、または非ゼロ値に初期化することによりデータを初期化しようとするまで通常の使用を開始main()が呼び出される前に実行される実行時モデルです。だからあなたのようなものを持っている:

1)リセットベクタは、initコード 2)Cのランタイム初期化コードは、初期化を呼び出します 3)Cランタイム初期化コードを呼び出す変数メイン()

あなたは場所へのリンカーを使用している場合外部RAMに変数がある場合は、その初期化が行われる前にRAMにアクセスできるようにする必要があります。そうしないと、ハードフォールトが発生します。したがって、あなたのためにシステムをセットアップしてから、あなたのアプリケーションを起動するブートローダを持っている必要があります。または、単に起動コードを編集して次のことを行うだけです:

1) 2)>>> Cランタイム初期化コードは外部RAMを構成します< < < 3)Cランタイム初期化コード初期化変数 4)Cランタイム初期化コードはmain()を呼び出します。

RAMにアクセスしようとすると、そのように使用できます。

しかし、外部RAMにFreeRTOSヒープを置いておきたい場合は、initコードをそのままにして、適切なヒープ実装(基本的に大きな静的配列を宣言するだけではない)を使用することができます。たとえば、heap_5を使用する場合、ヒープinitは、ヒープとして静的に宣言するのではなく、ヒープとして使用するRAMを記述するだけなので、割り当てが実行される前にヒープinit関数が呼び出されるようにするだけです。

関連する問題