Flash bellek veya SRAM bittiğinde ne yapabilirim?


28

Arduino belgelerine göre, ATmega328'in önyükleyici + yüklenen çizim için 32KB Flash belleği ve çalışma zamanı verileri için yalnızca 2KB SRAM var. ATmega2560, sırasıyla 256KB ve 8KB olmak üzere, biraz daha fazla.

Her iki durumda da, bu sınırlar, özellikle akıllı telefonlar gibi benzer büyüklükteki tüketici cihazlarıyla karşılaştırıldığında oldukça küçük görünmektedir.

Tükenirse ne yapabilirsin? Örneğin, çiziminiz çok büyükse veya çalışma zamanında çok fazla veri (dizeler gibi) işlemeniz mi gerekiyor? Flash veya SRAM'ı genişletmenin bir yolu var mı?


Bazı değişken optimizasyonu kullanmayı deneyin. Bazı farklı değişkenler burada
TheDoctor

1
Değişkenleriniz için uygun kapsamları zaten kullanmıyorsanız, derleyici, değişkenler kullanılmadığında sizin için RAM kullanımını optimize edecektir.
jippie

1
Bir Arduino ile karşılaştırılabilecek bir Teensy 3.2'yi (Teensyduino Yazılımıyla birlikte) kullanabilirsiniz. RAM / PROGMEM'in tükenmesi göz önüne alındığında, aynı zamanda yapmaya çalıştığınız şeyin Arduino'nuzu zorlama olasılığınızın da olduğu anlamına gelir. Teensy 3.2, o kadar da pahalı değil. ama var: 32bit, 72MHz (ağ!) 256KB FLASH ve 64KB RAM ve 3x UART. ATmega2560 gibi program belleği fazla değil, fakat RAM ve hız artışı yeterli.
Paul,

Yanıtlar:


30

Optimizasyon
Gömülü sistemler için düşük seviyeli programlama, bilgisayarlar ve cep telefonları gibi genel amaçlı cihazların programlanmasından oldukça farklıdır. Kaynaklar birinci sınıf olduğu için verimlilik (hız ve alan açısından) çok daha önemlidir. Bu, alanınız tükenirse yapılacak ilk şey, kodunuzun hangi bölümlerini optimize edebileceğinize bakmaktır.

Program alanı (Flash) kullanımının azaltılması açısından, kod boyutu deneyimsizseniz veya bu beceriye ihtiyaç duymayan masaüstü bilgisayarlar için programlamaya daha alışkınsanız, optimize etmek oldukça zor olabilir. Eğer kroki gerçekten ciddiye düşünün eğer o yardım etmek rağmen maalesef, her durum için çalışacak hayır 'Sihirli mermiler' yaklaşımı var ihtiyacı var. Bir özellik gerekli değilse, çıkarın.

Bazen, kodunuzun birden çok bölümünün aynı (veya çok benzer) nerede olduğunu belirlemek de yararlı olabilir. Bunları birden fazla yerden çağrılabilen yeniden kullanılabilir işlevler olarak yoğunlaştırabilirsiniz. Ancak, bazen kod yapmaya çalışıyorum unutmayın çok aslında tekrar kullanılabilen daha ayrıntılı yapma biter. Alıştırma yapma eğiliminde olan grev yapmak zor bir denge. Kod değişikliklerinin derleyici çıktısını nasıl etkilediğine bakarak biraz zaman harcamak size yardımcı olabilir.

Çalışma zamanı verileri (SRAM) optimizasyonu, alışkın olduğunuzda biraz daha kolay olma eğilimindedir. Başlangıç ​​programcıları için çok yaygın bir sorun, çok fazla küresel veri kullanıyor. Global kapsamda ilan edilen herhangi bir şey, skeçin ömrü boyunca geçerli olacak ve bu her zaman gerekli değildir. Bir değişken yalnızca bir işlev içinde kullanılıyorsa ve çağrılar arasında kalıcı olması gerekmiyorsa, onu yerel bir değişken yapın. Bir değerin işlevler arasında paylaşılması gerekiyorsa, değeri global yapmak yerine parametre olarak geçirip geçiremeyeceğinizi düşünün. Bu şekilde, SRAM'ı yalnızca gerçekten ihtiyacınız olduğunda bu değişkenler için kullanırsınız.

SRAM kullanımı için bir başka katil metin işlemedir (örneğin, Stringsınıfı kullanmak ). Genel olarak konuşursak, mümkünse String işlemlerini yapmaktan kaçınmalısınız. Onlar büyük hafıza domuzları. Örneğin, seriye çok sayıda metin çıktısı alıyorsanız, Serial.print()dize bitiştirme kullanmak yerine birden çok çağrı kullanın . Ayrıca mümkünse kodunuzdaki string değişmezlerinin sayısını azaltmaya çalışın.

Mümkünse, özyinelemeden kaçının. Özyinelemeli bir çağrı yapıldığında, yığını daha derine iner. Özyinelemeli işlevlerinizi yerine yinelemek için refactor.

EEPROM kullanın EEPROM
, yalnızca zaman zaman değişen şeylerin uzun süreli depolanması için kullanılır. Büyük listeler veya sabit veri arama tabloları kullanmanız gerekiyorsa, önceden EEPROM'da saklamayı ve yalnızca ihtiyaç duyduğunuzda gerekenleri çıkarmayı düşünün.

Açıkçası EEPROM, boyut ve hız bakımından oldukça sınırlı ve sınırlı sayıda yazma döngüsüne sahip. Veri sınırlamalarına harika bir çözüm değildir, ancak Flash veya SRAM üzerindeki yükü hafifletmek için yeterli olabilir. Aynı zamanda, SD kart gibi benzer harici depolama birimleriyle arayüz oluşturmak da oldukça mümkün.

Genişleme
Diğer tüm seçenekleri tükettiyseniz, genişletme olasılığı da olabilir. Ne yazık ki, program alanını artırmak için Flash belleği genişletmek mümkün değildir. Ancak, bir SRAM genişletmek mümkündür. Bu, artan veri boyutu pahasına kod boyutunu azaltmak için eskizinizi yeniden değerlendirebileceğiniz anlamına gelir.

Daha fazla SRAM almak aslında oldukça basittir. Bir seçenek bir veya daha fazla 23K256 cips kullanmaktır. SPI üzerinden erişilir ve bunları kullanmanıza yardımcı olacak SpiRAM kütüphanesi bulunur . Sadece 3.3V'da 5V'da çalışmadıklarına dikkat edin !

Mega kullanıyorsanız, alternatif olarak Lagrangian Noktası veya Sağlam Devrelerden SRAM genleşme kalkanlarını alabilirsiniz .


1
SRAM alan sorunları ve boş program belleği varsa, sabit verileri SRAM yerine program belleğinde de saklayabilirsiniz. Buraya veya buraya
Connor Wolf

1
EEPROM'a bir başka harika alternatif de SD kart. Birkaç IO portu kapsıyor ancak harita verisi veya benzeri bir şey için geniş bir alana ihtiyaç duyuyorsanız, PC'de özel bir programla değiştirmek ve düzenlemek kolay olabilir.
Anonim Penguen

1
İnsanlar, belleği azalıyorsa SPI SRAM'leri veya RAM genişletmelerini kullanmaya teşvik edilmemelidir. Bu sadece para kaybı. Daha büyük bir MCU seçmek daha ucuz olurdu. Ayrıca, performans çok zayıf olabilir. İlk önce bir basketbol sahası tahmininde bulunulmalı: Tahmini RAM kullanımı limite çok yakınsa, yanlış tahtayı / mikrokontrolcüyü / geliştirme platformunu seçersiniz. Elbette, iyi kullanım (dizeleri flaşa kaydetme) ve optimizasyon (bazı kütüphaneleri kullanmaktan kaçınmak) gerçek oyun değiştiriciler olabilir. Ancak bu noktada Arduino Yazılım platformunu kullanmanın hiçbir yararı görmüyorum.
sonraki kesmek

24

Kodunuzu Arduino'nuza yüklediğinizde, örneğin bir Uno söyleyin, kullanılabilir 32K'dan kaç bayt kullandığını söyleyecektir. Ne kadar flash belleğiniz var (bilgisayarın sabit diskini düşünün). Programınız çalışırken, SRAM adında olanı kullanıyor ve bundan daha az var.

Bazen programınızın bir süre bile dokunmadığınız bir noktada garip davrandığını fark edersiniz. En son değişiklikleriniz hafızanın tükenmesine neden olabilir (SRAM). Bazı SRAM'lerden kurtulma hakkında birkaç ipucu.

Dizeleri SRAM yerine Flash uygulamasında saklama.

Gördüğüm en yaygın şeylerden biri, çipin hafızasının tükenmesi, çünkü çok fazla uzun dize var.

F()Dizeleri kullanırken işlevi kullanın, böylece SRAM yerine Flash uygulamasında saklanırlar, çünkü bunlardan daha fazlasına sahipsiniz.

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

Doğru veri türlerini kullanın

Bir int(2 byte) 'dan byte(1 byte)' a geçerek bir bayt kaydedebilirsiniz . İmzasız bir bayt, size 0-255 verir, bu nedenle 255'ten daha yüksek olmayan sayılarınız varsa, bir bayt kaydedin!

Hafızamın tükendiğini nasıl bilebilirim?

Genelde, programınızın garip davrandığını gözlemler ve neyin yanlış gittiğini merak edersiniz ... Kodunun dağıldığı noktadaki hiçbir şeyi değiştirmediniz, peki ne veriyor? Hafızası tükeniyor.

Ne kadar hafıza hafızanız olduğunu söyleyen bir kaç fonksiyon var.

Mevcut bellek


F()Bir şeyin Arduino'ya özgü bir işlev olup olmadığını veya AVR kitaplıklarında mı olduğunu biliyor musunuz ? Sen de bahsetmeyi düşünebilirsin PROGMEM const ....
jippie

Ayrıca, eğer çok fazla boole ile uğraşıyorsanız, değişkenleriniz 5eg tarafından kullanılan alanı daha da azaltmak için bit yapılarını kullanabilirsiniz.
jfpoilpret

17

Başkalarının söylediklerine ek olarak (ki tamamen aynı fikirdeyim), bu adafruit makalesini bellekle ilgili okumanızı tavsiye ederim ; iyi yazılmış, hafıza hakkında birçok şeyi açıklar ve nasıl optimize edeceğinize dair ipuçları sağlar.

Okumanın sonunda, sorunuza oldukça eksiksiz bir cevap alacağınızı düşünüyorum.

Özetlemek gerekirse, 2 olası optimizasyon hedefiniz vardır (bellek problemlerinin bulunduğu yere bağlı olarak):

  • Flash (yani Program Belleği); Bunun için şunları yapabilirsiniz:
    • Ölü kodu (örneğin dahil olan ancak kullanılmayan kodları) ve kullanılmayan değişkenleri (bunlardan biri SRAM için de yardımcı olur) kaldırın
    • yinelenen kodu çözümlemek
    • bootloader'ı tamamen çıkarın (bir UNO için 0.5K ve diğer Arduino modelleri için 2 veya 4K arasında kazanabilirsiniz); Bu olsa bazı dezavantajları var
  • SRAM (yani yığın, yığın ve statik veri); Bunun için şunları yapabilirsiniz:
    • kullanılmayan değişkenleri kaldır
    • her değişkenin boyutunu optimize edin (örneğin, yalnızca int -2 bayt gerekiyorsa uzun -4 bayt kullanmayın)
    • değişkenleriniz için doğru kapsamı kullanın (ve mümkünse yığını statik veriye tercih edin)
    • arabellek boyutunu kesin asgariye indirin
    • Sabit verileri PROGMEM'e taşıyın (yani statik verileriniz Flash bellekte kalacak ve program başlangıcında SRAM'a kopyalanmayacaktır); bu aynı zamanda F()makroyu kullanabileceğiniz sabit dizeler için de geçerlidir )
    • kesinlikle gerekli değilse, dinamik dağıtımdan kaçının; belleği boşalttıktan sonra bile büzülmeyecek parçalanmış bir yığıntan kaçınacaksınız

SRAM kullanımını azaltmak için ek bir yaklaşım da açıklanmıştır (ancak, kodlama sırasında biraz ağır olduğundan ve çok verimli olmadığı için nadiren kullanılır), programınız tarafından oluşturulan verileri depolamak için EEPROM'u kullanmaktan sonra bazı durumlarda daha sonraya kadar kullanılmamasından oluşur. EEPROM'dan veri geri yüklenebildiği zaman ortaya çıkar.


1
Ölü kodu kaldırmak-- derleyici bu işlemi sizin için iyi bir şekilde yapmakta gerçekten iyidir - daha önce hiç çağrılmayan çok sayıda kodunuz varsa, bu bir fark yaratmaz. Yanlışlıkla ihtiyacınız olmayan kodu çağırırsanız, bu elbette farklı.
dethSwatch

9

Depounuz tükenirse yapmanız gereken iki şey vardır:

  • Her nasılsa kodunu "optimize et" böylece daha az depolama alanı gerekiyor; veya en azından tükettiğiniz belirli bir depolama türünden daha azını kullanır (ve hala sahip olduğunuz depolama türünden daha fazlasını kullanır). Veya,
  • Daha fazla depolama alanı ekleyin.

İlkini nasıl yapacağınızla ilgili çevrimiçi birçok ipucu var (ve insanların Arduino ile yaptıklarının büyük çoğunluğu için, yerleşik depolama "optimize etme" işleminden sonra fazlasıyla yeterli). Bu yüzden ikincisine odaklanacağım:

Flaş veya SRAM kullanan 3 şey vardır; her birinin depolama eklemek için biraz farklı bir yaklaşıma ihtiyacı var:

  • değişken depolama: sachleen'in de işaret ettiği gibi SRAM'ı genişletmek mümkündür. SRAM, FRAM ve NVSRAM , hızla değişen değişkenler için uygundur. (Prensipte değişkenleri saklamak için flaş kullanabiliyorken flaş aşınması konusunda endişelenmeniz gerekir). SPI (seri protokol), Arduino'ya bağlanmak için en kolay yoldur. SpiRAM kütüphane Mikroçip ile çalışır 23K256 seri SRAM yongası. Ramtron FM25W256 seri FRAM yongası (şimdi Cypress'e ait) ayrıca SPI kullanıyor. Cypress CY14B101 NVSRAM da SPI kullanıyor. Vb.

  • güç tekrar açıldığında hala orada olması gereken sabit veri: bu neredeyse SRAM'ı genişletmek kadar basit. Mevcut birçok harici EEPROM, FRAM, NVSRAM ve FLASH depolama aygıtı var. Şu anda MB başına en düşük maliyet SD flash kartlardır (SPI ile erişilebilmektedir). Ramtron FM25W256 (yukarıya bakın), Cypress CY14B101 (yukarıya bakın), vs. ayrıca sabit verileri de depolayabilir. Birçok genişletme kalkanında bir SD kart yuvası bulunur ve birkaç kitaplık ve öğretici de (flash) SD kartlara okuma ve yazmayı destekler. (Bunun için SRAM kullanamayız, çünkü güç kesildiğinde SRAM her şeyi unutur).

  • yürütülebilir kod: Maalesef, program alanını artırmak için Arduino's Flash belleğini genişletmek mümkün değil. Bununla birlikte, bir programcı, artan veri boyutu pahasına kod boyutunu azaltmak ve biraz daha yavaş çalışmasını sağlamak için her zaman bir çizimi yeniden etkileyebilir. (Teoride, eskizinizin tamamını yorumlanmış bir dile çevirebildiğiniz kadar ileri gidebilir, eskizinizin bu versiyonunu bir SD kartta saklayabilir ve ardından Arduino'da çalışan o dilden gelen bir tercümanı, SD kart - Arduino'dan daha ileri , bir BASIC yorumlayıcısı, bir Tom Napier Picaro yorumlayıcısı, uygulamaya özel bir dil, vb.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.