1

現在、STM32CubeMx と Keil uVision を使用して STM32F407 用のアプリケーションを開発しています。組み込みシステムでの動的メモリ割り当てがほとんど推奨されていないことは知っていますが、インターネット上のスポットからスポットへと、それを支持するいくつかの議論を見つけることができます.

私の発明家魂のために、私はそれをやってみたいと思っていましたが、安全に行ってください。着信 UART メッセージ用に動的に割り当てられた fifo を作成し、メッセージ自体とその長さで構成される構造体を保持していると仮定しましょう。ただし、すべてのヒープサイズを消費したくないので、どれだけ残っているかを確認したいと思います:私の新しい(?)アイデアは、メモリの大きなチャンク(たとえば 100 文字)を一時的に割り当ててみることです-成功した場合は着信メッセージを受け入れ、そうでない場合は、ヒープが不足していることを意味し、メッセージを無視します(または受け入れて最も古いメッセージをキューから取り出します)。チェックした後、もちろん一時メモリを解放します。

いくつかの疑問が頭に浮かびます:

  1. まず第一に、それはまったく理にかなっていますか?あなたの経験に基づいて、それは便利で安全だと思いますか?
  2. ESでRAMを正確に共有しているものについての正確な情報を見つけることができなかったので(ヒープ、スタック、および揮発性変数について知っています)、私の質問は次のとおりです。上記のコントローラーに一時メモリチェッカーを選択しますか?
  3. マイクロ自体について-192kBのRAMがありますが、Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm\startup_stm32f407xx.sファイルでは、512B + 1024Bのみがヒープとスタックに割り当てられています-それはほとんどありません、百日咳を残して、揮発性変数用に 190kB を残しますか? ヒープサイズを 50kB に増やすのは賢明でしょうか? はいの場合、このファイルで直接実行しますか、それとも別の場所で実行する方が良い方法ですか?

おそらく、「安全な動的メモリ」と「埋め込み」が 1 つの投稿に含まれていると、衝撃的で眩しいと感じる人もいるでしょうが、これは実験であり、新しい地平を模索していることを覚えておいてください :) ありがとうございます。

4

2 に答える 2

1

Keil uVision では、IDE についてのみ説明します。ARM の RealView コンパイラを意味する KEil MDK-ARM を使用している場合は、__heapstats()関数を使用して正確なヒープ情報を取得できます。

__heapstats()単純に値を返すのではなく、渡された関数ポインターとファイル記述子によって促進されるフォーマットされた出力ストリームにヒープ情報を出力するという点で少し奇妙です。出力関数には、fprintf()類似のインターフェイスが必要です。もちろん使用できますが、それには stdiofprintf()を正しく再ターゲットする必要があります

たとえば、次のとおりです。

typedef int (*__heapprt)(void *, char const *, ...);
__heapstats( (__heapprt)fprintf, stdout ) ; 

たとえば、次のように出力します。

4180 bytes in 1 free blocks (avge size 4180)
1 blocks 2^11+1 to 2^12

残念ながら、テキストを出力するため、実際には必要なものを達成できません。ただし、メモリ内のデータをキャプチャして結果を解析する独自の関数を実装することもできます。もちろん、空きメモリの量と最大の割り当て可能なブロックが必ずしも同じであるとは限りません。断片化は、空きブロックの数とその平均サイズによって示されます。おそらく、少なくとも平均サイズのブロックを割り当てることができることを保証できます。

組み込みシステムでの動的割り当ての問題は、メモリの枯渇の処理に関係しており、リアルタイム システムでは、デフォルトの malloc/free 実装を使用した割り当てと解放のタイミングが非決定的です。あなたの場合、固定ブロック アロケータを使用する方がよい場合があります。このようなアロケーターを実装するには、メモリ ブロックの静的配列を作成し (または起動時にヒープから動的に割り当てることにより)、キュー、リンク リスト、またはスタック構造に各ブロックへのポインターを配置します。割り当てるには、キュー/リスト/スタックからポインターを削除し、解放するにはポインターを元に戻します。使用可能なブロック構造が空の場合、メモリが使い果たされます。それは完全に決定論的です実装のパフォーマンスと容量を簡単に監視できます。

質問 3 に関して。アプリケーションに合わせてヒープとシステム スタックのサイズを調整する必要があります。私が使用したほとんどのツールには、静的に割り当てられていない、スタックに割り当てられている、または他の目的のためにヒープに予約されていないすべての使用可能なメモリを自動的に割り当てるリンカー スクリプトがあります。ただし、MDK-ARM はデフォルトのリンカ スクリプトではそれを行わず、固定サイズのヒープを割り当てます。

リンカー マップ ファイルの概要を使用して、使用されていないスペースの量を特定し、ヒープを手動で拡張できます。私は通常、静的に割り当てられたデータの量が増加する可能性がある場合に、メンテナンスを考慮して少量の未使用スペースを残します。ただし、ある時点で。メモリ不足になり、リンカからの難解なエラー メッセージでは、ヒープが大きすぎることが明らかにならない場合があります。デフォルトのリンカ スクリプトをオーバーライドして独自のスクリプトを提供することは可能であり、ヒープのサイズを自動的に変更することは間違いなく可能です。

于 2015-06-18T09:06:47.320 に答える