フラッシュメモリまたはSRAMが不足した場合はどうすればよいですか?


28

Arduinoの資料によると、ATmega328にはブートローダー+アップロードされたスケッチ用に32KBのフラッシュメモリがあり、ランタイムデータ用に2KBのSRAMしかありません。ATmega2560にはかなり多く、それぞれ合計256KBと8KBがあります。

どちらの場合でも、特にスマートフォンなどの同様のサイズの民生用デバイスと比較すると、これらの制限はかなり小さいように見えます。

使い果たしたら何ができますか?たとえば、スケッチが大きすぎる場合、または実行時に大量のデータ(文字列など)を処理する必要がある場合 フラッシュまたはSRAMを拡張する方法はありますか?


いくつかの変数最適化を使用してみてください。ここで
TheDoctor 14

1
変数の適切なスコープを使用します(まだ使用していない場合)。変数が使用されていない場合、コンパイラはRAMの使用を最適化します。
ジッピー14

1
実際には、Teensy 3.2(Teensyduino Softwareを使用)を使用する場合がありますが、これはArduinoに匹敵します。RAM / PROGMEMが不足していることを考えると、Arduinoをプッシュしようとしている可能性も高いことを意味します。Teensy 3.2はそれほど高価ではありません。ただし、32ビット、72MHz(wtf !?)256KBフラッシュ、64KB RAM、3x UARTを搭載しています。ATmega2560ほど多くのプログラムメモリはありませんが、RAMと速度の増加で十分です。
ポール

回答:


30

最適化
組み込みシステムの低レベルプログラミングは、コンピューターや携帯電話などの汎用デバイスのプログラミングとはまったく異なります。リソースは貴重であるため、効率(速度とスペース)ははるかに重要です。つまり、スペースが不足した場合に最初に行うことは、コードのどの部分を最適化できるかを調べることです。

プログラムスペース(Flash)の使用量を削減するという点では、経験の浅い場合や、そのスキルを必要としないデスクトップコンピューターのプログラミングに慣れている場合、コードサイズを最適化するのは非常に困難です。残念ながら、すべての状況で機能する「魔法の弾丸」アプローチはありません、スケッチが本当に必要なものを真剣に検討すると役立ちます。機能が必要ない場合は、外します。

コードの複数の部分が同じ(または非常に似ている)部分を識別することも役立つ場合があります。それらを複数の場所から呼び出すことができる再利用可能な関数に凝縮できる場合があります。ただし、コードを再利用しすぎるようにしようとすると、実際にはより冗長になることがあります。ストライキには扱いにくいバランスがあり、それは練習に伴う傾向があります。コードの変更がコンパイラの出力にどのように影響するかを調べるのに役立ちます。

ランタイムデータ(SRAM)の最適化は、慣れると少し簡単になる傾向があります。初心者プログラマーにとって非常に一般的な落とし穴は、使用するグローバルデータが多すぎることです。グローバルスコープで宣言されたものはすべて、スケッチの有効期間全体にわたって存在しますが、それは常に必要なわけではありません。変数が1つの関数内でのみ使用され、呼び出し間で持続する必要がない場合は、ローカル変数にします。関数間で値を共有する必要がある場合は、値をグローバルにするのではなく、パラメーターとして渡すことができるかどうかを検討してください。そうすれば、実際に必要な場合にのみ、これらの変数にSRAMを使用できます。

SRAMを使用するもう1つの理由は、テキスト処理です(Stringクラスの使用など)。一般的に、可能な場合は文字列操作を行わないでください。彼らは大規模なメモリ豚です。たとえば、大量のテキストをシリアルに出力する場合Serial.print()は、文字列の連結を使用する代わりに、複数の呼び出しを使用します。また、可能であれば、コード内の文字列リテラルの数を減らしてください。

可能であれば再帰も避けてください。再帰呼び出しが行われるたびに、スタックが1レベル深くなります。代わりに、再帰関数をリファクタリングして反復型にします。

EEPROMの使用EEPROM
は、たまにしか変更されないものの長期保存に使用されます。固定データの大きなリストまたはルックアップテーブルを使用する必要がある場合は、事前にEEPROMに保存し、必要なときに必要なものだけを引き出すことを検討してください。

EEPROMのサイズと速度は明らかに制限されており、書き込みサイクルの数は限られています。データの制限に対する優れたソリューションではありませんが、フラッシュやSRAMの負担を軽減するには十分かもしれません。また、SDカードなどの同様の外部ストレージとインターフェイスすることもできます。

拡張
他のすべてのオプションを使い果たした場合、拡張の可能性があります。残念ながら、プログラムのスペースを増やすためにフラッシュメモリを拡張することはできません。ただし、SRAMを拡張すること可能です。これは、データサイズを増やすことを犠牲にして、コードサイズを減らすためにスケッチをリファクタリングできることを意味します。

より多くのSRAMを取得することは、実際にはかなり簡単です。1つのオプションは、1つ以上の23K256チップを使用することです。それらはSPI経由でアクセスされ、それらを使用するのに役立つSpiRAMライブラリがあります。5V ではなく 3.3Vで動作することに注意してください!

Megaを使用している場合は、ラグランジュポイントまたはRugged CircuitsからSRAM拡張シールドを入手することもできます。


1
SRAMスペースに問題があり、プログラムメモリが空いている場合は、SRAMではなくプログラムメモリに定数データを保存することもできます。ここまたはここを
コナーウルフ

1
EEPROMのもう1つの優れた代替手段はSDカードです。いくつかのIOポートを使用しますが、マップデータなどに大きなスペースが必要な場合は、PCのカスタムプログラムで簡単に交換および編集できます。
匿名のペンギン

1
メモリが不足している場合は、SPI SRAMまたはRAM拡張を使用することは推奨されません。それは単なるお金の無駄です。より大きなMCUを選択する方が安くなります。また、パフォーマンスが非常に低い可能性があります。最初に概算を行う必要があります。推定RAM使用量が制限に近すぎる場合、間違ったボード/マイクロコントローラー/開発プラットフォームを選択しています。確かに、適切な使用(フラッシュに文字列を保存する)と最適化(一部のライブラリの使用を避ける)は、真のゲームチェンジャーになる可能性があります。ただし、現時点では、Arduino Softwareプラットフォームを使用するメリットはありません。
ネクストハック

24

Arduinoにコードをアップロードすると、たとえばUnoのように、使用可能な32Kのうち何バイトを使用するかがわかります。それはあなたが持っているフラッシュメモリの量です(コンピューターのハードディスクを考えてください)。プログラムの実行中は、SRAMと呼ばれるものを使用しているため、使用できるものははるかに少なくなります。

しばらく触れていない時点で、プログラムの動作がおかしくなることがあります。最新の変更により、メモリ(SRAM)が不足する可能性があります。SRAMを解放する方法に関するいくつかのヒントを以下に示します。

SRAMの代わりにフラッシュに文字列を保存します。

私が見た最も一般的なものの1つは、長い文字列が多すぎるためにメモリが不足していることです。

F()文字列を使用するときは、SRAMではなくFlashに保存されるように文字列を使用するときに、この関数を使用してください。

Serial.println(F("This string will be stored in flash memory"));

適切なデータ型を使用する

int(2バイト)からbyte(1バイト)に切り替えることでバイトを節約できます。符号なしバイトは0から255を与えるので、255を超えない数字がある場合は、バイトを節約してください!

メモリが不足していることを知るにはどうすればよいですか?

通常、プログラムの動作がおかしいのを観察し、何が間違っているのか疑問に思うでしょう...コードが混乱している箇所の近くでコードを何も変更していません。メモリ不足です。

使用可能なメモリの量を示す関数がいくつかあります。

使用可能なメモリ


F()ものがArduino固有の機能なのか、それともAVRライブラリーなのかを知っていますか?言及することも検討できPROGMEM const ...ます。
ジッピー14

また、ビット構造を使用して、多くのブール値を扱う場合、変数で使用されるスペースをさらに削減できます。
jfpoilpret 14

17

他の人が言ったこと(完全に同意します)に加えて、記憶に関するこのadafruitの記事を読むことをお勧めします。よく書かれており、メモリに関する多くのことを説明し、メモリを最適化する方法のヒントを提供します。

読書の終わりに、あなたはあなたの質問に対する非常に完全な答えを得ると思います。

要約すると、2つの可能な最適化ターゲットがあります(メモリの問題の場所に応じて):

  • フラッシュ(プログラムメモリ); このため、次のことができます。
    • デッドコード(含まれているが使用されていないコード)および未使用の変数(SRAMにも役立つ)を削除する
    • 重複コードを除外する
    • ブートローダーを完全に削除します(UNOの場合は0.5Kから、他のArduinoモデルの場合は2または4Kを獲得できます)。しかし、これにはいくつかの欠点があります
  • SRAM(つまり、スタック、ヒープ、および静的データ)。このために次のことができます。
    • 未使用の変数を削除する
    • 各変数のサイズを最適化する(たとえば、-4バイトのlongを使用しない-int -2バイトのみが必要な場合)
    • 変数に適切なスコープを使用します(可能な場合は静的データよりもスタックを優先します)
    • バッファのサイズを厳密な最小値に減らす
    • 定数データをPROGMEMに移動します(つまり、静的データはフラッシュメモリに残り、プログラムの開始時にSRAMにコピーされません)。F()マクロを使用できる定数文字列にも適用されます)
    • 絶対に必要でない場合は、動的割り当てを避けます。メモリを解放した後でも縮小しない可能性のある断片化されたヒープを回避します

SRAMの使用量を削減するための追加のアプローチも説明されています(ただし、コーディング時に少し重く、あまり効率的ではないため、めったに使用されません)。 EEPROMからデータを読み戻すことができる場合に発生します。


1
デッドコードの削除-コンパイラはこれを処理するのに非常に優れています-呼び出されていないコードがたくさんある場合、違いはありません。必要のないコードを誤って呼び出した場合は、当然異なります。
dethSwatch

9

ストレージが不足した場合、2つのことを行う必要があります。

  • 何らかの方法でコードを「最適化」して、必要なストレージを減らします。または、少なくとも、使い果たした特定の種類のストレージをより少なく使用します(そして、まだ十分な量のより多くの種類のストレージを使用します)。または、
  • ストレージを追加します。

最初の方法については、オンラインで多くのヒントがあります(そして、Arduinoを使用して行う大部分のことについては、組み込みストレージは「最適化」後は十分すぎるほどです)。したがって、2番目に焦点を当てます。

フラッシュまたはSRAMを使い果たすものは3つあります。ストレージを追加するには、それぞれ少しずつ異なるアプローチが必要です。

  • 変数ストレージ:Sachleenがすでに指摘したように、SRAMを拡張することが可能です。 SRAM、FRAM、およびNVSRAMはすべて、急速に変化する変数に適しています。(原則として、変数を保存するためにフラッシュを使用できますが、フラッシュの摩耗を心配する必要があります)。SPI(シリアルプロトコル)は、Arduinoに接続するのが最も簡単です。SpiRAMライブラリは、マイクロチップと連動23K256シリアルSRAMチップ。ラムトロンFM25W256シリアルFRAMの(現在はサイプレスが所有)チップはSPIを使用しています。Cypress CY14B101 NVSRAMもSPIを使用します。等。

  • 次回の電源投入時にも必要な一定のデータ:これは、SRAMを拡張するのとほぼ同じくらい簡単です。多くの外部EEPROM、FRAM、NVSRAM、およびフラッシュストレージデバイスが利用可能です。現在、MBあたりの最低コストはSDフラッシュカード(SPI経由でアクセス可能)です。Ramtron FM25W256(上記参照)、Cypress CY14B101(上記参照)なども定数データを保存できます。多くの拡張シールドにはSDカードスロットが含まれており、いくつかのライブラリチュートリアルは(フラッシュ)SDカードの読み取りと書き込みをサポートしています。(SRAMは電源が切れるとすべてを忘れるので、これにSRAMを使用することはできません)。

  • 実行可能コード:残念ながら、プログラムスペースを増やすためにArduinoのフラッシュメモリを拡張することはできません。ただし、プログラマはいつでもスケッチをリファクタリングしてコードサイズを縮小できますが、データサイズが大きくなり、実行速度が若干遅くなります。(理論的には、スケッチ全体を何らかの解釈言語に翻訳し、そのバージョンのスケッチをSDカードに保存し、Arduinoで実行されるその言語のインタープリターを記述して、 SDカード-ArduinoのForth、BASICインタープリター、Tom Napier Picaroインタープリター、アプリケーション固有の言語など)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.